/* ============================================================================
   laufweite.css — Vorlage „laufweite": Typographic Poster, Rhythmus aus der
   Laufweite. Eine seitenweite Größe --luft (0 eng … 1 weit) steuert echte
   Schriftbreite (wdth-Achse von Anybody), Spationierung, Durchschuss und die
   Grunddrift. Engine (scrollcraft.css/js) bleibt unangetastet: hier nur Tokens
   und eigenes Markup.

   Rollenregel (SPEC §5/BRIEF): eng gehört dem Besucher (Hero, Akt 2, Peak vor
   dem Latch), weit gehört der Kanzlei (Akte 4–6 tragen .weit = --luft 1 lokal).
   Ohne JS und unter reduced-motion ist --luft von Anfang an 1 (K6).
   ========================================================================== */

@font-face {
  font-family: "Anybody";
  src: url("fonts/anybody-var.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 50% 150%;
  font-display: swap;
}
@font-face {
  font-family: "Literata";
  src: url("fonts/literata-var.woff2") format("woff2");
  font-weight: 200 900;
  font-display: swap;
}

:root {
  --luft: 1;                       /* JS setzt 0.1 / 0 / Fahrt / 1 (Latch) */

  --lw-grund-eng:   #D2DDD5;       /* Salbei, dichter (Hero, Akt 2) */
  --lw-grund-weit:  #EEF4F0;       /* hellstes Salbei (ab Peak) */
  --lw-tinte:       #0F1F18;       /* Tintengrün, ≈12:1 / ≈15:1 */
  --lw-tinte-weich: #3B5147;       /* Nebenzeilen, ≈6:1 / ≈7,5:1 */
  --lw-grund: color-mix(in oklab, var(--lw-grund-eng), var(--lw-grund-weit) calc(var(--luft) * 100%));
  --lw-hairline: color-mix(in oklab, var(--lw-tinte) 18%, transparent);

  --sc-canvas:      var(--lw-grund);
  --sc-surface:     var(--lw-grund-weit);
  --sc-ink:         var(--lw-tinte);
  --sc-ink-soft:    var(--lw-tinte-weich);
  --sc-accent:      var(--lw-tinte);
  --sc-accent-ink:  var(--lw-grund-weit);
  --sc-font-display: "Anybody", "Archivo", system-ui, sans-serif;
  --sc-font-text:    "Literata", Georgia, "Times New Roman", serif;

  /* Randzeile (Chrome) und rechter Inhaltsrand */
  --rz-b: 2.75rem;
  --satz-r: max(calc(var(--rz-b) + 0.5rem), var(--sc-gutter));
}

body { color: var(--lw-tinte); }
/* Die Seite ist scrollgetrieben: Chromes Scroll-Anchoring würde bei jeder
   Laufweiten-Änderung oberhalb des Pins die Scrollposition nachziehen und die
   Fahrt gegen sich selbst rückkoppeln. Zusätzlich halten Hero und Akt 2 eine
   feste Höhe (s. u.), damit oberhalb des Peaks nie Layout wandert. */
html { overflow-anchor: none; }

.sr-only {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* Ohne JavaScript (Engine nie gemountet): alles sichtbar, alles weit */
html:not(.sc-ready) [data-sc-cue] { opacity: 1; }
html:not(.sc-ready) :is([data-sc-in], [data-sc-stagger] > *) { opacity: 1; transform: none; }
html:not(.sc-ready) [data-sc-reveal] { clip-path: none !important; }

a { color: inherit; text-decoration-color: var(--lw-tinte-weich); text-decoration-thickness: 1.5px; text-underline-offset: 0.18em; }
@media (hover: hover) and (pointer: fine) {
  a, #lotse-open { transition: color 140ms var(--sc-ease-out), text-decoration-color 140ms var(--sc-ease-out); }
  a:hover { text-decoration-color: var(--lw-tinte); }
}

/* Display-Zeilen: die Laufweite wirkt über font-variation-settings, nie über
   scaleX (K3). Schriftgrad kommt je Element (JS-Fit oder clamp). */
/* Die drei abgeleiteten Größen (SPEC §5.1–5.2) werden AM ELEMENT aufgelöst,
   nicht auf :root: nur so greift ein lokales --luft (.weit, Karte) auf die
   geerbte Rechnung durch. */
.display, .wand, .satz, .luft, .titel, .gebiet-begriff, .bz, .rz, .lotse-titel, .karte-kanzlei, .karte-tel a, .demotag, .gebiet-problem {
  --wdth:   calc(50 + 75 * var(--luft));                 /* 50 → 125 */
  --spat:   calc((-0.04 + 0.10 * var(--luft)) * 1em);    /* −0,04em → +0,06em (Ursprungswert; für Akt 2 auf .satz gezielt entschärft, siehe unten und SPEC §13) */
  --zeilen: calc(0.82 + 0.30 * var(--luft));             /* 0,82 → 1,12 */
  font-family: var(--sc-font-display);
  font-variation-settings: "wdth" var(--wdth), "wght" var(--wght, 800);
  letter-spacing: var(--spat);
  line-height: var(--zeilen);
}
/* Mit JS sind Fit-Zeilen einzeilig (Grad per Messung); ohne JS brechen sie
   normal um (clamp-Fallback), damit nichts überläuft (K6). */
html.js-fit .fitwall .zeile { white-space: nowrap; }
/* Spationierung je Zeile am eigenen Grad auflösen (em), nicht am Block erben */
.fitwall .zeile { display: block; letter-spacing: var(--spat); }
.fitwall .zi { display: inline; }
/* Hero-Zeilen brauchen die Glue-Fahrt zusätzlich zur normalen Laufweite;
   .zeile hat oben eine eigene letter-spacing-Deklaration (nicht geerbt vom
   .wand-Element), daher hier gezielt überschrieben (gleiche Spezifität,
   gewinnt per Position nach der geteilten .fitwall-Regel). */
.wand .zeile { letter-spacing: calc(var(--spat) + var(--glue, 0) * 1em); }

/* Weit gehört der Kanzlei: Akte 4–6 stehen immer weit, unabhängig vom Latch. */
.weit { --luft: 1; }

/* ============================================================ Randzeile */
.randzeile {
  position: fixed; top: 0; right: 0; z-index: var(--sc-z-chrome);
  width: var(--rz-b); height: 60vh; height: 60svh;
  display: flex; flex-direction: column; align-items: center;
  padding-top: 1rem;
  pointer-events: none;
}
.rz {
  margin: 0;
  writing-mode: vertical-rl;
  transform: rotate(180deg);          /* liest von unten nach oben (Buchrücken) */
  --wght: 600;
  font-size: 0.82rem;
  line-height: var(--rz-b);           /* = Zeilenbreite = Tap-Fläche quer */
  letter-spacing: calc((0.03 + 0.15 * var(--luft)) * 1em);
  white-space: nowrap;
  color: var(--lw-tinte);
  pointer-events: auto;
}
.rz-sep { margin-block: 0.7em; opacity: 0.55; }
/* inline-block: erst damit ist die Block-Größe des Links (quer zur Zeile) die
   volle Zeilenbreite = Tap-Fläche ≥ 44px; als reines Inline wäre sie nur die
   Schrifthöhe (gemessen 13–18px). */
.rz-tel { display: inline-block; line-height: var(--rz-b); text-decoration: none; padding-inline: 0.4em; }
.rz-tel:hover { text-decoration: underline; }
.rz-demo { color: var(--lw-tinte-weich); }

/* ============================================================ Akt 1 · Hero */
/* Feste Höhe (nicht min-height): während der Peak-Fahrt ändern sich Durch-
   schuss und Breite der Wand (offscreen); wüchse der Hero dabei mit, würde der
   gepinnte Peak darunter verschoben. Der Fit hält die Wand innerhalb der Höhe,
   overflow: clip fängt den Übergangszustand ab. */
/* .hero ist jetzt der Pin-Rahmen (Höhe/Sticky/Clip kommen von der Engine
   über [data-sc-stage] -> .sc-stage, siehe scrollcraft.css); das eigene
   Layout (Flex, Innenabstand) liegt auf der Stage selbst. */
.hero-stage {
  --glue: -0.1;                          /* JS schreibt live, siehe laufweite.js */
  display: flex; flex-direction: column;
  padding: clamp(1.25rem, 4vh, 2.5rem) var(--satz-r) max(var(--lotse-fab-platz, 6rem), 2rem) var(--sc-gutter);
}
.wand {
  margin: 0;
  color: var(--lw-tinte);
  font-size: clamp(3rem, 15vw, 12rem);   /* Fallback ohne JS; JS setzt den Fit-Grad */
  text-wrap: balance;
  /* Geklebt-bis-getrennt-Fahrt: additiv zur normalen (unveränderten) Laufweite,
     nicht anstelle davon — bei --glue:0 (Latch) exakt der Ursprungswert. */
  letter-spacing: calc(var(--spat) + var(--glue, 0) * 1em);
}
.karte {
  margin-top: auto; padding-top: 1.5rem;
  font-size: 0.95rem; line-height: 1.45; color: var(--lw-tinte-weich);
  max-width: 21rem;
}
.karte p { margin: 0; }
.karte-kanzlei {
  --wght: 600; --luft: 1;              /* Kanzlei-Zeile: weit, ruhig */
  font-size: 1rem; color: var(--lw-tinte);
}
.karte-tel a {
  --luft: 1; --wght: 700;
  display: inline-block; padding: 0.7rem 0;  /* Tap-Fläche ≥ 44px (gemessen 45px) */
  font-family: var(--sc-font-display);
  font-variation-settings: "wdth" var(--wdth), "wght" var(--wght);
  letter-spacing: var(--spat);
  font-size: 1.2rem; line-height: 1.2; color: var(--lw-tinte);
  text-decoration-thickness: 2px;
}
.demotag {
  --luft: 1; --wght: 600;
  margin-top: 0.4rem !important;
  font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--lw-tinte);
}
/* Desktop: die Karte sitzt in der letzten Lücke, rechts neben „eng." (BRIEF).
   laufweite.js prüft die Kollision und setzt sonst .karte-unten. */
@media (min-width: 960px) {
  .hero-stage:not(.karte-unten) .karte {
    position: absolute; right: var(--satz-r);
    bottom: max(var(--lotse-fab-platz, 6rem), 2.5rem);
    text-align: right; margin-top: 0; padding-top: 0;
  }
}

/* ============================================================ Akt 2 · Drang */
/* Score-Span 1.0: Akt 2 ist genau einen Bildschirm hoch, feste Höhe aus
   demselben Grund wie der Hero (kein wanderndes Layout oberhalb des Pins). */
.drang {
  height: 100svh; overflow: clip;
  display: flex; flex-direction: column; justify-content: center;
  padding: clamp(3rem, 9vh, 6rem) var(--satz-r) clamp(4rem, 12vh, 8rem) var(--sc-gutter);
}
.satz {
  margin: 0; color: var(--lw-tinte);
  font-size: clamp(1.6rem, 6vw, 5rem);    /* Fallback ohne JS; JS setzt den Fit-Grad */
  /* Boden für die geteilte --zeilen-Formel (0,82 bei --luft 0): der
     Fit-zur-Breite-Grad (laufweite.js fitSatz) wird bei engem wdth GRÖSSER,
     nicht kleiner, um dieselbe Breite zu füllen — bei 0,82 kollidierten die
     fünf gestapelten Zeilen dann tatsächlich (Buchstaben überlappten sich),
     nicht nur eng gesetzt. 1,05 hält den Satz noch lesbar, ohne die
     Bedrängnis-Wirkung (enger werdende Spationierung/Breite) zu verlieren. */
  --zeilen: max(1.05, calc(0.82 + 0.30 * var(--luft)));
  /* Dieselbe Kollision auch horizontal: bei großem Fit-Grad wurde aus
     −0,04em fast −6px Laufweite, genug um Glyphen dieser fetten
     Schnittstärke kollidieren zu lassen (siehe SPEC §13). Nur hier
     entschärft, der Hero („Es wird eng.") bleibt auf dem Ursprungswert,
     weil er nur zwei kurze, bereits abgenommene Zeilen ist. */
  --spat: calc((-0.015 + 0.075 * var(--luft)) * 1em);
}

/* ============================================================ Akt 3 · Peak */
/* Kein eigenes position auf der Stage: die Engine setzt .sc-stage sticky. */
.peak-stage {
  height: 100svh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 0 var(--satz-r) 0 var(--sc-gutter);
}
.luft {
  margin: 0; color: var(--lw-tinte); white-space: nowrap;
  --luft-min: clamp(3.25rem, 11vh, 6.5rem);  /* der Streifen */
  --luft-max: 20rem;                          /* JS: gemessener Vollbreite-Grad */
  font-size: calc(var(--luft-min) + (var(--luft-max) - var(--luft-min)) * var(--luft));
  font-variation-settings: "wdth" var(--wdth), "wght" calc(900 - 100 * var(--luft));
  letter-spacing: calc((-0.22 + 0.28 * var(--luft)) * 1em);   /* Streifen → offen */
  line-height: 1;
}
.luft-nach {
  margin: clamp(1.25rem, 4vh, 2.5rem) 0 0;
  font-size: clamp(1.05rem, 1.6vw, 1.3rem); line-height: 1.5;
  color: var(--lw-tinte-weich); text-align: center; max-width: 42ch; text-wrap: pretty;
}
/* Unter reduced-motion steht die Nachzeile von Anfang an (K6); !important
   schlägt die Inline-Opacity der Engine. */
@media (prefers-reduced-motion: reduce) {
  .luft-nach { opacity: 1 !important; transform: none !important; }
}

/* ============================================================ Akt 4 · Gebiete */
.spalte { padding-inline: var(--sc-gutter) var(--satz-r); }
/* Fließtext-Spalten halten den gemessenen Fab-Streifen frei (scroll-invariant);
   Display-Zeilen spannen die volle Satzbreite und werden nicht beschnitten. */
.fabguard { padding-right: max(0px, calc(var(--lotse-fab-breite, 0px) - var(--satz-r))); }

.gebiete { padding-block: 3.5rem 5rem; }   /* direkt nach dem Pin: reduziertes Kopf-Padding */
.wipe { padding-block: 0.1em; }
.titel {
  --wght: 500; margin: 0; color: var(--lw-tinte);
  font-size: clamp(2rem, 4.4vw, 3.8rem);
}
.intro { margin: 1rem 0 2.75rem; max-width: 50ch; font-size: 1.1rem; line-height: 1.6; color: var(--lw-tinte-weich); text-wrap: pretty; }
.gebiet {
  border-top: 1px solid var(--lw-hairline);
  padding-block: 1.6rem 2rem;
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.35rem 2.5rem;
}
/* Der Begriff ist die breite Zeile (eigene Reihe, volle Satzbreite); der Grad
   ist so gedeckelt, dass „Verwaltungsrecht" bei wdth 125 auf 390px wie auf
   1280px in einer Zeile bleibt (≈13,3em). */
.gebiet-begriff {
  --wght: 500; margin: 0; color: var(--lw-tinte);
  font-size: clamp(1.4rem, 5.2vw, 4.4rem);
  overflow-wrap: anywhere;
}
.gebiet-problem {
  --wght: 500; margin: 0.35rem 0 0;
  font-size: 0.82rem; letter-spacing: 0.1em; text-transform: uppercase; line-height: 1.4;
  color: var(--lw-tinte-weich);
}
.gebiet-zeile { margin: 0.5rem 0 0; max-width: 56ch; line-height: 1.6; color: var(--lw-tinte); text-wrap: pretty; }
@media (min-width: 900px) {
  .gebiet { grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); align-items: start; row-gap: 0.9rem; }
  .gebiet-begriff { grid-column: 1 / -1; }
  .gebiet-problem { margin-top: 0.35rem; }
  .gebiet-zeile { margin-top: 0; }
}

.lotse { margin-top: 3rem; border-top: 1px solid var(--lw-hairline); padding-top: 2rem; }
.lotse-titel { --wght: 500; margin: 0 0 0.8rem; font-size: 1.4rem; line-height: 1.2; color: var(--lw-tinte); }
.lotse-text { margin: 0; }
.lotse-text p { margin: 0; max-width: 56ch; line-height: 1.6; color: var(--lw-tinte-weich); text-wrap: pretty; }
#lotse-open {
  margin-top: 1.2rem; display: inline-flex; align-items: center;
  min-height: 44px; padding: 0.3rem 0.15rem;
  background: none; border: none; cursor: pointer;
  font: 500 1.05rem/1.3 var(--sc-font-text); color: var(--lw-tinte);
  text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 4px;
  text-decoration-color: var(--lw-tinte-weich);
}
#lotse-open:hover { text-decoration-color: var(--lw-tinte); }
#lotse-open:active { transform: translateY(1px); }

/* ============================================================ Akt 5 · Kanzlei */
.kanzlei { padding-block: 3rem 6rem; }
.kanzlei-grid { display: grid; grid-template-columns: 1fr; gap: 2rem; }
@media (min-width: 900px) {
  .kanzlei-grid { grid-template-columns: minmax(280px, 0.85fr) 1.15fr; gap: clamp(2.5rem, 5vw, 5rem); align-items: start; }
}
.portraet { margin: 0; max-width: 34rem; }
.portraet img { width: 100%; height: auto; filter: saturate(0.85); }
.portraet figcaption { margin-top: 0.65rem; font-size: 0.85rem; color: var(--lw-tinte-weich); }
.kanzlei-text p { margin: 1.1rem 0 0; max-width: 54ch; font-size: 1.05rem; line-height: 1.65; color: var(--lw-tinte); text-wrap: pretty; }

/* ============================================================ Akt 6 · Schluss */
/* Bodenfreiheit für den extern injizierten Bußgeldlotse-Fab (gemessen in
   laufweite.js, Fallback 6rem bei JS-Ausfall, 0 ohne Embed). */
/* Der Schluss ist der letzte Bildschirm der Seite (Kontakt Kante an Kante):
   min-height 100svh bewusst hier, damit die Wipes der letzten Zeilen noch
   sichtbar laufen, bevor das Dokument endet (Flow-Fortschritt p_max = h/(h+vh)),
   und die Seite auf einer gesetzten Fläche endet statt an einer Kante. */
.schluss {
  min-height: 100svh;
  display: flex; flex-direction: column; justify-content: center;
  padding: clamp(3rem, 8vh, 6rem) var(--satz-r) max(var(--lotse-fab-platz, 6rem), 3rem) var(--sc-gutter);
}
.bz {
  margin: 0; color: var(--lw-tinte); white-space: nowrap;
  --wght: 500;
  --bs: clamp(1.35rem, 5vw, 3.1rem);           /* Grundgrad; Modifikatoren unten überschreiben */
  font-size: var(--bs);
  line-height: 1.12; padding-block: 0.06em;    /* clip-path liegt am Border-Box: Raum für Ober-/Unterlängen */
}
.bz .zi { display: inline-block; }
.bz a { text-decoration: none; }
.bz a:hover, .bz a:focus-visible { text-decoration: underline; text-decoration-thickness: 0.05em; text-underline-offset: 0.12em; }
.bz-lead  { --bs: clamp(1.5rem, 5.6vw, 3.6rem); }
.bz-tel   { --bs: clamp(2.4rem, 11vw, 8.5rem); --wght: 800; }
/* Drei Gruppen statt sieben gleichlauten Zeilen (Tim-Fund: alles liest sich
   als ein Block): Erstgespräch+Telefon / Name+Adresse / Mail+Zeiten. Der
   Gruppen-Abstand sitzt jetzt als margin-top auf dem Kicker vor jeder Gruppe
   (siehe .bz-kicker), die volle-Breite-Zeilen-Mechanik (Bauregel §10/§12)
   bleibt je .bz-Zeile unangetastet. */
.bz-name  { --bs: clamp(1.7rem, 6vw, 4.2rem); --wght: 700; }
.bz-tel a {                                    /* Tap-Fläche = ganze Zeile */
  display: block;
  /* K13: ≥ 44px hoch, auch wenn fitBreite() den Grad mobil unter ~39px drückt
     (1,12em = Zeilenhöhe der Zeile; 45px statt 44 wegen Subpixel-Rundung, 43,99
     gemessen; Desktop-Grad ist weit darüber → 0 Padding, Layout unverändert). */
  padding-block: max(0px, calc((45px - 1.12em) / 2));
}
.bz-mail  { --bs: clamp(1rem, 3.6vw, 2rem); }
.bz-zeiten{ --bs: clamp(0.95rem, 3.2vw, 1.7rem); }
/* Kicker (Tim-Fund 05.09.2026: "Footer muss klarer sein"): kurze, GROSS
   gesetzte Mikro-Beschriftung vor jeder der drei Gruppen (Anrufen / Kanzlei /
   Erreichbar) — derselbe Mikro-Label-Ton wie .gebiet-problem, damit auf einen
   Blick klar ist, was zusammengehört, ohne die volle-Breite-Fahrt der
   eigentlichen .bz-Zeilen anzutasten (Kicker ist KEINE .bz-Zeile, nimmt an
   fitBreite() nicht teil, bleibt natürlich klein gesetzt). Trägt den
   Gruppen-Abstand (vorher auf .bz-name/.bz-mail), damit Label und erste
   Zeile der Gruppe optisch zusammenstehen. */
.bz-kicker {
  margin: clamp(1.4rem, 4vh, 2.4rem) 0 0.3rem;
  font-size: 0.78rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--lw-tinte-weich);
}
.bz-kicker:first-child { margin-top: 0; }
.kolophon {
  margin: 2.2rem 0 0; padding-block: 0.2rem;
  display: flex; justify-content: space-between; align-items: baseline; gap: 1.5rem; flex-wrap: wrap;
  font-size: 0.875rem; line-height: 1.5; color: var(--lw-tinte-weich);
}
.kolophon a { white-space: nowrap; }

/* ============================================================ Mobil */
@media (max-width: 700px) {
  :root { --rz-b: 2.5rem; }
  .rz-name, .rz-sep, .rz-demo { display: none; }
  /* Tap-Fläche quer ≥ 44px: Padding wächst nach innen (nach der Drehung links) */
  .rz-tel { padding-block-start: 0.3rem; }

  /* Der atemlose Satz fließt auf schmalen Geräten als dichter Block um
     (Phrase für Phrase statt Zeile für Zeile), sonst würden 33-Zeichen-Zeilen
     auf 310px zu klein. */
  html.js-fit .satz .zeile, .satz .zeile { display: inline; white-space: normal; }
  /* Grad fällt mit der Weite (weit gesetzt läuft der Block ~3x höher), damit
     der Satz in der festen Akt-Höhe bleibt: bei --luft 1 ≈ 0,54 des Eng-Grads. */
  .satz { font-size: calc(clamp(1.9rem, 10.5vw, 3rem) * (1 - 0.46 * var(--luft))) !important; text-wrap: pretty; }

  .kolophon { flex-direction: column; gap: 0.4rem; }
  .lotse-titel { font-size: 1.15rem; }   /* „Für Bußgeldsachen:" bleibt eine Zeile in der 274px-Spalte */
}

/* Bußgeldlotse-Pill (Drittanbieter-Embed) auf schmalen Geräten zum Icon-Knopf
   verkleinern (Muster lagen/sammlung); laufweite.js misst danach neu. */
@media (max-width: 900px) {
  button.bgl-fab { width: 56px; padding: 0; justify-content: center; }
  button.bgl-fab span { display: none; }
}
