/* ══════════════════════════════════════════════════════════════════
   FARAH STUDIO · „DIE LINIE"
   Eine Haarlinie läuft von unter dem Logo bis ans Seitenende und
   verändert bei jeder Leistung ihre Form. Am Schluss legt sie sich
   als Unterstrich unter das Logo — der Kreis geht zu.
   ══════════════════════════════════════════════════════════════════ */


/* ── Schriften · lokal, kein CDN ─────────────────────────────────── */

@font-face {
  font-family: 'Schibsted Grotesk';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('assets/fonts/schibsted-grotesk-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: 'Schibsted Grotesk';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('assets/fonts/schibsted-grotesk-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;
}


/* ── Marken-Token ────────────────────────────────────────────────── */

:root {

  /* ── DIE TYPSKALA ──────────────────────────────────────────────
     Acht Stufen, mehr nicht (DESIGN-PRINZIPIEN § 6). Vorher waren es
     39 verschiedene clamp()-Tripel, darunter Paare wie 40 und 41,6 px
     oder 86,4 und 96 px — solche Beinah-Dubletten lesen sich nicht als
     Hierarchie, sondern als Schlamperei.

     NUR AUS DIESER LISTE WAEHLEN. Wer eine neue Groesse braucht,
     braucht in Wahrheit fast immer eine der acht.

     ACHTUNG MINIMALWERT: § 6 zaehlt die Maximalwerte, aber am Handy regiert
     der erste Wert der clamp(). Beim ersten Zusammenlegen ist der Fliesstext
     auf Impressum und Datenschutz von 14,4 auf 12,8 px gerutscht — 5000
     Zeichen Rechtstext, kleiner geworden. Deshalb steht --s-text unten bei
     .9rem = 14,4 px und nicht tiefer. Wer das senkt, senkt die Lesegroesse
     der Rechtstexte mit.
  */
  --s-fein: clamp(.66rem, 1.7vw, .7rem);            /*  11.2 px — Marken, Meta, Kleinstes */
  /* Untergrenze am 24.08. von .56 auf .66 rem angehoben. Gemessen über sechs
     Seiten und sieben Breiten stand die Stufe auf schmalen Schirmen bei 9,0 px —
     Impressum, Datenschutz, „KI-generiert“ und die Anschrift im Fuss. Das ist
     keine Kleinschrift mehr, das ist unlesbar. Jetzt nie unter 10,6 px. */
  --s-klein: clamp(.7rem, 1.9vw, .78rem);           /*  12.5 px — Aufzaehlungen, Hinweise, Zeilen unter Bildern */
  /* Ebenso: Untergrenze von .62 auf .7 rem, also nie unter 11,2 px. */
  --s-text: clamp(.9rem, 2.35vw, .96rem);           /*  15.4 px — Fliesstext */
  --s-satz: clamp(1rem, 2.9vw, 1.25rem);            /*  20.0 px — hervorgehobener Satz, Preise, Vorspann */
  --s-karg: clamp(1.05rem, 3.6vw, 1.75rem);         /*  28.0 px — der karge Satz zwischen den Abschnitten */
  --s-titel: clamp(1.35rem, 4.6vw, 2.3rem);         /*  36.8 px — Gruppentitel, Einladung, Paketpreis */
  --s-haupt: clamp(1.9rem, 6.6vw, 3.875rem);        /*  62.0 px — Seitentitel, Kapitelfrage */
  --s-schau: clamp(2.1rem, 8.4vw, 5.4rem);          /*  86.4 px — Display: die grossen Ueberschriften und Zahlen */
  --s-riese: clamp(8rem, 26vw, 24rem);              /* 384.0 px — die Ziffer als Zeichnung — keine Textstufe */

  --tinte:  #111;
  --papier: #faf9f7;
  --leise:  #6a6a6a;

  /* ── Der eine Farbknall · PIGMENT-BORDEAUX ─────────────────────────
     Nicht aus einer Palette gewählt, sondern aus ihrem eigenen Material:
     das ist der Ton der Permanent-Make-up-Pigmente, mit denen sie Powder
     Brows und Powder Lips setzt. Tief genug, dass er neben Tinte auf
     Papier nicht nach Standard-Beauty-Rosa aussieht — und rot genug,
     dass die Pfeile eine Richtung bekommen statt nur eine Form.

     Kontrast auf Papier gemessen: 11,45 : 1 (WCAG AA verlangt 4,5 : 1
     für Fliesstext). Er könnte also Text tragen. Er tut es nicht: er
     wirkt an genau vier Stellen, und keine davon ist eine Überschrift
     oder ein Preis —
       · die Pfeile (jede Richtungsangabe der Seite, auf allen Seiten)
       · die Refrain-Zeile am Schluss (.wandel)
       · der Fokusring
       · der Unterstrich beim Überfahren eines Links
     Auf der schwarzen Schlussbühne wird er auf Papierton überschrieben
     (siehe .schluss): Bordeaux auf Tinte hat nur 1,57 : 1. */
  --akzent: #6b1030;

  /* Raster */
  --rand:  clamp(20px, 5vw, 88px);      /* Seitenluft                       */
  --rail:  clamp(44px, 11vw, 120px);    /* Breite der Linienspur            */
  --luft:  clamp(18px, 5vw, 80px);      /* Abstand Spur → Text              */
  --spur:  calc(var(--rail) + var(--luft));
  --kluft: clamp(24px, 5vh, 60px);      /* Abstand Logo → Linienfortsetzung */

  /* Höhe der Kopfleiste — der Auftakt hält genau soviel Luft frei */
  --leiste: clamp(30px, 4.6vh, 44px);

  /* Anteil der Logohöhe, auf dem die beiden Haarlinien des Logos sitzen.
     Aus der Bilddatei ausgemessen (Zeile 548,5 von 596). */
  --hf: .92;

  /* Motiv-Geometrie: alle Motiv-SVGs sind 500 breit, die Spur liegt bei x=60 */
  --motiv-w: clamp(140px, 34vw, 340px);
  --anker: .12;

  --schwung: cubic-bezier(.16, 1, .3, 1);
}


/* ── Grundlage ───────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html, body {
  overflow-x: clip;
}

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--papier);
  color: var(--tinte);
  font-family: 'Schibsted Grotesk', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-weight: 500;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, p, figure, ul, li, blockquote { margin: 0; padding: 0; }
ul { list-style: none; }
img { display: block; max-width: 100%; height: auto; }

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--akzent);
  outline-offset: 6px;
}

.seite {
  padding-inline: var(--rand);
  overflow-x: clip;   /* randbrechende Ziffern und der Schlussstrich enden am Seitenrand */
}


/* ══ KOPFLEISTE ══════════════════════════════════════════════════════
   Ausdrücklich KEINE Navigationsleiste: die Seite hat keine Menüpunkte,
   sie hat einen Zweck — anrufen. Oben läuft daher nur die Haarlinie des
   Konzepts mit. Sie wächst beim Scrollen von links nach rechts, und an
   ihrem Ende steht die Rufnummer. Kein Kasten, kein Rahmen, kein
   Schatten, keine Fläche mit eigener Farbe.

   Der Grund ist exakt der Papierton der Seite. Am Auftakt ist die Leiste
   deshalb unsichtbar — man sieht nur den kurzen Linienstummel oben links.
   Erst wenn Inhalt darunterläuft, zeigt sie sich als schmale Papierkante,
   und die wachsende Linie erklärt, wo diese Kante herkommt.

   Zwei Dinge sind absichtlich so gelöst:
   · Die Linie sitzt an der UNTERkante der Leiste. Sie ist die Grenze
     zwischen Kante und Inhalt und damit derselbe Strich, der auch das
     Rückgrat der Seite bildet.
   · Die schwarze Schlussbühne läuft ÜBER die Leiste hinweg (z-index).
     Am Seitenende bleibt das schwarze Bild ungestört — dort steht die
     Nummer sowieso im Terminkapitel darüber.

   Ein Blendmodus (difference) stand hier zuerst und war eleganter, fiel
   aber durch: über mittelgrauen Stellen der Schwarzweiss-Fotos war die
   Nummer nicht mehr lesbar.                                             */

.oberlinie {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 20;
  height: var(--leiste);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: clamp(14px, 3.4vw, 40px);
  padding-inline: var(--rand);
  pointer-events: none;
  background: var(--papier);
  color: var(--tinte);
}

.oberlinie-zug {
  position: absolute;
  inset: auto 0 0 0;
  border-top: 1px solid currentColor;
  transform-origin: left center;
}

.oberlinie-ruf {
  pointer-events: auto;
  font-size: var(--s-fein);
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  text-decoration: none;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  border-bottom: 1px solid transparent;
  padding-bottom: .2em;
}
.oberlinie-ruf > span { color: var(--leise); }
.oberlinie-ruf:hover { border-bottom-color: currentColor; }

/* Der zweite Weg in der Leiste: zur Preisseite (und dort zurück).
   Keine Navigationsleiste — dieselbe Zurückhaltung wie die Nummer, nur
   leiser gesetzt, damit die Rufnummer das Ende der Linie bleibt.
   Auf schmalen Schirmen fällt „Leistungen &" weg; „Preise" trägt allein. */
.oberlinie-weg {
  pointer-events: auto;
  font-size: var(--s-fein);
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  color: var(--leise);
  border-bottom: 1px solid transparent;
  padding-bottom: .2em;
}
.oberlinie-weg:hover,
.oberlinie-weg:focus-visible { color: var(--tinte); border-bottom-color: currentColor; }
/* Der Pfeil dieses Weges trug vorher color:inherit und war damit grau —
   die einzige Ausnahme von der Pfeilfarbe auf der ganzen Seite. Solange der
   Akzent gleich Tinte war, fiel das niemandem auf. Mit dem Bordeaux wäre es
   ein grauer Pfeil neben einem farbigen in derselben Leiste. Die Ausnahme
   ist deshalb weg: alle Pfeile aller Seiten sind Akzent, leise bleibt dieser
   Weg über die Textfarbe. */
.weg-lang { display: none; }
@media (min-width: 560px) { .weg-lang { display: inline; } }

/* ── Die Leiste auf schmalen Schirmen ────────────────────────────────
   Seit die Erklärseite dazugekommen ist, trägt die Leiste drei Wege.
   Gemessen bei 320 px: 87 + 110 + 152 px plus Abstände gegen 280 px
   verfügbare Breite — sie lief über.

   Was fällt, ist der Weg ZURÜCK, nicht einer der beiden Inhaltswege.
   Denn zurück kommt man auf diesen Seiten ohnehin zweifach: über das
   Logo und über „← Zurück zur Seite" direkt darunter. Die Rufnummer
   fällt nie — sie ist der einzige Buchungsweg dieses Betriebs. Vom Wort
   „Termin" davor bleibt auf schmalen Schirmen nur die Nummer; die
   Nummer erklärt sich selbst.                                          */
@media (max-width: 559px) {
  .oberlinie-weg--zurueck { display: none; }
  .ruf-wort { display: none; }
}


/* ══ DIE LINIE ═══════════════════════════════════════════════════════
   Jede Bühne (Auftakt, Kapitel, Schluss) trägt eine .linie, die von
   Oberkante bis Unterkante reicht. Weil die Bühnen lückenlos
   aufeinanderfolgen, ist die Linie durchgehend.                       */

.linie {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--rail);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  color: var(--tinte);
  pointer-events: none;
  z-index: 0;
}

/* gerades Zwischenstück */
.lauf {
  flex: 1 1 0;
  min-height: 0;
  width: 1px;
  margin-left: calc(var(--rail) / 2 - .5px);
  background: currentColor;
  transform-origin: top center;
}
.lauf:first-child { flex-grow: var(--oben, 1); }
.lauf:last-child  { flex-grow: var(--unten, 1); }

/* die Formwandlung */
.motiv {
  flex: 0 0 auto;
  width: var(--motiv-w);
  height: auto;
  margin-left: calc(var(--rail) / 2 - var(--motiv-w) * var(--anker));
  overflow: visible;
  view-timeline-name: --motiv;
  view-timeline-axis: block;
}
.motiv path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}


/* ── Die Ecken: dort wird die Linie zur Logo-Haarlinie ───────────── */

.logo-buehne {
  position: relative;
  width: min(100%, 760px);
  font-size: 0;
}
.logo-buehne--schluss { width: min(100%, 900px); }

.knick {
  position: absolute;
  right: 100%;
  width: calc(var(--rail) / 2 + var(--luft));
}

/* Auftakt: aus dem Logo nach links, dann hinunter */
.knick--start {
  top: calc(var(--hf) * 100% - .5px);
  bottom: calc(-1 * var(--kluft));
  border-top: 1px solid var(--tinte);
  border-left: 1px solid var(--tinte);
  border-top-left-radius: 999px;
}

/* Schluss: von oben herunter, dann nach rechts unter das Logo */
.knick--schluss {
  top: calc(-1 * var(--kluft));
  bottom: calc(100% - var(--hf) * 100% - .5px);
  border-bottom: 1px solid var(--papier);
  border-left: 1px solid var(--papier);
  border-bottom-left-radius: 999px;
}

/* und rechts wieder hinaus bis an den Seitenrand */
.strich--rechts {
  position: absolute;
  left: 100%;
  top: calc(var(--hf) * 100% - .5px);
  width: 100vw;
  border-top: 1px solid var(--papier);
}


/* ══ AUFTAKT ═════════════════════════════════════════════════════
   Gestrafft: Der Auftakt atmet noch, aber der erste Leistungsblock
   kommt deutlich früher. Reduziert wurden Oberluft, Abstand unter der
   Ortsmarke, Vorlauf des Videos und die Unterluft der Bühne; die
   Aufzählung sitzt jetzt in einer Zeile mit der Erfahrungszahl statt
   darunter.                                                          */

.auftakt {
  padding-top: calc(var(--leiste) + clamp(10px, 1.6vh, 22px));
}

.ortsmarke {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .55em;
  text-align: right;
  font-size: var(--s-fein);
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--leise);
  margin-bottom: clamp(16px, 3.2vh, 38px);
}

.rechtsweg a {
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.rechtsweg a:hover,
.rechtsweg a:focus-visible { border-bottom-color: currentColor; }

.auftakt-kopf {
  padding-left: var(--spur);
  padding-bottom: var(--kluft);
}

.auftakt-rest {
  position: relative;
  /* flow-root, damit der margin-top der Hero-Animation NICHT nach aussen
     kollabiert. Vorher tat er das: die Bühne begann 10 px zu tief, und
     genau diese 10 px klafften zwischen dem Logo-Knick und dem ersten
     geraden Stück der Linie. Gemessen bei 390 und 1440 px, jetzt null. */
  display: flow-root;
  padding-bottom: clamp(30px, 5vh, 62px);
}

/* Die Animation im Auftakt. Sie sitzt in derselben Textspalte wie alles
   andere (.inhalt trägt padding-left: var(--spur)) — die Linienspur links
   bleibt frei, beide Haarlinien berühren sich nie. Der transparente Grund
   liegt direkt auf dem Papierton.                                        */

.hero-linie,
.hero-linie-still {
  width: 100%;
  max-width: 940px;
  /* Das Stück ist 16:9 gerendert, die Linie lebt aber nur im Mittelband:
     über alle Frames gemessen liegt Tinte ausschliesslich zwischen 29 %
     und 74 % der Höhe. Der Rest war Leerraum — genau der Leerraum, über
     den sich der Betrieb beschwert hat. Deshalb wird auf dieses Band
     beschnitten (Mitte bei 52 %, damit oben und unten Luft bleibt).
     Kostet keinen einzigen Strich und spart über 200 px Scrollweg. */
  aspect-ratio: 1600 / 500;
  height: auto;
  object-fit: cover;
  object-position: center 52%;
  margin-top: clamp(4px, 1.2vh, 16px);
}

/* Ohne Bewegung steht das Standbild — die aussagekräftigste Form, der
   Brauenbogen. Erst wer Bewegung zulässt, bekommt das Video (siehe unten
   unter BEWEGUNG). Damit ist auch abgedeckt, wenn WebM ausfällt.          */
.hero-linie       { display: none; }
.hero-linie-still { display: block; }

/* Zahl und Aufzählung teilen eine Zeile — spart Höhe, ohne zu drängen */
.auftakt-fuss {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: clamp(22px, 4vh, 40px) clamp(20px, 4vw, 60px);
  margin-top: clamp(18px, 3.4vh, 44px);
}

.erfahrung {
  display: flex;
  align-items: flex-end;
  gap: clamp(9px, 1.6vw, 16px);
}
.erfahrung-zahl {
  font-size: var(--s-schau);
  font-weight: 800;
  line-height: .78;
  letter-spacing: -.055em;
  font-variant-numeric: tabular-nums;
}
.erfahrung-wort {
  font-size: var(--s-fein);
  font-weight: 600;
  letter-spacing: .24em;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--leise);
  padding-bottom: .3em;
}

.aufzaehlung {
  margin-left: auto;
  text-align: right;
  font-size: var(--s-klein);
  font-weight: 600;
  letter-spacing: .24em;
  line-height: 2.1;
  text-transform: uppercase;
  color: var(--leise);
}
.aufzaehlung span { display: block; }


/* ══ KAPITEL ═════════════════════════════════════════════════════ */

.kapitel {
  position: relative;
  padding-block: clamp(64px, 12vh, 150px);
}
.kapitel--eng  { padding-block: clamp(54px, 9.5vh, 115px); }

.inhalt {
  position: relative;
  z-index: 1;
  padding-left: var(--spur);
}
.inhalt--rechts { text-align: right; }

/* Die einzige Abweichung von der Satzkante im ganzen Auftritt — und sie hat
   einen Grund. Beim Dioden-Laser fächert die Linie in sechs waagerechte Bahnen
   auf, die nach rechts aus der Spur schiessen. Der Text setzt dort an, wo die
   längste Bahn endet: er steht am Ende des Strahls, nicht daneben. Ohne den
   Versatz beginnt die Überschrift mitten in den Bahnen und die Zeichnung wird
   zum Hintergrundmuster.

   Gemessen: 115 px Versatz bei 1440 px, 31 px bei 390 px. Alle zwölf übrigen
   Abschnitte des Auftritts stehen auf derselben Kante — geprüft.
   (DESIGN-PRINZIPIEN § 6: Abweichungen brauchen eine Bedeutung UND diesen
   Kommentar. Die Bedeutung war da, der Kommentar fehlte.)                    */
.kapitel--versetzt .inhalt {
  padding-left: calc(var(--spur) + clamp(0px, 8vw, 160px));
}

/* die randbrechende Ziffer, mit derselben Haarlinie gezeichnet */
.zahl {
  position: absolute;
  right: calc(-1 * var(--rand) - .06em);
  z-index: 0;
  font-size: var(--s-riese);
  font-weight: 900;
  line-height: .72;
  letter-spacing: -.06em;
  color: transparent;
  -webkit-text-stroke: 1px #a5a09a;
  user-select: none;
  pointer-events: none;
}
.zahl--hoch { top: clamp(8px, 3vh, 44px); }
.zahl--tief { bottom: clamp(8px, 3vh, 44px); }
/* rechtsbündige Kapitel tragen ihre Ziffer am linken Rand */
.zahl--links {
  right: auto;
  left: calc(-1 * var(--rand) - .06em);
}

/* Refrain — steht nur noch einmal, am Schluss */
.wandel {
  font-size: var(--s-klein);
  font-weight: 700;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--akzent);
}
.wandel span {
  font-weight: 400;
  color: var(--leise);
}

/* stille Vorzeile — dort, wo eine Einordnung nötig ist */
.marke {
  font-size: var(--s-klein);
  font-weight: 700;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--leise);
}
/* Gruppentitel innerhalb eines Kapitels (Make-up / Hairstyling) */
.marke--gruppe { margin-bottom: clamp(18px, 3vh, 30px); }

.kapitel h2 {
  font-size: var(--s-schau);
  font-weight: 800;
  line-height: .88;
  letter-spacing: -.045em;
  word-spacing: .12em;
  text-transform: uppercase;
  margin: clamp(12px, 2vh, 22px) 0 clamp(34px, 6vh, 66px);
}
/* ohne Vorzeile beginnt das Kapitel direkt mit der Überschrift */
.inhalt > h2:first-child { margin-top: 0; }

/* einzige Ausnahme: das Ä von GLÄTTUNG stößt sonst an das O von BIO */
#keratin h2 { line-height: 1.2; }

/* ── Fragen · gestellte Überschriften ────────────────────────────────
   Zwei Fragen als h2/h3 im Fließtext, weil Leute so suchen und KI-
   Systeme so zitieren. Keine Aufmachung, nur Grösse und Luft.        */

h3.frage {
  margin: clamp(-14px, -2vh, -6px) 0 0;
  font-size: var(--s-satz);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -.015em;
  max-width: 26ch;
}
h2 + h3.frage { margin-top: clamp(-20px, -3.4vh, -10px); }
.inhalt--rechts h3.frage { margin-left: auto; }

/* Der negative Rand oben stammt aus einer Zeit, in der auf jede Bühne genau
   EINE Frage kam — dort zog er die Frage an die Überschrift heran, unter deren
   grossen Abstand. Auf behandlungen.html stehen erstmals mehrere Frage-Antwort-
   Paare hintereinander, und dort riss er die nächste Frage in den vorigen
   Absatz hinein: gemessen 14 px Überlappung, die Überschrift lag auf der
   letzten Textzeile. Folgt eine Frage auf eine Antwort, ist der Abstand deshalb
   positiv und so gross wie zwischen zwei Blöcken.

   Aufgezählt statt per :not() gelöst: die Liste sagt, welche Fälle es gibt,
   und meldet sich von selbst, wenn ein neuer dazukommt. Der Standardwert
   bleibt negativ — die Frage direkt unter der Gruppenüberschrift ist immer
   noch der häufigste Fall auf dieser Website.                                */
.antwort + h3.frage,
.karg + h3.frage,
.tarif + h3.frage,
.regeln + h3.frage,
.nachsatz + h3.frage,
.ruf-zusatz + h3.frage { margin-top: clamp(34px, 5.6vh, 60px); }

.kapitel h2.frage {
  font-size: var(--s-haupt);
  line-height: 1.02;
  letter-spacing: -.035em;
  text-transform: none;
  word-spacing: 0;
  max-width: 19ch;
  margin-bottom: clamp(16px, 2.6vh, 26px);
}

.antwort {
  margin-top: .75em;
  font-size: var(--s-satz);
  font-weight: 500;
  line-height: 1.55;
  color: var(--leise);
  max-width: 42ch;
}
.inhalt--rechts .antwort { margin-left: auto; }
.antwort + .nennung { margin-top: clamp(32px, 5.5vh, 58px); }

/* ── Nennung · die Namen ohne Zahl ────────────────────────────────────
   Seit die Preise auf einer eigenen Seite stehen, nennt die Startseite
   nur noch, WAS es gibt. Eine Reihe von Namen, mit Mittelpunkt getrennt,
   im Register der kleinen Bezeichner (.was) — damit die Kapitel ihre
   Dramaturgie behalten und trotzdem ruhig werden.
   Der Trennpunkt hängt am Namen (::after), nicht vor dem nächsten:
   beim Umbruch beginnt so keine Zeile mit einem Punkt.                */

.nennung {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .55em clamp(11px, 1.9vw, 22px);
  max-width: 52ch;
}
.nennung li {
  font-size: var(--s-text);
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  line-height: 1.3;
}
.nennung li:not(:last-child)::after {
  content: "·";
  margin-left: clamp(11px, 1.9vw, 22px);
  color: var(--leise);
}
.inhalt--rechts .nennung { justify-content: flex-end; margin-left: auto; }
.nennung + .nachsatz { margin-top: clamp(14px, 2.4vh, 26px); }
.nennung + .marke--gruppe { margin-top: clamp(34px, 6vh, 62px); }

/* Der Weg zum Preis · Textlink, kein Knopf */
.preisweg {
  display: inline-block;
  margin-top: clamp(20px, 3.4vh, 34px);
  font-size: var(--s-klein);
  font-weight: 600;
  letter-spacing: .24em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
/* Zwei Wege nebeneinander lasen sich als ein Satz — „WAS DAS IST → PREISE →".
   Gesperrte Grossbuchstaben haben keine Wortzwischenräume, die als Trennung
   taugen. Folgt ein Weg auf einen Weg, steht er deshalb darunter, mit dem
   kleinen Abstand einer Aufzählung statt dem grossen eines neuen Blocks. */
.preisweg { margin-right: 0; }
.preisweg + .preisweg {
  display: block;
  margin-top: clamp(8px, 1.4vh, 14px);
}

.preisweg:hover,
.preisweg:focus-visible { border-bottom-color: var(--akzent); }

/* ── Kleiner Bezeichner über einem grossen Wert ───────────────────────
   Trägt jetzt nur noch die Rufnummer-Blöcke (Anmeldung, die drei Wege
   zum Termin). Die früheren Preisklassen (.preise, .wieviel und ihre
   Varianten) sind mit der Auslagerung der Preise auf leistungen.html
   ersatzlos entfallen — die Preiszeile dort heisst .tarif.            */

.was {
  display: block;
  font-size: var(--s-klein);
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  margin-bottom: .7em;
  max-width: 30ch;
}

.nachsatz {
  margin-top: clamp(6px, 1.5vh, 14px);
  font-size: var(--s-text);
  font-weight: 500;
  line-height: 1.6;
  color: var(--leise);
}

.karg {
  font-size: var(--s-karg);
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: -.01em;
  max-width: 26ch;
}

/* Drei Zusagen, jede mit einem Haarstrich davor — die Linie im Kleinen.
   Keine Kästen, keine Häkchen, keine Chips.                            */
.versprechen {
  margin-top: clamp(30px, 5vh, 56px);
  font-size: var(--s-klein);
  font-weight: 600;
  letter-spacing: .12em;
  line-height: 1.65;
  text-transform: uppercase;
}
.versprechen span { display: block; margin-bottom: 1em; max-width: 46ch; }
.versprechen span:last-child { margin-bottom: 0; }
.versprechen span::before,
.versprechen span::after {
  content: "";
  display: inline-block;
  width: clamp(16px, 3.6vw, 38px);
  vertical-align: .3em;
  border-top: 1px solid var(--leise);
}
.versprechen span::before { margin-right: .9em; }
.versprechen span::after  { display: none; }
.inhalt--rechts .versprechen span            { margin-left: auto; }
.inhalt--rechts .versprechen span::before    { display: none; }
.inhalt--rechts .versprechen span::after     { display: inline-block; margin-left: .9em; }

/* ══ ACADEMY · die Schulung ══════════════════════════════════════════
   Das Kapitel steht seit dem Umbau an dritter Stelle und trägt sieben
   Punkte vom Schulungsplakat. Die frühere Fassung war „viel auf
   einmal" — vier gesperrte Versalzeilen als Treppe. Deshalb hier eine
   klare Dreiteilung statt einer Liste aus sieben gleich lauten Zeilen:

     laut    die 3 Tage      — gesetzt wie die 10 Jahre im Auftakt
     leise   fünf Punkte     — gemischte Schreibung, eine Zeile je Punkt,
                               keine Sperrung, keine Striche, keine Häkchen
     laut    das Starter-Set — Label klein darüber, Wert gross, also
                               dieselbe Grammatik wie ein Preiseintrag,
                               nur dass hier keine Zahl steht

   Etwas mehr Unterluft als ein Nebenkapitel, weil das Kapitel jetzt
   Gewicht trägt — aber dieselbe Bühne wie alle anderen.               */

.kapitel--lehre { padding-block: clamp(72px, 13vh, 168px); }

/* ihre eigene Plakatzeile · keine Versalien, damit sie nicht mit dem
   ACADEMY darüber konkurriert */
h3.einladung {
  margin-top: clamp(-24px, -4vh, -14px);
  font-size: var(--s-titel);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -.025em;
  max-width: 20ch;
}
.unterzeile {
  margin-top: clamp(10px, 1.8vh, 18px);
  font-size: var(--s-text);
  font-weight: 500;
  line-height: 1.5;
  color: var(--leise);
  max-width: 32ch;
}
.leiser { color: var(--leise); }

.lehrgang {
  display: flex;
  align-items: flex-end;
  gap: clamp(10px, 1.8vw, 20px);
  margin-top: clamp(38px, 6.5vh, 72px);
}
.lehrgang-zahl {
  font-size: var(--s-schau);
  font-weight: 800;
  line-height: .74;
  letter-spacing: -.055em;
  font-variant-numeric: tabular-nums;
}
.lehrgang-wort {
  font-size: var(--s-klein);
  font-weight: 600;
  letter-spacing: .22em;
  line-height: 1.7;
  text-transform: uppercase;
  padding-bottom: .3em;
}

/* die fünf ruhigen Punkte dazwischen */
.lehrplan { margin-top: clamp(30px, 5vh, 54px); }
.lehrplan li {
  margin-bottom: clamp(12px, 2vh, 20px);
  font-size: var(--s-satz);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: -.008em;
  max-width: 40ch;
}
.lehrplan li:last-child { margin-bottom: 0; }

.dazu {
  margin-top: clamp(30px, 5vh, 54px);
  font-size: var(--s-titel);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -.035em;
}
.dazu span {
  display: block;
  margin-bottom: .6em;
  font-size: var(--s-klein);
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--leise);
}


/* ══ BILDSYSTEM ══════════════════════════════════════════════════════
   Vorher hatte jedes Bild eine handgesetzte Breite — es gab keine Regel,
   und das war zu Recht die erste Frage des Betriebs. Jetzt gilt genau
   eine:

        DIE BILDHÖHE FOLGT DEM RANG DER LEISTUNG.

   Die Breite ergibt sich daraus und aus dem Seitenverhältnis der Datei
   (--ar = Breite / Höhe, am <figure> notiert). Warum über die Höhe und
   nicht über die Breite: die Fotos sind teils hochkant, teils quer. Nur
   die Höhe gibt beiden Formaten dieselbe Präsenz im Scrollfluss — der
   Grössenunterschied, den man sieht, ist damit immer ein Rangunterschied
   und nie ein Zufall des Dateiformats.

   Stufe 1 · .bild--kern    Hauptleistungen des Studios:
                            Permanent Make-up, Wimpern, Hydrafacial.
                            Höhe bis 600 px.
   Stufe 2 · .bild--neben   Einzel- und Zusatzleistungen:
                            Lash-/Browlifting, Haut, Bio Keratin, Academy.
                            Höhe bis 300 px — halb so hoch wie Stufe 1,
                            also Beleg und nicht Hauptdarsteller.
   Stufe 3 · .bild--ort     Kein Leistungsbild, sondern ein Ort oder ein
                            Anlass: das Studio, der Blick in den Spiegel.
                            Randbrechendes Band über die ganze Textbreite
                            bis in den Seitenrand hinaus — bewusst ausser
                            Konkurrenz zu den Rangstufen.

   Auf schmalen Schirmen läuft Stufe 1 auf die volle Textbreite, Stufe 2
   auf 64 % davon: die Rangfolge bleibt sichtbar, auch wenn die Rechnung
   über die Höhe dort nicht mehr greift.

   Sonderfall .bild--portraet: die Inhaberin ist keine Leistung und steht
   deshalb ausserhalb der Stufen.                                        */

.bild img {
  /* Farbe, auf Wunsch von Farah (11.08.2026). Vorher liefen alle Motive
     entfaerbt — das hielt die Reihe zusammen, aber es nahm den Behandlungen
     genau das, was man an ihnen sieht: den Ton der Haut, das Braun der Braue,
     das Rot der Lippe.

     Der leichte Kontrast bleibt. Er war nie fuer die Graustufen da, sondern
     gegen die flaue Ausleuchtung der Vorlagen. Die Saettigung liegt knapp
     unter eins: die Bilder sollen neben dem cremefarbenen Grund liegen,
     nicht daraus hervorspringen.

     Der Hintergrund (.atmo) bleibt entfaerbt — er ist kein Bild, das man
     ansieht, sondern eine Flaeche bei 10 Prozent Deckung. Farbe faerbt dort
     den cremefarbenen Grund ein, statt etwas zu zeigen. */
  filter: saturate(.92) contrast(1.08);
  width: 100%;
}
.bild figcaption {
  margin-top: 1.1em;
  font-size: var(--s-fein);
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--leise);
}

.bild--kern,
.bild--neben { margin-top: clamp(38px, 7vw, 74px); }

/* HÖHER UND BREITER seit dem 19.08.2026. Vorher deckelte die Höhe bei 600
   bzw. 300 px — bei hochformatigen Aufnahmen wurde das Bild dadurch schmal
   und liess die halbe Fläche daneben leer. Gemessen nutzten die Bilder
   zwischen 22 % und 74 % der Textbreite; das las sich als Unordnung, obwohl
   die Regel dahinter stimmte.

   Die Rangfolge über die Höhe bleibt — sie ist richtig. Dazu kommt eine
   MINDESTBREITE: kein Bild soll schmaler stehen als die Hälfte (Stufe 1)
   bzw. ein gutes Drittel (Stufe 2) der Textspalte. Damit bleibt der
   Rangunterschied sichtbar, aber kein Bild verliert sich mehr im Weissraum. */
/* DIE HÖHE FÜHRT, UND SIE IST GEDECKELT.

   Am 19.08. hatte ich eine Mindestbreite eingezogen, damit hochformatige
   Bilder nicht zu schmal stehen. Das war der falsche Hebel: Bei einem Bild
   im Verhältnis 0,6 zwingt eine Mindestbreite von 52 % die Höhe auf über
   1100 px. Gemessen kamen dabei 983, 887 und 1463 px heraus — Bilder, die
   höher waren als ein Bildschirm.

   Die Höhe ist wieder die einzige Führungsgrösse, und sie ist gedeckelt.
   Der Rangunterschied zwischen den Stufen bleibt dadurch erhalten, ohne
   dass ein Format aus der Reihe wächst.

   Der Freiraum neben hochformatigen Bildern kehrt damit teilweise zurück.
   Das ist der Preis, und er ist der kleinere: ein Bild, das höher ist als
   der Schirm, zwingt zum Scrollen mitten im Motiv. */
.bild--kern {
  --bh: clamp(300px, 52vh, 600px);
  width: min(100%, calc(var(--bh) * var(--ar)));
}
.bild--neben {
  /* Höher als Stufe 1 es je war, weil hochformatige Motive bei gleicher
     Höhe schmal werden: „Bio Keratin" (Verhältnis 0,665) stand mit 180 px
     Breite da, während querformatige Nachbarn 406 hatten. Der Rangunterschied
     zu Stufe 1 bleibt, aber kein Bild fällt mehr durch. */
  /* 50vh statt 38 — Sadan am 20.08. zum Keratin-Bild: „größer machen".
     Es stand mit 227 x 342 px in einer Spalte von 672 px Breite da.
     Bleibt unter Stufe 1 (52vh / 600), die Rangfolge der Bildstufen hält. */
  --bh: clamp(260px, 50vh, 560px);
  width: min(64%, calc(var(--bh) * var(--ar)));
}
.inhalt--rechts .bild--kern,
.inhalt--rechts .bild--neben { margin-left: auto; }

.bild--ort {
  margin-block: clamp(38px, 7vw, 76px);
  margin-right: calc(-1 * var(--rand));
}
/* KEIN BESCHNITT MEHR. Der Deckel mit object-fit:cover schnitt oben und
   unten weg — bei „Die grossen Tage" fehlte damit der halbe Kopf, und Sadan
   verlangte am 20.08. ausdrücklich „hier das volle bild".

   Die Höhe wird stattdessen über die BREITE begrenzt: ein Band, das schmaler
   ist, wird von selbst flacher, und das Bild bleibt ganz. Randbrechend
   bleibt es trotzdem — es läuft weiterhin in den Seitenrand hinein. */
.bild--ort img,
.bild--ort video {
  /* Ganz, aber nicht höher als der halbe Bildschirm. max-height mit
     width:auto behält das Seitenverhältnis — im Gegensatz zu object-fit,
     das beschneiden würde. Bei „Die grossen Tage" war das Bild sonst
     1437 px hoch: man scrollte mitten durch das Motiv. */
  max-height: 64vh;
  width: auto;
  max-width: 100%;
}
.bild--ort figcaption { padding-right: var(--rand); }
.inhalt--rechts .bild--ort figcaption { text-align: right; }


/* ══ DER RAUM ALS TIEFE ══════════════════════════════════════════════
   Gewünscht war „der salon so im hintergrund so ein video". Ein zweites
   Video kommt hier nicht hin: neben der Linien-Animation wären das zwei
   bewegte Flächen auf einem Schirm, und die Linie verliert dann ihren
   Auftritt — sie ist die Idee der Seite, nicht Beiwerk.

   Stattdessen liegt DASSELBE Salonfoto, das im Über-Kapitel lesbar steht
   (assets/foto-studio.jpg), an zwei Stellen als Ahnung von Tiefe hinter
   der Seite. Kein neues Bild, keine zusätzliche Anfrage, kein Byte mehr:
   die Datei wird sowieso geladen. Zwei Anschnitte desselben Raums.

   WO — und warum dort:

   · TERMIN. Gemessen war das die einzige Bühne der Startseite ohne
     randbrechende Ziffer UND ohne Bild: 915 px hoch bei 1440 px, rechts
     der Rufnummer nichts. Jedes andere Kapitel hat seine Ziffer, die die
     rechte Hälfte trägt; das Über-Kapitel hat Porträt und Studioband.
     Nur hier stand die Fläche wirklich leer — das ist die Leere, die
     gestört hat. Und es ist die Stelle, an der man sich entscheidet
     anzurufen: hinter der Nummer liegt der Raum, in den man kommt.

   · AUFTAKT. Der erste Schirm ist eine Haarlinie auf 1440 × 900 px
     Papier, sonst nichts. Hier liegt der Raum hinter der Animation,
     deutlich schwächer als im Termin-Kapitel (7 statt 10 Prozent), weil
     der Auftakt bewusst leer ist und bleiben soll. Nebenbei: auf dem
     Foto hängt an ihrer Salonwand eine Einstrich-Zeichnung eines
     Gesichts. Die Animation führt vor, was bei ihr an der Wand hängt —
     das Konzept ist nicht erfunden, es hängt dort.

   WIE:

   · Schwarz-Weiss, stark aufgehellt, Deckkraft 7 % und 10 %. Über 12 %
     wird aus der Ahnung ein Bild und der graue Fliesstext verliert
     seinen Kontrast, unter 6 % ist auf dem Off-White nichts mehr zu
     sehen. Beides gemessen, nicht geschätzt.
   · Randlos. Die Fläche läuft über den Seitenrand hinaus (dort schneidet
     .seite ab) und wird an jeder Kante, die im Bild liegt, weich
     ausmaskiert. Eine sichtbare Bildkante wäre ein Kasten.
   · Zwei Masken auf zwei Elementen (waagerecht am Träger, senkrecht am
     Bild) statt einer mit mask-composite: multipliziert sich genauso und
     braucht kein Compositing-Feature.
   · Bewegung: 48 s Skalieren, alternierend — 96 s pro Runde, an der
     Wahrnehmungsgrenze. „alternate" statt Neustart, weil eine Schleife,
     die zurückspringt, einen Sprung hat; und ein Sprung wäre bei 7 %
     Deckkraft genau das Einzige, was man bemerkt.
   · prefers-reduced-motion: keine Animation. Die Fläche steht dann
     einfach still — es fehlt nichts und es klafft nichts.               */

.atmo {
  position: absolute;
  z-index: 0;
  overflow: clip;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 var(--einsatz, 46%));
          mask-image: linear-gradient(to right, transparent 0%, #000 var(--einsatz, 46%));
}
.atmo img,
.atmo video {
  width: 100%;
  height: auto;          /* 9:16 aus den Massen — kein object-fit */
  object-fit: cover;
  object-position: var(--op, center);
  /* Aufgehellt, im Kontrast zurückgenommen, leicht unscharf: aus dem Foto
     wird eine Fläche mit Tiefe — und aus der Tiefe kein Motiv. Die
     Unschärfe ist nicht Kosmetik, sie war nötig: ohne sie blieben zwei
     harte Senkrechte aus dem Foto stehen (der Spiegelrahmen, die Regal-
     streben). Die lasen sich als Streifen, also als Bild, das man ansieht.
     Unscharf ist es Tiefe. Nebenwirkung: die Auflösung der Datei ist
     dadurch völlig gleichgültig. */
  filter: grayscale(1) brightness(1.34) contrast(.72) blur(2.6px);
  opacity: var(--deckung, .1);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 17%, #000 83%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0%, #000 17%, #000 83%, transparent 100%);
}

/* Termin · die rechte Hälfte, über den Seitenrand hinaus */
.atmo--termin {
  inset: 0 calc(-1 * var(--rand) - 7vw) 0 37%;
  --deckung: .10;
  --einsatz: 42%;
  --op: 56% 64%;
}

/* Auf schmalen Schirmen gibt es keine leere rechte Hälfte: dort ist die
   Textspalte die ganze Seite. Die Fläche liegt deshalb hinter dem ganzen
   Block — und endet ÜBER der grauen Anschriftzeile am Fuss des Kapitels.
   Gemessen: lief die Fläche bis unten durch, fiel diese Zeile bei 390 px
   auf 4,45 : 1 und damit unter AA. Die Zeilen darüber sind alle Tinte und
   haben 16 : 1 und mehr, die tragen die Fläche ohne Weiteres. */
@media (max-width: 700px) {
  .atmo--termin {
    inset: 0 calc(-1 * var(--rand) - 7vw) 17% 6%;
    --einsatz: 26%;
    --op: 50% 58%;
  }
}

/* Auftakt · hinter der Animation, ein flaches Band statt einer Fläche */
.atmo--auftakt {
  top: calc(-1 * clamp(26px, 6vh, 84px));
  left: 3%;
  right: calc(-1 * var(--spur) - var(--rand) - 7vw);
  /* Höhe = Höhe der Animation plus Überstand, nicht aus einem Seiten-
     verhältnis. Die Animation ist min(100%, 940px) breit bei 1600/500,
     also 3,2 — dieselbe Rechnung hier in vw ausgeschrieben. Ein festes
     Seitenverhältnis wäre falsch: die Fläche wird mit dem Schirm breiter,
     die Animation ab 1240 px nicht mehr höher; die Fläche wäre dann bis
     in die Fusszeile gewachsen. Dort steht die graue Aufzählung, und
     grau auf Papier hat nur 5,14 : 1 Reserve — gemessen fiel sie mit
     einer zu hohen Fläche auf 4,54 : 1. So endet die Fläche auf jeder
     Breite über der Fusszeile. */
  height: clamp(175px, calc((100vw - 2 * var(--rand) - var(--spur)) / 3.2 + 48px), 385px);
  /* Wieder .07 wie ursprünglich: hier liegt seit dem 18.08.2026 abends
     wieder das Salonfoto und kein Film. Der Film ist in einen eigenen
     Rahmen umgezogen, weil ein Hochformat-Video in einem flachen Band
     nur zu 13 % ankam — nachzulesen in index.html an der Fläche selbst.
     Ein Standbild als Ahnung von Tiefe verträgt die niedrige Deckkraft,
     dafür war sie gedacht. */
  --deckung: .07;
  --einsatz: 40%;
  --op: 46% 52%;
}



/* Die Animation im Auftakt hat einen EINGEBACKENEN Off-White-Grund (kein
   Alpha, siehe index.html) — als opakes Rechteck würde sie ein helles Loch
   in die Fläche schlagen. Der Grund ist bitgenau der Papierton (250 249
   247, im Videoframe nachgemessen), also nimmt „darken" pixelweise den
   dunkleren von beiden: der Videogrund verschwindet vollständig, die Tinte
   der Linie bleibt. Keine Kante, kein Loch, keine zweite Datei.
   „multiply" wäre falsch — es hätte das Rechteck um 2 % abgedunkelt und
   damit genau die Kante erzeugt, die hier nicht sein darf. Beide Elemente
   liegen im Stapelkontext von .inhalt (position:relative, z-index:1);
   deshalb steht die Fläche als erstes Kind DARIN und nicht daneben. */
.hero-linie,
.hero-linie-still { mix-blend-mode: darken; }


/* ══ ÜBER ════════════════════════════════════════════════════════
   Kein Kapitel mit Nummer: die Linie holt hier einmal weit aus und
   kommt zurück, bevor sie in den Schluss läuft.                    */

.kapitel--ueber { padding-block: clamp(80px, 14vh, 180px); }

.kapitel--ueber h2 { margin-bottom: clamp(18px, 3vh, 32px); }
.kapitel--ueber .karg { max-width: 22ch; }

/* Freigestelltes Porträt — kein Rahmen, kein Kasten; der weiße Blazer
   läuft nach unten ins Papier aus, das Gesicht trägt das Bild. */
.bild--portraet {
  margin-top: clamp(40px, 8vw, 72px);
  /* Die Zahl greift hier NICHT: das Porträt steht in einer Grid-Spalte des
     Über-Abschnitts, und die gibt mit 353 px die Breite vor. Gemessen, nicht
     vermutet. Der Wert bleibt als Deckel für den Fall stehen, dass das
     Porträt je ausserhalb des Grids verwendet wird — und der Über-Abschnitt
     braucht ihn nicht, weil dort Text NEBEN dem Bild steht. Genau das ist
     der Grund, warum dort kein Freiraum entsteht. */
  width: min(100%, 420px);
}

.bild--studio { margin-top: clamp(44px, 8vw, 84px); }


/* ══ TERMIN ══════════════════════════════════════════════════════
   Es gibt kein Buchungssystem — also steht hier keines. Drei Wege,
   jeder als grosser Text mit Pfeil. Keine Schaltfläche.            */

.kapitel--termin { padding-block: clamp(70px, 12vh, 150px); }

.wege-liste { margin-top: clamp(34px, 6vh, 62px); }
.wege-liste li {
  margin-left: calc(var(--i, 0) * clamp(0px, 3vw, 54px));
  margin-bottom: clamp(24px, 4vh, 44px);
}
.wege-liste li:last-child { margin-bottom: 0; }
.wege-liste .was { margin-bottom: .6em; }
.wege-liste + .nachsatz { margin-top: clamp(26px, 4.2vh, 46px); }
/* Nach den drei Wegen steht jetzt „Wo liegt Farah Studio?" statt einer
   blossen Anschriftenzeile — dieselbe Angabe, aber als Frage, damit die
   FAQ-Auszeichnung deckt, was sichtbar ist. Der Abstand ist der einer neuen
   Frage, nicht der eines Nachsatzes. Die negative Regel h2 + h3.frage greift
   hier nicht: dazwischen liegt die Liste. */
.wege-liste + h3.frage { margin-top: clamp(34px, 5.6vh, 60px); }


/* ── Rufnummer und Handles · grosser Text mit Pfeil ──────────────── */

/* Die Anmeldung zur Schulung: dieselbe Bauweise wie die drei Wege zum
   Termin — grosser Text mit Pfeil, kein Knopf. Die Zweitzeile führt
   dieselbe Nummer über WhatsApp, deshalb steht sie klein darunter und
   nicht als zweiter grosser Block.                                    */
.ruf { margin-top: clamp(40px, 7vh, 76px); }
.ruf-zusatz { margin-top: .9em; }

.ruf a,
.wege-liste a {
  display: inline-block;
  font-size: var(--s-haupt);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.045em;
  word-spacing: .1em;
  text-decoration: none;
  font-variant-numeric: tabular-nums;
  border-bottom: 1px solid transparent;
}
.handle a,
.ruf-zusatz a,
.rechtsweg--schluss a {
  display: inline-block;
  font-size: var(--s-satz);
  font-weight: 600;
  letter-spacing: .02em;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.rechtsweg--schluss a { font-size: var(--s-text); }

.ruf a:hover, .ruf a:focus-visible,
.wege-liste a:hover, .wege-liste a:focus-visible,
.handle a:hover, .handle a:focus-visible,
.ruf-zusatz a:hover, .ruf-zusatz a:focus-visible,
.rechtsweg--schluss a:hover, .rechtsweg--schluss a:focus-visible { border-bottom-color: var(--akzent); }

.pfeil {
  display: inline-block;
  margin-left: .22em;
  color: var(--akzent);
  font-style: normal;
}
.pfeil--links { margin-left: 0; margin-right: .22em; }


/* ══ SCHLUSS · die Linie schließt sich ═══════════════════════════ */

.schluss {
  --leise: #a8a8a8;
  --akzent: var(--papier);
  position: relative;
  /* höher als die Kopfleiste (20): die Schlussbühne schiebt sich am
     Seitenende darüber, damit das schwarze Bild ungeteilt bleibt */
  z-index: 30;
  margin-inline: calc(-1 * var(--rand));
  padding-inline: var(--rand);
  padding-bottom: clamp(56px, 10vh, 130px);
  background: var(--tinte);
  color: var(--papier);
  view-timeline-name: --finale;
  view-timeline-axis: block;
}
.schluss .linie { color: var(--papier); }

/* die Oberluft gehört in den Kontaktblock, damit die Linienspur
   lückenlos von der letzten Sektion herüberläuft */
.schluss-kontakt {
  position: relative;
  padding-top: clamp(72px, 13vh, 165px);
  padding-bottom: var(--kluft);
}

.wandel--hell { color: var(--papier); }
.wandel--hell span { color: var(--leise); }

.anschrift {
  margin-top: clamp(24px, 4.4vh, 46px);
  font-size: var(--s-satz);
  font-weight: 500;
  line-height: 1.55;
  color: var(--leise);
}
.handle {
  margin-top: clamp(18px, 3vh, 30px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .45em;
}
.rechtsweg--schluss {
  margin-top: clamp(26px, 4.4vh, 48px);
  display: flex;
  flex-wrap: wrap;
  gap: 1.6em;
  color: var(--leise);
}

.schluss-lockup { padding-left: var(--spur); }


/* ══ BEWEGUNG ════════════════════════════════════════════════════
   Alles hierunter ist Zugabe. Ohne Bewegung steht die Seite fertig
   gezeichnet da — jede Animation läuft vom unsichtbaren Zustand in
   genau diesen Endzustand.                                          */

@media (prefers-reduced-motion: no-preference) {

  /* Die Linie, die zum Gesicht wird — sonst bleibt das Standbild stehen */
  .hero-linie       { display: block; }
  .hero-linie-still { display: none; }

  /* Der Raum atmet · 48 s hin, 48 s zurück. Der Skalierpunkt ist derselbe
     wie der Bildanschnitt (--op), damit das Bild nicht aus seinem Ausschnitt
     wandert. will-change hebt die Fläche auf eine eigene Compositor-Ebene:
     ohne das würde ein maskiertes, gefiltertes Bild dieser Grösse 96 s lang
     durchgehend neu gezeichnet. */
  .atmo img {
    transform-origin: var(--op, center);
    will-change: transform;
    animation: raum-atem 48s ease-in-out infinite alternate;
  }
  @keyframes raum-atem {
    from { transform: scale(1.004); }
    to   { transform: scale(1.086); }
  }

  /* Eintritt beim Laden */
  .auftritt {
    animation: auftritt .95s var(--schwung) both;
    animation-delay: var(--d, 0ms);
  }
  @keyframes auftritt {
    from { opacity: 0; transform: translateY(.42em); clip-path: inset(-30% -30% 100% -30%); }
    to   { opacity: 1; transform: none;              clip-path: inset(-30% -30% -30% -30%); }
  }

  .knick--start {
    animation: knick-start 1.05s cubic-bezier(.65, 0, .25, 1) both;
    animation-delay: 620ms;
  }

  /* Der Auftakt-Strich hängt NICHT am Scrollen: er wird beim Laden aus dem
     Logo-Knick heraus nach unten gezogen und bleibt dann stehen. Am
     Seitenanfang ist der cover-Bereich eines Elements schon zur Hälfte
     verstrichen — auf der Scroll-Zeitachse klaffte hier im ersten
     Bildschirm eine sichtbare Lücke in der Linie. Höhere Spezifität als
     die .lauf-Regel weiter unten, gilt also auch dort.                 */
  .auftakt-rest .lauf {
    animation: lauf 1.15s cubic-bezier(.62, 0, .25, 1) both;
    animation-delay: 1.45s;
    animation-timeline: auto;
  }

  /* Dasselbe am Kopf der Preisseite: das erste Stück Linie steht schon
     beim Laden im Bild, hängt also nicht am Scrollen. */
  .preis-auftakt .lauf {
    animation: lauf 1.05s cubic-bezier(.62, 0, .25, 1) both;
    animation-delay: 520ms;
    animation-timeline: auto;
  }

  /* Auf den Rechtstexten führt die Linie nichts vor — sie steht einfach da */
  .recht-seite .lauf { animation: none; }
  @keyframes knick-start {
    0%   { clip-path: inset(0 0 calc(100% - 2px) 100%); }
    46%  { clip-path: inset(0 0 calc(100% - 2px) 0); }
    100% { clip-path: inset(0 0 0 0); }
  }

  /* Die Kopfleiste wächst mit dem Scrollen und liefert am Ende die Nummer.
     Ohne Scroll-Timeline bleibt beides im Endzustand — voll gezogen. */
  @supports (animation-timeline: scroll()) {
    .oberlinie-zug {
      animation: zug linear both;
      animation-timeline: scroll(root block);
    }
    /* nicht bei null: oben links steht immer ein kurzer Stummel, damit
       erkennbar ist, dass dort eine Linie anfängt */
    @keyframes zug { from { transform: scaleX(.06); } to { transform: scaleX(1); } }

    .oberlinie-ruf,
    .oberlinie-weg {
      animation: aufblenden linear both;
      animation-timeline: scroll(root block);
      animation-range: 1% 5%;
    }
    @keyframes aufblenden { from { opacity: 0; } to { opacity: 1; } }
  }

  @supports (animation-timeline: view()) {

    /* die Linie zeichnet sich beim Scrollen */
    .lauf {
      animation: lauf linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 56%;
    }
    @keyframes lauf { from { transform: scaleY(0); } to { transform: scaleY(1); } }

    /* letztes Stück ebenfalls an der Schlussbühne, sonst bleibt es kurz */
    .schluss-kontakt .lauf {
      animation-timeline: --finale;
      animation-range: entry 0% entry 44%;
    }

    .motiv path {
      stroke-dasharray: 1;
      animation: ziehen linear both;
      animation-timeline: --motiv;
      animation-range-start: cover calc(10% + var(--v, 0) * 2.4%);
      animation-range-end:   cover calc(52% + var(--v, 0) * 2.4%);
    }
    @keyframes ziehen { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }

    /* Inhalt kommt beim Scrollen herauf */
    .kapitel .inhalt > *:not(h2),
    .schluss .inhalt > * {
      animation: heben linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 28%;
    }
    @keyframes heben {
      from { opacity: 0; transform: translateY(28px); }
      to   { opacity: 1; transform: none; }
    }

    /* Kapitelübergang: die Überschrift wird von der Linienseite her
       aufgedeckt — links­bündige Kapitel von links, rechtsbündige von
       rechts. Kein Sprung, kein Federn, nur ein Wischen.             */
    .kapitel h2 {
      animation: wischen linear both;
      animation-timeline: view();
      animation-range: entry 4% cover 26%;
    }
    @keyframes wischen {
      from { opacity: 0; clip-path: inset(0 100% 0 0); }
      to   { opacity: 1; clip-path: inset(-14% -14% -14% -14%); }
    }
    .inhalt--rechts h2 { animation-name: wischen-rechts; }
    @keyframes wischen-rechts {
      from { opacity: 0; clip-path: inset(0 0 0 100%); }
      to   { opacity: 1; clip-path: inset(-14% -14% -14% -14%); }
    }

    /* die drei Wege zum Termin kommen einer nach dem anderen */
    .wege-liste { animation: none; }
    .wege-liste li {
      animation: heben linear both;
      animation-timeline: view();
      animation-range: entry calc(2% + var(--i, 0) * 7%) cover calc(24% + var(--i, 0) * 7%);
    }

    /* die Haarstriche vor den Zusagen ziehen sich nach */
    .versprechen span::before,
    .versprechen span::after {
      transform-origin: left center;
      animation: strichziehen linear both;
      animation-timeline: view();
      animation-range: entry 6% cover 30%;
    }
    .inhalt--rechts .versprechen span::after { transform-origin: right center; }
    @keyframes strichziehen { from { transform: scaleX(0); } to { transform: scaleX(1); } }

    /* Der Abzweig zeichnet sich beim Scrollen — jetzt als echtes Ziehen
       des Pfades statt als Breitenwachstum, denn ein scaleX würde das
       Motiv verzerren statt es zu zeichnen. Mehrteilige Motive (Wimpern,
       Nadeln, Fächer) setzen ihre Teile nacheinander: --v je Pfad, wie
       bei den Motiven der Startseite. */
    .abzweig path {
      stroke-dasharray: 1;
      animation: ziehen linear both;
      animation-timeline: view();
      animation-range-start: entry calc(4% + var(--v, 0) * 2%);
      animation-range-end: cover calc(24% + var(--v, 0) * 2%);
    }

    /* ══ DIE UNTERSEITEN BEKOMMEN DIESELBE BEWEGUNG ═══════════════════
       Hier stand vorher: „Das ist die einzige Bewegung an den Preisen —
       die Zahlen stehen fertig da, denn hier wird gelesen und nicht
       vorgeführt." Der Satz war zu grob. Richtig ist nicht „keine
       Bewegung", sondern: **alles bewegt sich, nur die Zahlen nicht.**

       Denn der Grund galt immer nur den Beträgen. Eine Überschrift, ein
       Bild, eine Frage darf sich aufdecken — eine Preiszeile nicht, weil
       man beim Vergleichen zurückspringt und dann nichts blinken soll.
       Genau diese Trennung steht unten: .tarif und .zonen sind
       ausdrücklich ausgenommen.

       Es kommt KEINE neue Geste dazu. .gruppe benutzt „heben" und
       „wischen" der Startseite — dieselbe Bewegung, anderer Ort.
       Eine zweite Sprache wäre der Fehler vom 30.07. (DESIGN-PRINZIPIEN
       § 2: „Eine Seite gibt die Grammatik vor").

       Grundzustand ist überall das fertige Bild: ohne
       animation-timeline-Unterstützung und bei prefers-reduced-motion
       steht alles da, wo es hingehört (§ 8).                          */
    .gruppe .inhalt > *:not(h2):not(.tarif):not(.zonen):not(.linie) {
      animation: heben linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 26%;
    }
    .gruppe .gruppe-titel {
      animation: wischen linear both;
      animation-timeline: view();
      animation-range: entry 4% cover 24%;
    }

    /* Die Strichprobe setzt sich, wie Pigment gesetzt wird: von links
       nach rechts. Dieselbe Maske, die schon die Verteilung macht —
       sie wandert nur einmal durch. Kein zweites Mittel.

       Warum eigene Keyframes je Variante: eine Animation mit „both"
       muss auf dem Zielwert des Grundzustands enden (§ 7). Ombré,
       Lippe und Aquarell haben verschiedene Endmasken, also brauchen
       sie verschiedene Keyframes — eine gemeinsame würde ihre
       Verteilung nach dem Durchlauf überschreiben.                    */
    /* Die Körperachse zeichnet sich von oben nach unten — in der
       Reihenfolge, in der die Zonen am Körper liegen. Erst der Körper,
       dann die Zonen. */
    .ka-achse {
      stroke-dasharray: 1;
      animation: ziehen linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 26%;
    }
    .ka-ast {
      stroke-dasharray: 1;
      animation: ziehen linear both;
      animation-timeline: view();
      animation-range-start: entry calc(6% + var(--v, 0) * 1.1%);
      animation-range-end: cover calc(22% + var(--v, 0) * 1.1%);
    }

    /* Die Spanne zeichnet sich: erst der Massstab, dann die Striche von
       links nach rechts — in der Leserichtung und in der Reihenfolge der
       Beträge, also vom günstigsten zum teuersten. */
    .spanne-achse {
      stroke-dasharray: 1;
      animation: ziehen linear both;
      animation-timeline: view();
      animation-range: entry 2% cover 20%;
    }
    .spanne path:not(.spanne-achse) {
      stroke-dasharray: 1;
      animation: ziehen linear both;
      animation-timeline: view();
      animation-range-start: entry calc(6% + var(--v, 0) * .5%);
      animation-range-end: cover calc(22% + var(--v, 0) * .5%);
    }

    /* Der Auftakt steht über der Falz und bekommt seinen Auftritt beim
       Laden (.auftritt), nicht beim Scrollen — sonst zeichnete er sich nie,
       weil man ihn schon sieht, bevor gescrollt wird. */
    .probe:not(.probe--auftakt) {
      animation: pigment-setzen linear both;
      animation-timeline: view();
      animation-range: entry 2% cover 22%;
    }
    @keyframes pigment-setzen {
      from { -webkit-mask-image: linear-gradient(90deg, #000 0%, transparent 1%);
                     mask-image: linear-gradient(90deg, #000 0%, transparent 1%); }
      to   { -webkit-mask-image: linear-gradient(90deg, #000 100%, transparent 101%);
                     mask-image: linear-gradient(90deg, #000 100%, transparent 101%); }
    }
    .probe--ombre { animation-name: pigment-ombre; }
    @keyframes pigment-ombre {
      from { -webkit-mask-image: linear-gradient(90deg, transparent 0%, transparent 1%);
                     mask-image: linear-gradient(90deg, transparent 0%, transparent 1%); }
      to   { -webkit-mask-image: linear-gradient(90deg, transparent 2%, #000 88%);
                     mask-image: linear-gradient(90deg, transparent 2%, #000 88%); }
    }
    .probe--lippe { animation-name: pigment-lippe; }
    @keyframes pigment-lippe {
      from { -webkit-mask-image: linear-gradient(90deg, transparent 0%, transparent 1%, transparent 2%, transparent 3%);
                     mask-image: linear-gradient(90deg, transparent 0%, transparent 1%, transparent 2%, transparent 3%); }
      to   { -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 34%, #000 66%, transparent 100%);
                     mask-image: linear-gradient(90deg, transparent 0%, #000 34%, #000 66%, transparent 100%); }
    }
    .probe--aquarell { animation-name: pigment-aquarell; }
    @keyframes pigment-aquarell {
      from { -webkit-mask-image: linear-gradient(90deg, transparent 0%, transparent 1%, transparent 2%);
                     mask-image: linear-gradient(90deg, transparent 0%, transparent 1%, transparent 2%); }
      to   { -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 45%, transparent 96%);
                     mask-image: linear-gradient(90deg, transparent 0%, #000 45%, transparent 96%); }
    }

    .zahl {
      animation: zifferheben linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 40%;
    }
    @keyframes zifferheben {
      from { opacity: 0; transform: translateX(.1em); }
      to   { opacity: 1; transform: none; }
    }

    /* Die Pointe hängt an der Zeitachse der Schlussbühne, nicht an der
       eigenen: die letzten Elemente der Seite erreichen ihren eigenen
       cover-Bereich nie ganz — das Schlussbild bliebe sonst ungezeichnet.
       „entry 100%" der Schlussbühne ist exakt das Seitenende.          */
    .knick--schluss {
      animation: knick-schluss linear both;
      animation-timeline: --finale;
      animation-range: entry 46% entry 86%;
    }
    @keyframes knick-schluss {
      0%   { clip-path: inset(0 calc(100% - 2px) 100% 0); }
      55%  { clip-path: inset(0 calc(100% - 2px) 0 0); }
      100% { clip-path: inset(0 0 0 0); }
    }

    .strich--rechts {
      animation: hinaus linear both;
      animation-timeline: --finale;
      animation-range: entry 84% entry 100%;
    }
    @keyframes hinaus {
      from { clip-path: inset(0 100% 0 0); }
      to   { clip-path: inset(0 0 0 0); }
    }

    .logo-buehne--schluss .logo {
      animation: heben linear both;
      animation-timeline: --finale;
      animation-range: entry 30% entry 62%;
    }
  }

  .pfeil { transition: transform .45s var(--schwung); }
  a:hover .pfeil { transform: translateX(.3em); }
  a:hover .pfeil--links { transform: translateX(-.3em); }
  .bild img { transition: filter .6s ease; }
  .bild:hover img { filter: saturate(1.06) contrast(1.14); }
}


/* ══ GRÖSSERE SCHIRME ════════════════════════════════════════════ */

@media (min-width: 900px) {
  .karg { font-size: var(--s-titel); }

  .bild--ort { width: min(78%, 760px); }
  .inhalt--rechts .bild--ort { width: auto; margin-left: min(22%, 220px); }

  /* Über: Text links, Porträt rechts, der Raum quer darunter */
  .inhalt--ueber {
    display: grid;
    grid-template-columns: minmax(0, 1fr) min(32%, 380px);
    column-gap: clamp(32px, 5vw, 90px);
    align-items: start;
  }
  .ueber-text      { grid-column: 1; grid-row: 1; }
  .bild--portraet  { grid-column: 2; grid-row: 1; margin: 0; width: 100%; }
  .bild--ort.bild--studio { grid-column: 1 / -1; grid-row: 2; width: min(78%, 760px); }
}


/* ══ PREISSEITE · leistungen.html ════════════════════════════════════
   Die Startseite nennt nur noch, was es gibt. Hier stehen die Zahlen.

   Dieselbe Bühne, dieselbe Linie — aber die Linie verwandelt sich hier
   nicht. Sie läuft gerade durch und zweigt an jeder Leistungsgruppe
   einen Haarstrich zur Überschrift ab: auf der Startseite führt sie
   etwas vor, hier gliedert sie. Ein Motiv pro Gruppe wäre neun Mal
   dieselbe Vorstellung, nur ohne Bild — das wäre laut, nicht schön.

   ZUORDNUNG NAME → PREIS · das eigentliche Kriterium dieser Seite
   Die alte Wix-Seite setzte Namen und Preise in getrennte Textblöcke;
   die Zuordnung existierte nur im Auge des Betrachters, nicht im
   Dokument. Hier ist jede Zeile EIN <li> mit Name und Preis darin:
     · flex ohne Umbruchmöglichkeit für das Paar — der Name trägt
       flex-basis 0, seine hypothetische Breite ist damit null, also
       kann der Preis niemals in eine eigene Zeile rutschen. Bei 390 px
       bricht der Name intern um, der Preis bleibt auf der ersten
       Grundlinie stehen.
     · Der Preis klebt am Namen (kein rechter Anschlag über die halbe
       Seitenbreite), der Name hält eine Mindestbreite — daraus entsteht
       eine weiche Preisspalte ohne eine einzige Linie, ohne Kasten,
       ohne Zebrastreifen.                                              */

.preis-auftakt { position: relative; }

.preis-kopf {
  position: relative;
  z-index: 1;
  padding-top: calc(var(--leiste) + clamp(10px, 1.6vh, 22px));
  padding-bottom: clamp(30px, 5vh, 58px);
  padding-left: var(--spur);
}
/* Das Logo steht hier so gross wie auf den Rechtstexten. Hinweis für später:
   .logo-buehne trägt dort width: min(100%, 420px), das aber ins Leere geht —
   das Element ist ein <a> und damit inline, eine Breite greift nicht. Beide
   Unterseiten zeigen deshalb ein randbreites Logo. Bewusst nicht angefasst:
   so sehen Impressum, Datenschutz und Preisseite gleich aus. Soll es kleiner
   werden, gehört an DIESE Stelle ein display:block — dann aber auf allen drei
   Unterseiten gleichzeitig. */

.preis-titel {
  font-size: var(--s-schau);
  font-weight: 800;
  /* ACHTUNG BEI UMLAUTEN: .88 ist enger als die Versalhöhe plus Trema.
     Steht auf der zweiten Zeile ein Ä, Ö oder Ü, stossen dessen Punkte in
     die Zeile darüber — gemessen an „Behandlungen erklärt", das sah wie
     ein Fleck aus. Gelöst wurde es durch eine andere Zeile, nicht durch
     eine andere Durchschusshöhe: die enge Setzung ist der Charakter dieser
     Titel. Wer hier einen Umlaut auf Zeile zwei braucht, muss .98 setzen. */
  line-height: .88;
  letter-spacing: -.045em;
  word-spacing: .12em;
  text-transform: uppercase;
  margin-bottom: clamp(22px, 3.6vh, 38px);
}

.preis-auftakt .inhalt { padding-bottom: clamp(30px, 5vh, 58px); }
.preis-auftakt .karg + .nachsatz { margin-top: clamp(12px, 2vh, 20px); }

/* ── Die Körperachse · die Linie wird zu dem, was behandelt wird ─────
   Die Linie dieses Auftritts wird auf der Startseite zur Braue, zum
   Wimpernkranz, zur Laserbahn. Hier wird sie das, was behandelt wird:
   der Körper. Senkrecht von der Stirn bis zu den Beinen, ein Abzweig je
   Zone an der Stelle, wo diese Zone liegt.

   Sie ersetzt ein Raster aus drei Spalten. Das beantwortete „was kostet
   Zone X" — aber nicht die Frage, die davor kommt: „welche Zone ist
   meine?" Vierzehn Namen in drei Spalten sind vierzehn Namen. An einer
   Achse sind sie ein Körper.

   Und sie zeigt die Preislogik, die in der Tabelle unsichtbar war: oben
   drängen sich fünf Zonen zwischen 15 und 25 €, unten steht eine einzige
   für 80. Der Preis folgt der Fläche, die Fläche folgt dem Körper.

   Erzeugt von scripts/koerperachse.py aus den Preisen der Seite — bei
   jeder Preisänderung neu laufen lassen. Das Skript bricht ab, wenn eine
   Zone dazukommt oder wegfällt, statt sie stillschweigend zu übergehen. */
.koerperachse {
  display: block;
  width: 100%;
  max-width: 420px;
  height: auto;
  margin-top: clamp(6px, 1.4vh, 14px);
  overflow: visible;
  fill: none;
  stroke: var(--tinte);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.koerperachse path { vector-effect: non-scaling-stroke; }
/* Die Achse liegt leiser als ihre Äste: sie ist der Körper, nicht die
   Zone — dieselbe Rangfolge wie bei der Spanne. */
.ka-achse { stroke: var(--leise); }
.ka-name, .ka-preis {
  fill: var(--tinte);
  stroke: none;
  font-size: 15px;          /* im viewBox-Mass, skaliert mit */
  font-weight: 500;
  letter-spacing: -.01em;
}
.ka-preis {
  text-anchor: end;
  font-weight: 800;
  font-size: 16px;
}


/* ── Die Spanne · die These der Seite, gezeichnet ────────────────────
   Der Kopf sagt „Von 15 € für die Stirn bis 475 € für fünf Microneedling-
   Sitzungen". Das ist die These dieser Seite, und sie hatte kein Bild.

   Hier steht sie als Linie: ein Strich je verschiedenem Betrag, an der
   Stelle, wo er liegt. Linear skaliert, nicht logarithmisch — die Ballung
   im unteren Drittel IST die Aussage. 22 der 36 Beträge liegen unter
   160 €, und ganz rechts steht einsam das Fünferpaket.

   Sie ist ERZEUGT, nicht gesetzt: `scripts/spanne.py` liest die sichtbaren
   Preiszeilen und schreibt das SVG neu. Von Hand gezeichnet wäre sie beim
   nächsten Preis falsch, und eine falsche Verteilung ist schlimmer als
   gar keine.

   Kein Diagramm-Vokabular: keine Achse mit Zahlen, kein Gitter, kein
   Kasten. Nur die beiden Enden sind beschriftet, und auch die nur, weil
   ein Strich ohne Anfang und Ende keine Spanne ist.                     */
.spanne {
  display: block;
  width: 100%;
  max-width: 44ch;
  height: auto;
  margin-top: clamp(26px, 4.4vh, 46px);
  overflow: visible;
  fill: none;
  stroke: var(--tinte);
  stroke-width: 1;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.spanne path { vector-effect: non-scaling-stroke; }
/* Die Achse liegt leiser als die Striche darauf: sie ist der Maßstab,
   nicht der Inhalt. */
.spanne-achse { stroke: var(--leise); }
.spanne-marke {
  fill: var(--leise);
  stroke: none;
  font-size: 21px;      /* im viewBox-Maß, skaliert mit */
  font-weight: 600;
  letter-spacing: .12em;
}
.spanne-marke--rechts { text-anchor: end; }


/* ── Verzeichnis · zehn Wege, einmal genannt ─────────────────────────
   Bewusst KEINE Navigationsleiste: nichts, was mitfährt, nichts in
   einem Kasten. Die einzige mitfahrende Zeile dieser Website ist die
   Oberlinie mit der Telefonnummer, und dabei bleibt es. Dies hier ist
   ein Inhaltsverzeichnis — es steht einmal oben und wird beim Lesen
   zurückgelassen, wie das Inhaltsverzeichnis eines Buches.

   Deshalb auch kein Grossbuchstabensatz wie bei .marke: zehn Einträge
   mit .26em Sperrung liest niemand. Hier ist Lesbarkeit wichtiger als
   Register. Die Wörter tragen sich selbst, sie brauchen keine Kästen,
   keine Punkte dazwischen und keine Zähler — nur Abstand.

   Kein aktiver Zustand per :target: auf dieser Seite ist immer genau
   eine Gruppe angesprungen, und eine dauerhaft markierte Zeile im
   Verzeichnis würde behaupten, man befinde sich noch dort, während man
   längst weitergescrollt hat.                                          */
.verzeichnis {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(10px, 1.6vh, 16px) clamp(16px, 2.4vw, 30px);
  margin-top: clamp(28px, 4.6vh, 52px);
  max-width: 44ch;
}
.verzeichnis a {
  /* derselbe clamp wie .nachsatz — kein eigener. Siehe .r-was weiter unten. */
  font-size: var(--s-text);
  font-weight: 500;
  line-height: 1.2;
  color: var(--leise);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: color .25s ease, border-color .25s ease;
}
.verzeichnis a:hover,
.verzeichnis a:focus-visible {
  color: var(--tinte);
  border-bottom-color: var(--akzent);
}

/* Der Sprung landet sonst 19 px unter der festen Oberlinie — gemessen,
   nicht geschätzt. Das reicht gerade, sieht aber nach Zufall aus. Mit
   dem Rand liegt der Gruppentitel nach dem Sprung 60 px frei, also im
   selben Abstand, den die Gruppen ohnehin untereinander halten.        */
.gruppe { scroll-margin-top: var(--leiste); }

/* ── Leistungsgruppe ─────────────────────────────────────────────── */

.gruppe {
  position: relative;
  padding-block: clamp(40px, 6.6vh, 82px);
}

.gruppe-titel {
  position: relative;
  font-size: var(--s-titel);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.035em;
  word-spacing: .1em;
  text-transform: uppercase;
  margin-bottom: clamp(26px, 4.4vh, 46px);
}

/* ── Der Abzweig · der Weg nimmt die Form seines Ziels an ────────────
   Der Abzweig ist der Haarstrich, der die Linienspur mit einer Gruppen-
   überschrift verbindet — der WEG zu dieser Leistung. Bisher war er
   überall derselbe gerade Strich; die Linie tat auf dieser Seite nichts,
   während sie auf der Startseite pro Kapitel ihre Form wechselt.

   Jetzt nimmt er unterwegs die Form dessen an, wohin er führt, und läuft
   an beiden Enden wieder gerade aus — sonst reisst die Verbindung.
   Die Keratin-Glättung ist die schönste davon: dort läuft eine Welle aus,
   bis nur noch die Gerade übrig ist. Das Motiv führt die Leistung vor.

   BEWUSST NICHT die Motive der Startseite kopiert. Dort WIRD die Linie
   zur Leistung, gross und im Bild. Hier ist es der Weg dorthin, in
   Haarstrich-Grösse. Gleiche Grammatik, anderer Sinn — DESIGN-PRINZIPIEN
   § 2. Ein Kapitel hat kein Motiv: „Bedingungen". Regeln sind keine
   Leistung, der Weg dorthin bleibt gerade. Das ist die Aussage.

   viewBox 120 × 36, Grundlinie y = 18. Die Höhe folgt der Breite (0,3),
   und top zieht das halbe Kästchen wieder hoch, damit die Grundlinie
   exakt dort liegt, wo vorher der 1-px-Strich lag — .52em, unverändert.

   vector-effect: non-scaling-stroke, weil der Kasten bei 1440 px 132 px
   breit ist und bei 390 px nur 42: ohne das wäre der Strich dort ein
   Drittel so dick wie hier, und die Haarlinie ist überall dieselbe.     */
.abzweig {
  --abzweig-w: calc(var(--rail) / 2 + var(--luft));
  position: absolute;
  right: 100%;
  width: var(--abzweig-w);
  height: calc(var(--abzweig-w) * .3);
  top: calc(.52em - var(--abzweig-w) * .15);
  overflow: visible;
  fill: none;
  stroke: var(--tinte);
  stroke-width: 1;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.abzweig path { vector-effect: non-scaling-stroke; }

.gruppe .antwort { margin-top: .8em; }

.marke--tarif { margin-bottom: clamp(12px, 2vh, 20px); }
.tarif + .marke--tarif,
.zonen + .marke--tarif,
.regeln + .marke--tarif { margin-top: clamp(30px, 5vh, 54px); }
.antwort + .tarif,
.antwort + .marke--tarif,
.karg + .tarif,
.karg + .marke--tarif,
.karg + .lehrplan { margin-top: clamp(26px, 4.4vh, 46px); }
.tarif + .nachsatz,
.zonen + .nachsatz { margin-top: clamp(12px, 2vh, 20px); }
.tarif + .ruf { margin-top: clamp(30px, 5vh, 54px); }
.lehrplan + .tarif { margin-top: clamp(30px, 5vh, 54px); }

/* ── Die Preiszeile ──────────────────────────────────────────────── */

/* width: fit-content ist hier das Entscheidende. Ohne es wird die Liste so
   breit wie die Textspalte, der Name wächst mit und schiebt den Preis an
   den rechten Anschlag — bei 1440 px klaffen dann 280 px zwischen „Powder
   Brows" und „300 €", und genau das liest sich wieder wie zwei getrennte
   Blöcke. Mit fit-content ist die Liste nur so breit, wie ihr LÄNGSTER
   Name sie braucht: die Preisspalte rückt an die Namen heran und steht
   trotzdem senkrecht untereinander. max-width kappt die Ausreisser, deren
   Name dann intern umbricht — der Preis bleibt auf der ersten Zeile.     */
.tarif {
  width: fit-content;
  max-width: min(100%, 25rem);
}

/* Zwei Rasterspalten, nicht flex: ein Raster hat keine Umbruchmöglichkeit,
   der Preis kann also unter keinen Umständen in eine eigene Zeile rutschen —
   auch bei 320 px nicht, wo eine flex-Zeile mit Mindestbreite noch gebrochen
   ist. Spalte 1 nimmt den ganzen Rest, Spalte 2 ist so breit wie der Preis.
   Weil die Liste selbst nur fit-content breit ist, stehen die Preise damit
   automatisch senkrecht untereinander, ohne feste Spaltenbreite.
   Bricht der Name auf zwei Zeilen, bleibt der Preis auf seiner ERSTEN
   Grundlinie stehen (align-items: baseline = first baseline).            */
.tarif li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  column-gap: clamp(14px, 3vw, 30px);
  padding-block: clamp(6px, 1vh, 10px);
}

.t-was {
  font-size: var(--s-text);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -.005em;
}
.t-preis {
  justify-self: end;
  white-space: nowrap;
  font-size: var(--s-satz);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
/* das „ab" vor einem Startpreis und das Wort statt einer Zahl.
   Der Abstand kommt aus einem echten Leerzeichen im HTML, nicht aus einem
   margin: sonst liest ein Screenreader „ab50 €" und dasselbe landet in der
   Zwischenablage. */
.t-preis i {
  font-style: normal;
  font-size: .5em;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--leise);
}
.t-preis--wort {
  font-size: var(--s-text);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--leise);
}

/* was in einem Paket steckt — eigene Rasterzeile über beide Spalten, leise */
.t-inhalt {
  grid-column: 1 / -1;
  margin-top: .35em;
  font-size: var(--s-text);
  font-weight: 500;
  line-height: 1.5;
  color: var(--leise);
  max-width: 34ch;
}

/* Pakete · das Verkaufsargument, deshalb eine Stufe lauter */
.tarif--paket { max-width: min(100%, 28rem); }
.tarif--paket li { padding-block: clamp(10px, 1.7vh, 18px); }
.tarif--paket .t-was {
  font-size: var(--s-satz);
  font-weight: 700;
  letter-spacing: -.018em;
}
.tarif--paket .t-preis {
  font-size: var(--s-titel);
  letter-spacing: -.042em;
}

/* Einzelposten in den Zonen · eine Stufe leiser */
.tarif--klein { max-width: min(100%, 15rem); }
/* Zwei Spuren statt Fliesstext: Name links, Betrag rechts an der Kante
   seiner Spalte. Als Raster, nicht als Flex mit Anschlag — nur so haben
   alle drei Regionen dieselbe Kante, unabhängig davon, wie lang ihr
   längster Name ist. minmax(0,1fr) statt 1fr, sonst nimmt die Namensspur
   max-content-Breite an und schiebt den Betrag aus der Spalte
   (DESIGN-PRINZIPIEN § 6, Sticky-Welten-Mechanik, zweite Falle). */
.tarif--klein li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  column-gap: .9em;
  padding-block: clamp(5px, .85vh, 8px);
}
/* Die grossen Listen sind fit-content breit — sie sollen nur so breit sein
   wie ihr längster Eintrag. Die Zonenlisten nicht: sie füllen ihre Region,
   sonst richtet jede ihre Preiskante wieder nach ihrem eigenen Inhalt aus,
   und genau das war der Befund. Gemessen vorher: drei Kanten bei 112, 135
   und 153 px vom Spaltenrand. */
.tarif--klein { width: 100%; max-width: none; }
.tarif--klein .t-was { min-width: 0; }
.tarif--klein .t-preis { font-size: var(--s-satz); }

/* ── Die 14 Laserzonen ───────────────────────────────────────────────
   Nach Körperregion gruppiert statt in eine 14-zeilige Kolonne oder in
   ein Raster gestellt. Ein mehrspaltiges Raster über 14 gleichrangige
   Zeilen braucht Spaltenkanten, um lesbar zu bleiben — und damit hätte
   man wieder eine Tabelle, nur ohne Striche. Drei benannte Regionen mit
   vier bis fünf Zeilen sind je einzeln überschaubar und antworten auf
   die Frage, die tatsächlich gestellt wird: „Was kostet meine Zone?"
   Ab Tablet stehen die drei Regionen nebeneinander.                   */

/* Farah, 01.08.2026: „Das laserzonen mit Preise passen gut soll nur nicht
   durcheinander wirken."

   Nachgemessen, woher das Durcheinander kam — es waren zwei Sachen:

   1. Die Spalten waren 169 px breit, die Namen darin 82, 60 und 100 px.
      Jede Region richtete ihre Preise nach ihrem EIGENEN längsten Namen
      aus, weil der Preis am Namen klebt. Drei Spalten nebeneinander,
      drei verschiedene Preispositionen — das Auge sucht eine Kante und
      findet keine.
   2. „Intim (Bikini)" passte als einziger Name nicht in eine Zeile.
      Diese eine Zeile war 62 statt 39 px hoch und schob die ganze dritte
      Region gegen die beiden anderen aus dem Takt.

   Beides ist behoben: die Spalten sind breiter (52 statt 44 rem, engerer
   Spaltenabstand), und in den Zonen steht der Preis am rechten Rand
   SEINER Spalte statt am Namen. Damit haben alle drei Regionen dieselbe
   Preiskante.

   Das ist bewusst anders als bei den grossen Listen darüber, wo der Preis
   am Namen klebt (Begründung dort unter „Die Preiszeile"). Der Grund für
   die Ausnahme: dort ist die Zeile bis zu 700 px breit, ein rechter
   Anschlag risse Name und Betrag auseinander. Hier ist die Spalte 200 px
   schmal — da steht der Betrag ohnehin dicht daneben, und die gemeinsame
   Kante über drei Regionen wiegt schwerer.                              */
.zonen {
  display: grid;
  gap: clamp(26px, 4.4vh, 42px) clamp(20px, 3vw, 44px);
  max-width: min(100%, 52rem);
}
.zone-name {
  font-size: var(--s-text);
  font-weight: 700;
  letter-spacing: -.005em;
  margin-bottom: clamp(8px, 1.4vh, 14px);
}
/* Kein fester Umbruchpunkt, sondern eine Mindestbreite: das Raster teilt
   selbst, sobald genug Platz ist. Die alten Grenzwerte (620 und 980 px)
   rechneten gegen die BILDSCHIRM-Breite, nicht gegen die Breite, die den
   Zonen tatsächlich bleibt — und die ist um die Bildspalte kleiner. Im
   Band 620 bis 1180 px standen deshalb drei Spalten zu je 111 bis 137 px
   nebeneinander, und „Intim (Bikini)" brach als einziger Name um.
   Gemessen: 170 px trägt den längsten Namen samt Betrag (100 + 48 + 15). */
.zonen { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }

/* Abschluss der Preisseite · zurück zur Startseite */
.gruppe--abschluss { padding-bottom: clamp(56px, 9vh, 110px); }
.ruf-zusatz + .preisweg { margin-top: clamp(30px, 5vh, 52px); }

/* ── Ein Bild je Gruppe · GLEICHMASS, nicht Rangfolge ────────────────
   ACHTUNG, DAS IST DER BEWUSSTE GEGENSATZ ZUR STARTSEITE UND KEIN FEHLER.

   Auf index.html folgt die Bildhöhe dem Rang der Leistung (Stufe 1 bis
   600 px, Stufe 2 bis 300 px, Stufe 3 als randbrechendes Band) — dort
   wird eine Dramaturgie erzählt, und Grösse ist ihr Mittel.

   Hier ist jedes Bild GLEICH gross, im GLEICHEN Format, an der GLEICHEN
   Stelle. Denn diese Seite erzählt keine Rangfolge, sie ist eine
   Übersicht: neun Gruppen, gleiches Gewicht. Wer hier Grössen staffelt,
   behauptet eine Wertung, die es nicht gibt — und das Auge fängt an,
   Bilder zu vergleichen statt Preise zu lesen. Deshalb auch ein fester
   Kasten (3:2, object-fit: cover) und nicht das Seitenverhältnis der
   Datei: sechs Fotos sind quer, drei hochkant, und bei gleicher Höhe
   hätten sie neun verschiedene Breiten. Neun verschiedene Breiten sind
   kein Gleichmass, sondern ein Zufall des Dateiformats.

   Keine Bildunterschriften: die Gruppenüberschrift steht schon daneben
   und sagt dasselbe. Auf der Startseite tragen die Unterschriften die
   Erzählung, hier wären sie neun Mal eine Wiederholung.

   Ab 1000 px steht das Bild RECHTS, am inneren Seitenrand, aus dem Fluss
   genommen: die Preisliste ist fit-content breit und lässt dort über
   400 px frei. Die Seite wird dadurch keine Zeile länger (gemessen: bei
   1440 px genau 0 px Zuwachs für neun Bilder), und die neun gleich
   grossen Bilder bilden eine zweite Senkrechte am rechten Rand —
   Gegenstück zur Linienspur links. Darunter, wo die Textspalte die ganze
   Seite ist, läuft das Bild im Fluss unter die Überschrift.

   Warum 1000 px und nicht 900: bei 900 px ist die Spalte zu schmal.
   Gemessen (glyphengenau, nicht am Elementkasten) lief die Frage im
   Keratin-Abschnitt 20 px in die Bildspalte hinein. Und weil ein
   Grenzwert allein das nächste Mal wieder reisst, hält die Textspalte die
   Bildspalte jetzt frei — padding-right, kein Ausprobieren. Die vierzehn
   Laserzonen stehen weit unter dem Bild und holen sich die Spalte per
   negativem Rand zurück, sonst würden sie unnötig schmal.

   Bewegung: Überschrift, Bild und Frage decken sich beim Scrollen auf —
   dieselbe Geste wie auf der Startseite, kein eigenes Vokabular. Die
   PREISZEILEN nicht: beim Vergleichen springt man zurück, und dann darf
   nichts blinken. Die Ausnahme steht ausdrücklich im Bewegungsblock
   (.tarif und .zonen sind vom „heben" ausgenommen).                     */

/* Die Bildspalte wird aus der BREITE gerechnet, nicht aus einer Wunschhöhe.
   Vorher stand hier eine Höhe (max. 196 px), aus der die Breite folgte — das
   Ergebnis war ein 281 px breites Bild in einer 516 px breiten freien Spalte.
   Gemessen bei 1440 px: 235 px der reservierten Spalte blieben leer, und alle
   neun Motive sind Detailaufnahmen (Pinzette am Wimpernkranz, Handstück an der
   Oberlippe). Bei dieser Grösse erkennt man sie nicht — man sieht neun graue
   Flecken. Die Spalte gibt jetzt die Breite vor, die Höhe folgt aus 3:2.

   Die Obergrenze 440 px ist keine Geschmacksfrage, sondern die Auflösung der
   schwächsten Vorlage: foto-academy-portraet.jpg ist 662 px breit. Bei 440 px
   Anzeigebreite bleiben 1,5 Bildpunkte je CSS-Pixel — auf einem 2×-Schirm
   gerade noch vertretbar. Wer die Spalte weiter aufzieht, braucht zuerst
   grössere Dateien (siehe Bildnachweis-Notiz im Impressum).                  */
.gruppe {
  --bildspalte: clamp(240px, 31vw, 440px);
  --bildhoehe: calc(var(--bildspalte) * 2 / 3);
  --bildluft: clamp(28px, 3vw, 64px);
}

.bild--tarif {
  /* Unter 1000 px füllt das Bild die Textspalte ganz aus. Ein 177 px breites
     Bild in einer 350 px breiten Spalte sieht aus wie ein Fehler, nicht wie
     eine Entscheidung — und lesbar war es ohnehin nicht. Volle Breite kostet
     Höhe (gemessen bei 390 px: die Seite wächst von 8340 auf rund 9400 px),
     aber eine Übersicht, in der man die Bilder nicht erkennt, spart die Höhe
     an der falschen Stelle. */
  width: 100%;
  /* Das Bild nimmt die Luft mit, die zwischen Überschrift und Preisliste
     sowieso stand: negatives margin-top gegen die margin-bottom der
     Überschrift, dafür voller Abstand nach unten. Ab 1000 px ist das Bild
     absolut gesetzt und kostet null — dort wird die Seite durch neun Bilder
     keine Zeile länger. */
  margin-top: calc(-1 * clamp(12px, 2vh, 22px));
  margin-bottom: clamp(20px, 3vh, 34px);
}
.bild--tarif img {
  aspect-ratio: 3 / 2;
  object-fit: cover;
  object-position: var(--op, center);
}

/* ── Die Strichprobe · vier Techniken, ein Punkt ─────────────────────
   NUR auf behandlungen.html.

   Die Linie dieses Auftritts ist auf der Startseite eine Haarlinie, auf der
   Preisseite ein Rückgrat mit Abzweigen. Hier wird sie aus der Nähe gezeigt —
   und aus der Nähe ist sie kein Strich, sondern eine Reihe von Punkten.
   Das ist keine Metapher: Permanent Make-up IST Pigment, Punkt für Punkt
   gesetzt. Die vier Techniken unterscheiden sich in nichts anderem als darin,
   wie die Punkte stehen.

   Deshalb ist es immer DERSELBE Punkt, nur anders verteilt:
     Powder   gleichmässig dicht           — der pudrige Effekt
     Ombré    von links einsetzend         — der Verlauf
     Lippe    in der Mitte dicht, aussen dünn — die Schattierung der Lippe
     Aquarell feiner, weiter, ein Durchgang  — der zarte Farbhauch

   Die Probe steht über der Frage; der Antwortsatz darunter benennt, was man
   gerade gesehen hat. Zeigen, dann benennen — nie umgekehrt.

   Zur Technik, weil es wie ein Anti-Pattern aussehen könnte: Die Verteilung
   entsteht durch eine MASKE, nicht durch einen sichtbaren Farbverlauf. Zu
   sehen sind ausschliesslich Punkte, die dünner werden. Ein Verlauf als
   Fläche wäre der KI-Look, den DESIGN-PRINZIPIEN § 4 benennt — hier liegt
   keiner.                                                                    */
.probe {
  display: block;
  width: clamp(96px, 26vw, 168px);
  height: clamp(18px, 3.4vw, 26px);
  margin-bottom: clamp(14px, 2.2vh, 22px);
  color: var(--tinte);
  background-image: radial-gradient(circle, currentColor .9px, transparent 1.1px);
  background-size: 4px 4px;
}
.probe--ombre {
  -webkit-mask-image: linear-gradient(90deg, transparent 2%, #000 88%);
          mask-image: linear-gradient(90deg, transparent 2%, #000 88%);
}
.probe--lippe {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 34%, #000 66%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 34%, #000 66%, transparent);
}
.probe--aquarell {
  background-image: radial-gradient(circle, currentColor .6px, transparent .9px);
  background-size: 6.5px 6.5px;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 45%, transparent 96%);
          mask-image: linear-gradient(90deg, transparent, #000 45%, transparent 96%);
}

/* Die Prämisse im Kopf von behandlungen.html: dieselbe Probe, nur lang.
   Sie sagt, was die ganze Seite voraussetzt — aus der Nähe ist die Linie
   dieses Auftritts keine Linie, sondern eine Reihe von Punkten. Die vier
   Techniken darunter sind Abwandlungen davon.

   Gleichmässig verteilt und ohne Maske: eine Verteilung wäre schon eine
   Technik, und hier ist noch keine gemeint. Nur der Punkt selbst. */
.probe--auftakt {
  width: 100%;
  max-width: 44ch;
  height: clamp(26px, 4.4vw, 40px);
  margin-top: clamp(30px, 5vh, 54px);
  margin-bottom: 0;
}
/* Nach einer Antwort beginnt ein neuer Block — die Probe braucht denselben
   Abstand wie eine Frage, sonst klebt sie am vorigen Absatz. */
.antwort + .probe { margin-top: clamp(34px, 5.6vh, 60px); }
/* Steht eine Probe über der Frage, hat die Frage ihren Abstand schon von der
   Probe bekommen und darf ihren negativen Rand nicht mehr anwenden. */
.probe + h3.frage { margin-top: 0; }


/* ── Bedingungen · Regel und Erklärung ───────────────────────────────
   Farah hat beide Regelwerke als Grafik geschickt: helles Tuch, Serifen-
   schrift, Kreissymbole. Hier steht der Text, nicht das Bild. Ein Bild
   mit Text ist für Google, für Vorleseprogramme und für die Suche im
   Browser schlicht nicht vorhanden — und Bedingungen sind genau das,
   was jemand gezielt sucht.

   Gebaut wie eine Preiszeile ohne Preis: links das Stichwort, darunter
   der Satz. Keine Symbole — die Kreise der Vorlage sind Dekoration und
   sagen nichts, was das Stichwort nicht schon sagt. Kein Kasten, keine
   Trennlinien: die Abstände gliedern, so wie überall auf dieser Seite.

   Die Erklärung ist auf 52ch begrenzt, nicht auf die 46ch der Antworten:
   diese Sätze sind Kleingedrucktes, das man am Stück liest, keine
   Erzählung.                                                            */
.regeln { margin-top: clamp(4px, 1vh, 10px); }
.regeln li {
  margin-bottom: clamp(20px, 3.2vh, 34px);
  max-width: 52ch;
}
.regeln li:last-child { margin-bottom: 0; }
/* Die beiden Grössen sind KEINE neuen Stufen: r-was übernimmt den clamp von
   .t-was, r-text den von .nachsatz — Zeichen für Zeichen. Beim ersten Anlauf
   hatte ich hier eigene clamp()-Werte erfunden (1rem/3vw/1.25rem und
   .85rem/2.4vw/1rem). Gemessen ergab das bei 390 px 13,6 px neben den 13,1 px
   des .nachsatz und bei 1440 px 20,0 px neben den 20,5 px des .t-was — also
   genau die Beinah-Dubletten, die DESIGN-PRINZIPIEN § 6 als Schlamperei
   benennt. Eine Stufe, die sich um einen halben Pixel unterscheidet, liest
   niemand als Hierarchie.                                                    */
.r-was {
  display: block;
  font-size: var(--s-text);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -.012em;
}
.r-text {
  display: block;
  margin-top: .3em;
  font-size: var(--s-text);
  font-weight: 500;
  line-height: 1.55;
  color: var(--leise);
}


/* ── Das Porträt läuft ganz · die eine Ausnahme ──────────────────────
   Acht Kästen im gleichen Mass, einer nicht: die Academy. Das ist keine
   Aufweichung der Regel darüber, sondern dieselbe Ausnahme, die die
   Startseite schon kennt (.bild--portraet, „die Inhaberin ist keine
   Leistung"). Die acht anderen Bilder zeigen eine Behandlung — dort ist
   der gleiche Kasten das Argument, weil keine Leistung über der anderen
   steht. Farah Hakimie steht in keiner dieser Reihen.

   Praktisch war der Beschnitt hier ohnehin der schlechteste der neun:
   662 × 1102 in einen 3:2-Kasten heisst 60 Prozent der Höhe wegschneiden.
   Übrig blieb ein Kopf im Querformat — von einem Porträt.

   Warum 0,7 der Spaltenbreite und nicht die ganze: bei voller Breite wäre
   das Bild 733 px hoch und liefe unten aus dem Abschnitt heraus in den
   Termin hinein. Mit 0,7 ist es 513 px hoch und bleibt drin. Hochkant und
   schmaler als die übrigen acht ist es damit sowieso — genau das macht es
   als Ausnahme lesbar und nicht als Fehler.

   Unter 760 px läuft es wie alle anderen in der Spaltenbreite mit, nur
   eben hoch statt quer.                                                 */
.bild--voll img {
  aspect-ratio: auto;
  object-fit: fill;
}

/* Die Seitenspalte beginnt bei 760 px, nicht erst bei 1000.
   Der alte Grenzwert stammt aus der Zeit, als die Textspalte sich die Breite
   noch mit dem Bild teilen musste; seit die Spalte per padding-right
   freigehalten wird, kann eine Kollision nicht mehr auftreten. Und der Grund,
   ihn zu senken, ist gemessen: mit einem vollbreiten Bild im Fluss wuchs die
   Seite im Band 768–999 px auf 11 300 bis 12 200 px — dort ist die Spalte
   568 bis 739 px breit, ein 3:2-Bild darin also bis zu 493 px hoch. Neun
   davon sind eine Diashow, keine Preisübersicht. Ab 760 px steht das Bild
   deshalb seitlich; die Textspalte bleibt dabei 424 px breit und damit
   lesbar. Unter 760 px läuft es im Fluss und füllt die Spalte ganz.          */
@media (min-width: 760px) {
  /* .inhalt ist position:relative — das Bild verlässt damit den Fluss und
     kostet keine Höhe. Kein Raster: ein Raster müsste das Bild über alle
     Zeilen spannen, und die Zeilenzahl ist je Gruppe verschieden. */
  .bild--tarif {
    position: absolute;
    top: 0;
    right: 0;
    width: var(--bildspalte);
    margin: 0;
  }
  /* Das Porträt schmaler, damit es nicht aus seinem Abschnitt läuft —
     Begründung oben unter „Das Porträt läuft ganz". Es bleibt rechts
     bündig, die Senkrechte am Seitenrand reisst also nicht. */
  .bild--voll { width: calc(var(--bildspalte) * .7); }
  /* Die Spalte wird freigehalten, nicht gehofft — aber NUR dort, wo auch ein
     Bild steht. Gemessen bei 1440 px: „Bedingungen" und die beiden Abschlüsse
     hielten 483 px frei und stellten nichts hinein. DESIGN-PRINZIPIEN § 6 nennt
     genau diesen Fall: „Wer den Platz reserviert, muss ihn füllen. […] Ein
     reservierter, leerer Kasten neben einer linksklebenden Überschrift ist kein
     Weissraum." Der Grund ist, dass die Seite acht Mal vorher zeigt, dass dort
     etwas hingehört — die Leerstelle liest sich als unfertig, nicht als Luft.

     Die drei Abschnitte haben kein Bild und sollen keins bekommen: sie sind
     Text (Regeln) und Abschluss. Also wird dort auch nichts reserviert.       */
  .gruppe:has(.bild--tarif) .inhalt { padding-right: calc(var(--bildspalte) + var(--bildluft)); }
  .gruppe .zonen  { margin-right: calc(-1 * (var(--bildspalte) + var(--bildluft))); }

  /* Kein Abschnitt darf kürzer sein als sein eigenes Bild. Sonst ragt das Bild
     aus dem Abschnitt heraus und trifft das Bild des nächsten — gemessen ab
     1440 px zwischen „Lash- & Browlifting" (kürzester Abschnitt, zwei Zeilen)
     und „Dioden-Laser". Die Mindesthöhe ist die Bildhöhe, nicht mehr. */
  .gruppe .inhalt { min-height: var(--bildhoehe); }
}


/* ══ RECHTSTEXTE · Impressum und Datenschutz ═════════════════════
   Dieselbe Bühne, dieselbe Linie, nur ohne Wandlung: hier gibt es
   nichts vorzuführen, hier muss man lesen können. Deshalb ist dies
   die einzige Stelle der Seite mit echten Absätzen.                */

.recht-seite { position: relative; padding-block: 0 clamp(70px, 12vh, 140px); }

.recht-kopf {
  padding-top: calc(var(--leiste) + clamp(10px, 1.6vh, 22px));
  padding-bottom: clamp(34px, 6vh, 70px);
  padding-left: var(--spur);
}
.recht-kopf .logo-buehne { width: min(100%, 420px); }

/* Rücklink im Kopf — auf den Rechtstexten und auf der Preisseite */
.zurueck {
  display: inline-block;
  margin-top: clamp(20px, 3.4vh, 34px);
  font-size: var(--s-fein);
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--leise);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.zurueck:hover,
.zurueck:focus-visible { border-bottom-color: currentColor; }

.recht-seite h1 {
  font-size: var(--s-haupt);
  font-weight: 800;
  line-height: .92;
  letter-spacing: -.045em;
  text-transform: uppercase;
  margin-bottom: clamp(28px, 5vh, 56px);
}

.recht-seite h2 {
  margin: clamp(40px, 6.5vh, 76px) 0 clamp(12px, 2vh, 18px);
  font-size: var(--s-klein);
  font-weight: 700;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--leise);
}
.recht-seite h3 {
  margin: clamp(24px, 4vh, 40px) 0 clamp(8px, 1.4vh, 12px);
  font-size: var(--s-satz);
  font-weight: 700;
  letter-spacing: -.01em;
}

.recht-seite p,
.recht-seite li {
  font-size: var(--s-text);
  font-weight: 500;
  line-height: 1.72;
  max-width: 62ch;
}
.recht-seite p + p { margin-top: .9em; }
.recht-seite ul { margin: .9em 0 0; }
.recht-seite li { padding-left: 1.9em; position: relative; margin-bottom: .5em; }
.recht-seite li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .82em;
  width: 1.1em;
  border-top: 1px solid var(--leise);
}
.recht-seite a { text-decoration: none; border-bottom: 1px solid currentColor; }

.recht-seite .anschrift-block {
  font-size: var(--s-satz);
  font-weight: 600;
  line-height: 1.6;
  letter-spacing: -.01em;
}
.recht-seite .luecke {
  font-size: var(--s-text);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--leise);
}

.recht-schluss {
  margin-top: clamp(56px, 9vh, 110px);
  padding-top: clamp(24px, 4vh, 40px);
  border-top: 1px solid #ddd9d4;
  display: flex;
  flex-wrap: wrap;
  gap: 1.6em;
  font-size: var(--s-text);
  font-weight: 600;
  color: var(--leise);
}
.recht-schluss a { text-decoration: none; border-bottom: 1px solid transparent; }
.recht-schluss a:hover,
.recht-schluss a:focus-visible { border-bottom-color: currentColor; }

/* ══ KI-KENNZEICHNUNG · Art. 50 EU-KI-VO ═══════════════════════════════
   Die acht Behandlungsmotive sind erzeugt (BILDER-PROMPTS.md,
   PRUEFBERICHT.md § 18) und fotorealistisch — sie brauchen ein sichtbares
   Label am Bild, nicht im Impressum. Zwei Formen, beide in der Stimme der
   fein-Beschriftung:
   1. Wo eine Bildunterschrift steht (Startseite), haengt „· KI-generiert"
      an der Unterschrift — gleiche Zeile, gleicher Ton, --leise auf
      --papier misst 5,2:1.
   2. Wo keine steht (Preis- und Behandlungsseite, .bild--tarif), sitzt
      der Vermerk als Ecke AUF dem Bild: Papier auf Tinte .78, auf jedem
      Motiv >= 4,5:1. text-transform bleibt aus, damit woertlich
      „KI-generiert" dasteht. */
figcaption.ki-vermerk {
  /* figcaption.ki-vermerk statt .ki-vermerk: gleiche Spezifitaet wie
     `.bild figcaption` (0,1,1) und spaeter in der Datei — sonst gewinnen
     dessen text-transform und --leise, und der Vermerk misst auf dem
     dunklen Grund nur noch 3:1. */
  position: absolute;
  right: .55rem;
  bottom: .55rem;
  margin: 0;
  font-size: var(--s-fein);
  font-weight: 600;
  letter-spacing: .26em;
  text-transform: none;
  color: var(--papier);
  background: rgba(17, 17, 17, .78);
  padding: .5em .55em .45em .7em; /* rechts weniger: der Sperrsatz traegt Luft im Buchstaben */
  pointer-events: none;
}
/* Unter 760 px liegt .bild--tarif im Fluss (statisch) — der Vermerk braucht
   dort einen eigenen Anker. Ab 760 px ist die Figur selbst absolut gesetzt
   (siehe oben), dann anchert er von allein richtig. */
@media (max-width: 759.98px) {
  .bild--tarif { position: relative; }
}

/* ══ DIE ZEICHEN UND DER LAGEPLAN ═══════════════════════════════════════
   Instagram und TikTok bekommen ihr Zeichen, der Anschrift wird eine
   Karte beigestellt.

   WARUM DIE KARTE GEZEICHNET IST UND NICHT EINGEBETTET
   Die Seite laeuft mit script-src 'none' und frame-src 'none'. Eine
   Maps-Einbettung braeuchte beides und waere ohne Einwilligung obendrein
   der bekannteste Abmahngrund im deutschen Web. Die Karte ist deshalb ein
   eigenes SVG aus OpenStreetMap-Daten, das hier liegt — der Besucher laedt
   nichts von fremden Servern. Erzeugt von scripts/lageplan.py.

   Die Nennung "Kartendaten © OpenStreetMap-Mitwirkende" ist nach ODbL
   Pflicht und steht sichtbar darunter. Nicht wegkuerzen.

   ZU DEN ZEICHEN
   Beide sind fremde Marken. Sie stehen einfarbig und nur dort, wo sie auf
   das jeweilige Profil verweisen — so sehen es die Markenrichtlinien beider
   Anbieter vor. Nicht einfaerben, nicht verzerren, nicht als Schmuck
   verwenden.                                                              */

.marke-zeichen {
  width: 1.15em;
  height: 1.15em;
  flex: none;
  vertical-align: -.24em;
  margin-right: .55em;
}
.mz-strich { fill: none; stroke: currentColor; stroke-width: 1.7; }
.mz-punkt  { fill: currentColor; }

/* Zeichen und Wort duerfen nicht auseinanderreissen: sonst steht das
   Zeichen allein am Zeilenende und der Name in der naechsten Zeile. */
.handle a { display: inline-flex; align-items: baseline; }
.marke-wort { display: inline; }

.lageplan {
  margin: clamp(22px, 3.4vh, 38px) 0 0;
  /* Genau so breit, wie die Zeichnung entworfen ist (380 viewBox-Einheiten).
     Schmaler dargestellt schrumpft die Beschriftung mit — bei 300 px kamen
     die Strassennamen mit 5 px an und waren nicht mehr zu lesen. */
  max-width: 380px;
}
.lageplan img {
  display: block;
  width: 100%;
  height: auto;
  /* Kein Rahmen. Die inverse Fassung hat denselben Grund wie der
     Schlussblock — sie soll aufgehen, nicht als Kasten daraufsitzen.
     Die helle Fassung mit Rahmen leuchtete hier wie ein Fenster und zog
     mehr Aufmerksamkeit als die Anschrift, der sie beigestellt ist. */
}
.lageplan figcaption {
  margin-top: .7em;
  font-size: var(--s-fein);
  letter-spacing: .07em;
  text-transform: uppercase;
  opacity: .62;
}

/* Ab mittlerer Breite steht die Karte NEBEN der Anschrift statt darunter —
   dort ist die Spalte breit genug, und "neben der Adresse" war der
   Auftrag. Darunter bleibt sie unter der Anschrift, weil eine 300 px
   breite Karte neben drei Zeilen Text am Handy beides erdrueckt. */
@media (min-width: 620px) {
  .schluss-kontakt .inhalt:has(.lageplan) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: clamp(28px, 5vw, 64px);
    align-items: start;
  }
  .schluss-kontakt .inhalt > .wandel,
  .schluss-kontakt .inhalt > .rechtsweg { grid-column: 1 / -1; }
  .lageplan { grid-column: 2; grid-row: 2 / span 2; margin-top: 0; }
}

/* Nur die Zeichen, nebeneinander. Der Name steht nicht mehr daneben —
   er steckt im aria-label, sonst liest ein Screenreader die nackte URL vor.

   TIPPFLAECHE: das Zeichen ist rund 22 px gross, WCAG 2.5.8 verlangt 24.
   Deshalb sitzt jeder Verweis in einer 44-px-Flaeche — das ist die Groesse,
   die sich mit dem Daumen sicher trifft, und sie ist unsichtbar. */
.handle--zeichen {
  display: flex;
  flex-direction: row;         /* .handle steht auf column — hier nebeneinander */
  align-items: center;
  gap: .35em;
  margin-left: -11px;          /* die unsichtbare Flaeche zurueckrechnen,
                                  damit das Zeichen an der Satzkante steht */
}
.handle--zeichen a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
}
.handle--zeichen .marke-zeichen {
  width: 22px;
  height: 22px;
  margin: 0;
  vertical-align: 0;
}

/* Der Unterstrich der Textverweise ergibt ohne Text keinen Sinn — er saesse
   unter dem Zeichen wie ein abgerutschter Balken. */
.handle--zeichen a,
.handle--zeichen a:hover,
.handle--zeichen a:focus-visible { border-bottom-color: transparent; }
.handle--zeichen a:hover .marke-zeichen { opacity: .6; }

/* Ohne Text und ohne Unterstrich braucht die Tastatur einen eigenen
   sichtbaren Zustand — sonst ist beim Durchtabben nicht zu sehen, wo man
   steht (WCAG 2.4.7). */
.handle--zeichen a:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: -6px;
  border-radius: 4px;
}

/* ══ DIE EINZELNEN SCHULUNGEN ═══════════════════════════════════════════
   Farahs Übersichtsblatt zeigt fünf Karten nebeneinander. Karten kann diese
   Seite nicht — sie hat keine (DESIGN-PRINZIPIEN § 4). Die Rangfolge, die
   dort die Kästen tragen, tragen hier Reihenfolge und Grad: die Kombi steht
   oben und ausführlich, die vier einzelnen darunter als Liste.

   Aufbau je Zeile wie bei .tarif — Name links, Dauer rechts, Trennlinie
   darunter. Statt eines Preises steht die Dauer an der Stelle, an der man
   auf dieser Seite den Preis erwartet. Das ist die Absicht: die Schulungen
   haben keinen Preis auf der Seite, aber sie haben eine Länge.            */

.kurse { list-style: none; max-width: min(100%, 34rem); }

.kurse li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: clamp(14px, 3vw, 32px);
  padding-block: clamp(14px, 2.4vh, 24px);
  border-bottom: 1px solid color-mix(in srgb, var(--tinte) 14%, transparent);
}
.kurse li:first-child { border-top: 1px solid color-mix(in srgb, var(--tinte) 14%, transparent); }

.k-was {
  font-size: var(--s-satz);
  font-weight: 600;
  letter-spacing: -.01em;
  /* „Wimpernverlängerung" ist das längste Wort dieser Liste und brauchte
     bei 320 px fünf Pixel mehr, als die Spalte hergab — gemessen 169 gegen
     164. Ein abgeschnittener Kursname ist schlimmer als eine Trennung, also
     darf das Wort umbrechen. Nur hier, nicht in den Preiszeilen: dort steht
     die Zahl daneben, und eine getrennte Leistung neben einer Zahl liest
     sich als zwei Angaben. */
  overflow-wrap: break-word;
  hyphens: auto;
}
.k-dauer {
  font-size: var(--s-klein);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  align-self: baseline;
  white-space: nowrap;
  opacity: .72;
}
/* Der Inhalt laeuft ueber beide Spalten — er gehoert zum Namen, nicht neben
   die Dauer. Rechts eingerueckt bliebe er in einer 15-Zeichen-Spalte haengen. */
.k-inhalt {
  grid-column: 1 / -1;
  margin-top: .5em;
  font-size: var(--s-text);
  line-height: 1.5;
  max-width: 46ch;
  opacity: .78;
}

.lehrplan + .marke--tarif,
.kurse + .nachsatz { margin-top: clamp(30px, 5vh, 54px); }

/* Die Nennung der vier einzelnen Schulungen steht NACH dem Starter-Set und
   soll leiser sein als die Kombi darueber — sonst hebt sie die Rangfolge auf,
   um die es geht.

   KEINE Deckkraft. Der erste Versuch hatte opacity .72, und das ergab 2,95:1
   statt der noetigen 4,5 — denn .unterzeile ist mit var(--leise) bereits
   gedaempft, die Deckkraft daempft ein ZWEITES Mal. Nachgeordnet ist die
   Zeile ohnehin: durch ihre Stellung, ihre Breite und den Abstand darueber.
   Wer Rangfolge ueber Deckkraft macht, zahlt sie beim Kontrast. */
.unterzeile--nach {
  margin-top: clamp(20px, 3.2vh, 34px);
  max-width: 34ch;
}

/* ══ DIE SCHULUNG ALS GRUND ═════════════════════════════════════════════
   Im Auftakt läuft seit dem 18.08.2026 das Schulungsvideo statt des
   Salon-Standbilds. Es liegt auf derselben Fläche und unter denselben
   Regeln wie vorher das Foto (.atmo) — aufgehellt, unscharf, an allen
   Kanten ausmaskiert. Was sich ändert, ist nur: es bewegt sich.

   ZWEI FASSUNGEN, EINE SICHTBAR. Der Film und das Standbild stehen beide
   im Markup. Welches gilt, entscheidet prefers-reduced-motion — und zwar
   in BEIDE Richtungen ausgeschrieben, nicht nur als Ausnahme. Ein Video,
   das per CSS versteckt wird, lädt in manchen Browsern trotzdem; deshalb
   steht am versteckten Film zusätzlich display: none.                    */

.atmo-still { display: none; }

@media (prefers-reduced-motion: reduce) {
  .atmo-film  { display: none; }
  .atmo-still { display: block; }
}

/* ══ DIE ÜBERLEITUNG ZUR ACADEMY ════════════════════════════════════════
   Oben läuft die Schulung, unten steht die Academy — diese Zeile sagt es
   und führt hin. Sie ist der letzte Halt des Auftakts.

   Machart wie die übrigen Wege: Wort, Haarlinie darunter, Pfeil. Kein
   Knopf, kein Kasten, kein gefüllter Grund (§ 4). Der Unterschied zu den
   anderen Wegen ist die Pfeilrichtung — nach unten, weil das Ziel unten
   steht und nicht weiterführt.                                          */

.ueberleitung {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .3em 1.1em;
  margin-top: clamp(26px, 4.4vh, 52px);
  text-decoration: none;
  color: inherit;
}
.ue-was {
  font-size: var(--s-klein);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--leise);
}
.ue-weg {
  font-size: var(--s-satz);
  font-weight: 600;
  letter-spacing: -.01em;
  border-bottom: 1px solid color-mix(in srgb, var(--tinte) 30%, transparent);
  padding-bottom: .12em;
  transition: border-color .3s ease;
}
.ueberleitung:hover .ue-weg,
.ueberleitung:focus-visible .ue-weg { border-bottom-color: var(--akzent); }

/* Der Pfeil nach unten wandert beim Überfahren nach unten, nicht nach
   rechts — sonst zeigt die Bewegung woandershin als das Zeichen. */
.pfeil--ab { display: inline-block; margin-left: .3em; }
@media (hover: hover) {
  .ueberleitung:hover .pfeil--ab { transform: translateY(.25em); }
}

/* ══ FILM IM BILDRAHMEN ═════════════════════════════════════════════════
   Einzelne Abschnitte zeigen statt eines Standbilds eine Aufnahme aus dem
   Studio. Der Rahmen bleibt derselbe (.bild) — nur der Inhalt bewegt sich.

   preload="none" im Markup, damit die Filme nicht schon beim Seitenaufruf
   geladen werden: sie stehen weit unten. Moderne Browser holen sie dann
   erst, wenn sie in Sichtweite kommen. Ohne JavaScript ist das die beste
   Näherung, die es gibt — und die Seite kommt ohne JavaScript aus.        */

.bild-film {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.bild-still { display: none; }

@media (prefers-reduced-motion: reduce) {
  .bild-film  { display: none; }
  .bild-still { display: block; }
}

/* ══ DER SCHULFILM TRÄGT DIE RECHTE SEITE ═══════════════════════════════
   Er stand vorher als Rechteck im Fuss des Auftakts, zwischen der Zahl und
   der Aufzählung. Sadans Urteil dazu: „so ist tot". Er hatte recht — ein
   Kasten, der danebensteht, ohne Bezug zu irgendetwas. § 4 nennt genau das
   als Anti-Pattern.

   Jetzt trägt er die rechte Hälfte und bricht über den Seitenrand hinaus.
   Drei Dinge ändern sich dadurch:

   Er ist gross genug, um zu wirken. Er füllt die Fläche, die vorher leer
   blieb — das war Sadans „zu viel Freiraum". Und er bricht aus dem Raster,
   was § 3 ausdrücklich fordert.

   Die Aufnahme läuft weiterhin unbeschnitten: der Rahmen hat ihr Format.
   Kein Rahmen, kein Schatten, keine runden Ecken.                        */

.auftakt-rest:has(.schulfilm) {
  position: relative;
  /* Höhe des Films plus Luft — sonst ragt er in die Academy und überdeckt
     deren Ziffer. 1.7778 ist 16/9. */
  min-height: calc(clamp(300px, 34vw, 480px) * 1.7778 + 24px);
}

.schulfilm {
  position: absolute;
  /* GERADE — Sadan am 20.08.: „das video gerade machen".
     Messbar: alles auf der Seite endet am Seitenrand (bei 1440 px Fenster
     also auf 1368) — nur der Film lief bis 1440 durch, an die Fensterkante.
     Ein Element, das als einziges anders endet, liest sich nicht als
     Randbruch, sondern als schief. Oben dasselbe: er begann bis zu 40 px
     über dem Auftakt. Jetzt sitzt er bündig in beiden Richtungen. */
  top: 0;
  right: 0;
  /* Von 520 auf 440 zurückgenommen. Er trägt die rechte Seite und darf
     dafür gross sein — aber 924 px Höhe waren mehr als der halbe Schirm,
     und das ist keine Bühne mehr, sondern eine Wand. */
  /* 480 statt 440 — auf Sadans Wunsch „das video vorne etwas größer".
     Er trägt die rechte Seite; die Ziffer bleibt trotzdem frei, weil der
     Verlauf bei 60 Prozent ausläuft und die Ziffer erst darunter beginnt
     (nachgemessen auf vier Breiten). */
  /* 560 statt 480 — Sadan am 20.08.: „das Video größer". Er trägt die
     rechte Seite; die Ziffer bleibt frei, weil der Verlauf bei 60 % ausläuft
     und die Ziffer erst darunter beginnt. */
  /* 608 statt 560 — „und größer bitte", aber nicht weiter: 608 px ist die
     native Breite der Aufnahme (608 x 1080). Darüber wird hochskaliert,
     und Sadans Regel vom 30.07. lautet „die videos sollen scharf sein".
     Ein höher aufgelöstes Original liegt nicht vor — falls Farah eines
     hat, kann der Film hier grösser werden, ohne weich zu werden. */
  width: clamp(300px, 34vw, 480px);

  /* KEIN AUSSCHNITT MEHR — DAS GANZE BILD.
     Zwischenstand vom 20.08., verworfen: ein querformatiger Rahmen mit
     gewähltem Ausschnitt. Er zeigte je nach Moment ein zufälliges Detail —
     mal ein Porträt, mal eine Schulter, nie die Schulung. Die Ursache war
     nicht der Ausschnitt, sondern das Fenster: 605 x 472 auf einem Film
     von 608 x 1080 sind 44 Prozent. Jeder Schnitt darin ist Glückssache.

     Der Auftakt war 492 px hoch — deshalb MUSSTE jeder grosse Hochkantfilm
     beschnitten werden. Jetzt bekommt er die Höhe, die der Film braucht.

     RECHNUNG: vorher 518 breit, davon 472 px sichtbar — rund 244 000 px²
     Motiv. Jetzt 480 x 853, also 409 000. Der Film ist in der Zahl
     schmaler und im Sichtbaren zwei Drittel grösser.

     Frühere Fassung, zur Erinnerung:
     Vorher bestimmte die Maske, was man sieht: die oberen 44 Prozent des
     Films. Nachgesehen (vier Momente über die Filmlänge herausgeschnitten)
     liegt dort überwiegend leere Wand — das Motiv sitzt tiefer im Bild.
     Deshalb zeigte der Auftakt Haare und Hintergrund statt der Schulung.
     Jetzt hat der Rahmen die Höhe, die vorher sichtbar war, und der
     Ausschnitt ist gewählt statt geerbt. */
  margin: 0;
  z-index: 0;                      /* hinter Text und Animation */
}
.schulfilm-film,
.schulfilm-still {
  display: block;
  width: 100%;
  height: 100%;
  /* Beschnitten wird er ohnehin — vorher durch die Maske, unkontrolliert
     immer oben. Die Frage ist nur, WAS man sieht.

     Nachgesehen an vier Momenten über die Filmlänge, für vier Ausschnitte
     (25/40/55/70 Prozent): bei 62 lag der Schnitt auf Porträthöhe, man sah
     Haare und Gesicht, aber nicht die Arbeit. 40 zeigt das Gesicht MIT
     Kontext, die Werkzeuge auf dem Tisch, die beiden Personen bei der
     Schulung und die Behandlung am Auge. Das ist der Film, um den es geht.

     WARUM ÜBERHAUPT BESCHNITTEN: 9:16 mal 605 px Breite sind 1080 px Höhe.
     Der sichtbare Auftakt hat rund 620. Ein unbeschnittener Film dürfte
     hier also nur 349 px breit sein — schmaler als die 518 von vorher.
     Grösser und unbeschnitten schliessen sich in diesem Raum aus. */

  filter: contrast(.96) saturate(.97);
  /* Die untere Kante läuft ins Papier aus, statt hart zu enden — dieselbe
     Machart wie beim Porträt im Über-Kapitel. Ein hartes Ende wäre wieder
     ein Kasten. */
  /* AUSLAUFEN, BEVOR DIE ZIFFER BEGINNT.

     Der Film ist höher als der Auftakt und ragt in den Academy-Abschnitt
     hinein — inhaltlich richtig, denn er IST die Academy. Dort steht aber
     die Riesenziffer, und gemessen überlagerten sich beide auf 323 × 270 px,
     also 87 Prozent der Ziffer. Sadans Urteil: „verdecken die zahl".

     Gerechnet statt geschätzt: Film 253–1122, Ziffer ab 776. Der Übergang
     muss also bei (776 − 253) / 870 = 60 % abgeschlossen sein. Volle Deckung
     bis 30 %, ab 60 % nichts mehr — die Ziffer steht dann frei.

     Der erste Versuch mit 52–94 % reichte nicht: bei 776 war der Film noch
     zu vier Fünfteln da. Ein Verlauf, der DORT beginnt, wo das Hindernis
     steht, ist zu spät. */
  /* Der Verlauf sitzt jetzt auf dem Rahmen statt auf der vollen Filmhöhe;
     50/100 ist dasselbe weiche Auslaufen. Frühere Fassung: 24/49 statt 30/60. Der Film ist von 518 auf 634 px Breite gewachsen
     und damit von 921 auf 1125 px Höhe — die Prozentwerte beziehen sich
     auf diese Höhe, also wanderte das Auslaufende 204 px nach unten, in
     die Ziffer hinein (gemessen: 75 % Deckkraft über der 01 bei 1440 px).
     Die neuen Werte halten das Auslaufende auf derselben absoluten Höhe
     wie vorher. Der Film wird dadurch breiter, ohne tiefer zu reichen.

     22/44 statt 24/49 nach einem A/B gegen den Stand von heute früh: die
     Ziffer lag dort schon bei 0,38 Deckkraft — die frühere Prüfung hatte
     nur den Ziffernanfang betrachtet, nicht ihr Textrechteck. Mit 22/44
     sind es 0,30. Der Film ist also zugleich grösser (634 x 495 sichtbar
     gegen 518 x 553, rund 10 Prozent mehr Fläche) und die Ziffer freier
     als vorher. Beides gemessen, nicht geschätzt. */
  -webkit-mask-image: linear-gradient(to bottom, #000 92%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 92%, transparent 100%);
}
.schulfilm-still { display: none; }

@media (prefers-reduced-motion: reduce) {
  .schulfilm-film  { display: none; }
  .schulfilm-still { display: block; }
}

/* Der Inhalt macht rechts Platz, damit Text und Film sich nicht überlagern. */
@media (min-width: 900px) {
  .auftakt-rest:has(.schulfilm) .inhalt {
    /* Der Film ist 853 px hoch, der Text war 446 — links unten blieben
       gut 400 px leer. Sadans stehende Regel: „nicht zu viel Freiraum".
       Der Inhalt verteilt sich jetzt über dieselbe Höhe wie der Film,
       statt oben zu kleben. */
    min-height: calc(clamp(300px, 34vw, 480px) * 1.7778);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    /* Von 30vw auf 48. Gemessen endete die Wortliste auf 936, der Film
       begann auf 922 — 14 px Überlappung, auf allen vier geprüften
       Breiten. Daher das abgeschnittene „BRAU|E" auf Sadans Bild.
       Der grössere Film braucht entsprechend mehr Platz. */
    padding-right: clamp(280px, 48vw, 700px);
  }
}

/* Am Handy trägt er nichts — dort steht er unter dem Auftakt in voller
   Breite, wo Hochformat ohnehin das natürliche Format ist. */
@media (max-width: 899px) {
  /* Am Handy trägt er nichts — er steht unter dem Auftakt in voller Breite,
     wo Hochformat ohnehin das natürliche Format ist.

     REIHENFOLGE: Im Markup steht der Film VOR dem Inhalt, weil er auf dem
     Schirm rechts danebenliegt. Auf einem Handy hiesse das, er stünde vor
     der Linien-Animation und verdeckte sie — gemessen, nicht vermutet: er
     lag über der Wimper. Die Animation ist das Konzept der Seite und kommt
     zuerst. Flexbox mit order dreht die beiden um, ohne das Markup zu
     ändern (dort bleibt die Lesereihenfolge die des Schirms). */
  .auftakt-rest:has(.schulfilm) { display: flex; flex-direction: column; }
  .auftakt-rest:has(.schulfilm) > .linie     { order: 0; }
  .auftakt-rest:has(.schulfilm) > .inhalt    { order: 1; }
  .auftakt-rest:has(.schulfilm) > .schulfilm { order: 2; }

  .schulfilm {
    position: static;
    width: min(100%, 340px);
    margin: clamp(28px, 5vh, 48px) 0 0;
  }
}


/* ══ FILM HOCHKANT ══════════════════════════════════════════════════════
   Alle Aufnahmen aus dem Studio sind mit dem Handy gedreht, also hochkant.
   Bis zum 19.08.2026 steckten sie in den querformatigen Bildrahmen der
   Fotos — dafür mussten sie beschnitten werden, und zwar auf GEMESSENE
   38 Prozent der Bildhöhe. Zwei Drittel jeder Aufnahme fielen weg.

   Jetzt behalten sie ihr Format und laufen vollständig.

   DIE REGEL, die man dadurch sieht: Foto = quer, Film = hochkant. Das ist
   kein Zufall des Materials, sondern seine Herkunft — Fotos aus der Kamera,
   Filme vom Handy aus der Hand.                                          */

/* Der Rahmen hat das Seitenverhaeltnis der Aufnahme — 9:16, kein
   object-fit. Deshalb ist nichts zu beschneiden. */
.bild--hoch {
  /* 290 statt 340: die Bilder der Seite liegen bei 210 bis 640 px Höhe, ein
     Film mit 604 sass am oberen Ende. Bei 290 Breite sind es 516 — mitten
     in der Reihe. Ein Film ist eine Aufnahme wie jede andere und soll nicht
     dadurch auffallen, dass er grösser ist. */
  --fb: clamp(210px, 27vw, 360px);
  width: var(--fb);
  margin: 0;
}
.bild--hoch .bild-film,
.bild--hoch .bild-still {
  display: block;
  width: 100%;
  height: auto;
  filter: contrast(.96) saturate(.97);
}
.bild--hoch .bild-still { display: none; }
.bild--hoch figcaption { margin-top: .9em; }

@media (prefers-reduced-motion: reduce) {
  .bild--hoch .bild-film  { display: none; }
  .bild--hoch .bild-still { display: block; }
}

/* Am Handy untereinander: dort ist die Spalte zu schmal fuer beides, und
   hochkant ist auf einem Handy ohnehin das natuerliche Format. */
@media (max-width: 760px) {
  .bild--hoch { --fb: min(100%, 320px); }
}

/* Am Handy sitzt die tiefe Ziffer am unteren Rand des Kapitels, der Film
   steht im Fluss darüber — und beide trafen sich: gemessen 111 × 45 px
   Überlappung bei 390 px, in den Kapiteln mit Film.

   Auf dem Schirm passiert das nicht, weil der Film dort neben dem Text
   steht und nicht unter ihm. Deshalb greift die Regel nur schmal.

   Der Zuschlag entspricht der Höhe der Ziffer plus ihrem Abstand — sie
   bekommt damit ihre eigene Zeile unter dem Film, statt darüberzuliegen. */
@media (max-width: 760px) {
  .kapitel:has(.bild--hoch) .inhalt { padding-bottom: clamp(96px, 16vw, 140px); }
}

/* ══ WAS GEKENNZEICHNET WIRD ═══════════════════════════════════════════
   Neunmal stand „Im Studio gefilmt" unter einem Film — bei fünf Filmen auf
   drei Seiten. Das ist Ballast, und es dreht die Logik um: Gekennzeichnet
   gehört die AUSNAHME, nicht die Regel.

   Die Regel ist echtes Material aus dem Studio. Die Ausnahme sind die
   erzeugten Bilder, und die tragen weiterhin ihren Vermerk — dort ist er
   Pflicht, nicht Schmuck. Wo keiner steht, ist die Aufnahme echt.        */


/* ══ KEINE HARTEN KANTEN ════════════════════════════════════════════════
   Sadan am 20.08.: „dass es mir zu eckig ist". Er hat recht, und es
   widerspricht § 4: Die Seite hat keine Kästen — aber jedes Bild und jeder
   Film sass in einem, mit vier scharfen Ecken.

   Der Auftakt-Film zeigte längst, wie es geht: seine untere Kante läuft ins
   Papier aus. Das gilt jetzt für alle. Die Maske greift nur unten und ist
   sehr weich (ab 88 Prozent), damit das Motiv nicht beschnitten wirkt —
   sie nimmt der Kante die Härte, nicht dem Bild den Inhalt.

   Nicht mit border-radius: runde Ecken wären ein Kasten mit runden Ecken,
   und genau das nennt § 4 als KI-Look. Ein Auslaufen ist kein Rahmen.     */
.bild img,
.bild video,
.bild--hoch .bild-film,
.bild--hoch .bild-still {
  -webkit-mask-image: linear-gradient(to bottom, #000 88%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 88%, transparent 100%);
}

/* Der Weg zurück nach oben. Steht am Schluss, wo man ankommt — nicht als
   schwebender Knopf, der beim Lesen im Weg liegt. Der Pfeil zeigt hinauf,
   und beim Überfahren wandert er dorthin. */
.rechtsweg--hoch { margin-bottom: clamp(20px, 3vh, 34px); }
.pfeil--auf { display: inline-block; margin-left: .3em; }
@media (hover: hover) {
  .rechtsweg--hoch a:hover .pfeil--auf { transform: translateY(-.25em); }
}
/* Sanft scrollen, aber nur wenn Bewegung erwünscht ist. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* ══ DIE KOPFLEISTE AUF SCHMALEN SCHIRMEN ═══════════════════════════════
   Gemessen bei 390 px: Der erste Weg begann bei x = −22, ragte also links
   aus dem Bild. Vier Wege brauchten 392 px, das Fenster hat 390.

   Und die Schrift stand bei 8,96 px — unter der kleinsten Stufe der
   Typskala (11,2). Sadans Befund: „oben ist manches so ungerade etwas zu
   klein".

   Beides hat dieselbe Ursache: die Sperrung. .22em sind bei zwölf Zeichen
   rund 24 px allein an Luft zwischen den Buchstaben. Auf schmalen Schirmen
   ist das Platz, den die Schrift selbst braucht.

   Also: weniger Sperrung, dafür grössere Schrift. Das Wort bleibt gleich
   breit, wird aber lesbar — und die Leiste passt wieder ins Bild.        */
@media (max-width: 760px) {
  .oberlinie {
    gap: clamp(10px, 2.6vw, 18px);
    justify-content: space-between;
  }
  .oberlinie-weg,
  .oberlinie-ruf {
    font-size: clamp(9.6px, 2.7vw, 11.2px);
    letter-spacing: .09em;
  }
  /* „Mein" fällt weg — auf einem Handy ist die Leiste zu kurz für einen
     Zusatz, der nichts unterscheidet. Das Ziel bleibt dasselbe. */
  .weg-mein { display: none; }
}

/* Unter 380 px reicht auch das nicht: gemessen ragte die Leiste dort noch
   19 px über den rechten Rand. Das Wort „Behandlungen" ist das längste und
   trägt seine Bedeutung auch verkürzt — die Seite dahinter heisst so. */
@media (max-width: 379px) {
  .oberlinie {
    gap: 8px;
    /* Eigener, knapperer Seitenrand nur für die Leiste. Mit der grösseren
       Schrift brauchte sie bei 320 px genau 5 px mehr, als das Fenster hat;
       der Seitenrand der Seite (20 px) ist die einzige Reserve, die keinen
       Text kostet. Der Rest der Seite behält seinen Rand. */
    padding-inline: 12px;
  }
  /* Sperrung ganz weg und dafür lesbare Schrift. Bei 320 px war die Stufe
     auf 9,6 px gefallen — die gesparte Buchstabenluft geht in die Grösse. */
  .oberlinie-weg, .oberlinie-ruf {
    letter-spacing: 0;
    font-size: clamp(10.5px, 3.3vw, 11.2px);
  }
  .weg-ruf { display: none; }
}

/* ══ ZWEI RESTE IN DER KOPFLEISTE ═══════════════════════════════════════
   Gemessen bei 1440 px: die Lücken stehen exakt auf 40/40/40, alle vier
   Wege haben dieselbe Mitte. Gleichmässig ist sie also. Übrig blieben
   zwei Dinge, die man sieht, ohne sie benennen zu können:

   Der Pfeil schien 1,6 px zu hoch zu sitzen — gemessen gegen die Mitte
   des Links. Diese Messung ist zirkulär: der Pfeil bestimmt die Höhe des
   Links, gegen die er verglichen wird. Gegen die Mitte des Textes selbst
   gemessen steht er auf 0,00 px. Der Befund war meiner, nicht der Seite.

   Blieb einer, und der ist echt: die Schrift stand auf 11,2 px — der untersten Stufe der Skala.
   — der untersten Stufe der Skala. Auf einem 1440er Schirm ist das die
   Grösse einer Fussnote, nicht die einer Navigation. Eine Stufe höher
   (12,5 px) bleibt in der bestehenden Skala, es kommt keine neunte
   Stufe dazu.                                                        */
@media (min-width: 1100px) {
  .oberlinie-weg,
  .oberlinie-ruf { font-size: var(--s-klein); }
}


/* ══ TIPPZIELE ══════════════════════════════════════════════════════════
   WCAG 2.2 verlangt auf Stufe AA (Kriterium 2.5.8) mindestens 24 x 24
   CSS-Pixel für alles, was angetippt wird. Gemessen am 24.08. über sechs
   Seiten: der Rückweg stand auf 12 px Höhe, die Wege in der Kopfleiste auf
   16, „Preise→“ auf 14, „Nach oben↑“ auf 21.

   Links MITTEN IM FLIESSTEXT sind davon ausdrücklich ausgenommen — ihre
   Grösse ergibt sich aus der Zeilenhöhe des Textes, in dem sie stehen.
   Deshalb steht hier eine Liste und keine Regel für alle a-Elemente: die
   Telefonnummer im Impressumsabsatz bleibt, wie sie ist.

   min-height statt padding, damit sich der Textfluss nicht verschiebt —
   der Link wächst um seine Mitte, nicht nach unten. */
.oberlinie-weg,
.oberlinie-ruf,
.zurueck,
.rechtsweg,
.preisweg,
.ueberleitung,
.ruf-zusatz,
.verzeichnis,
/* Bei diesen dreien sitzt die Klasse am UMSCHLAG, nicht am Link — gemessen:
   der Elternteil war korrekt 24 px hoch, das <a> darin blieb bei 21. Getippt
   wird aber der Link, nicht sein Umschlag. */
.rechtsweg > a,
.ruf-zusatz > a,
.verzeichnis > a {
  min-height: 24px;
  display: inline-flex;
  align-items: center;
}

/* ══ SAFARI ZEICHNET MIT ═══════════════════════════════════════════
   Befund vom 29.08.: „die Animation mit dem Strich ist weg."
   Sie war nicht weg — sie hat in Safari nie existiert. Gemessen:

     Chromium   CSS.supports('animation-timeline','view()')  true
                44 gestrichelte Pfade, je eine Animation
     WebKit     dasselbe                                     FALSE
                0 gestrichelte Pfade

   Die gesamte Bewegung liegt in @supports (animation-timeline: view()).
   Safari faellt komplett heraus und zeigt nur den Endzustand.

   DER WEG HIER: derselbe Strich, andere Uhr. Wo scroll-getriebene
   Zeitleisten fehlen, sagt ein winziger Beobachter Bescheid, wenn ein
   Motiv ins Bild kommt, und die Zeichnung laeuft zeitgesteuert ab.

   ZWEI SICHERUNGEN:
   · Ohne JavaScript wird `js-zeichnet` nie gesetzt — dann bleibt es beim
     heutigen Verhalten: die Zeichnung steht fertig da. Niemand verliert
     etwas, wenn das Skript nicht laeuft.
   · Der Beobachter startet gar nicht erst bei prefers-reduced-motion.

   Der Datenschutz sagt „keine Cookies, kein Tracking, keine externen
   Ressourcen". Das Skript setzt nichts, misst nichts und laedt nichts —
   die Zusage bleibt wahr. */

@supports not (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    /* Ungezeichnet nur dort, wo der Beobachter auch wirklich zeichnet */
    .js-zeichnet svg[data-zeichnen] path {
      stroke-dasharray: 1;
      stroke-dashoffset: 1;
    }
    /* Staffelung ueber --v — dieselbe Reihenfolge wie bei den
       scroll-getriebenen Fassungen, nur in Millisekunden statt Prozent. */
    .js-zeichnet svg[data-zeichnen].sichtbar path {
      animation: ziehen-fallback .85s cubic-bezier(.33, 1, .68, 1) both;
      animation-delay: calc(var(--v, 0) * 55ms);
    }
    /* EIGENE Keyframes, und das ist der Grund: `ziehen` ist oben INNERHALB
       von @supports (animation-timeline: view()) definiert. Safari
       ueberspringt diesen Block komplett — die Regel verwies dort also auf
       Keyframes, die es gar nicht gibt, und es passierte nichts.
       Gemessen: Klasse gesetzt, 11 SVG ausgeloest, 0 von 44 Pfaden bewegt. */
    @keyframes ziehen-fallback {
      from { stroke-dashoffset: 1; }
      to   { stroke-dashoffset: 0; }
    }
  }
}
