/* Looop Web — Kundenseiten.
   Aufbau: Schriften → Stilwelten (data-stil) → Grundlagen → Sektionen → Vorschau-Modus.
   Farben je Kunde kommen aus farben.css neben der Seite (CSP erlaubt keine style-Attribute). */

@font-face { font-family: "Archivo"; src: url("archivo.woff2") format("woff2"); font-weight: 100 900; font-stretch: 62% 125%; font-display: swap; }
@font-face { font-family: "Fraunces"; src: url("fraunces.woff2") format("woff2"); font-weight: 300 900; font-display: swap; }
@font-face { font-family: "Fraunces"; src: url("fraunces-italic.woff2") format("woff2"); font-style: italic; font-weight: 400 900; font-display: swap; }
@font-face { font-family: "Oswald"; src: url("oswald-normal-300-700.woff2") format("woff2"); font-weight: 300 700; font-display: swap; }
@font-face { font-family: "Manrope"; src: url("manrope-normal-300-800.woff2") format("woff2"); font-weight: 300 800; font-display: swap; }
@font-face { font-family: "Bricolage"; src: url("bricolage-normal-300-800.woff2") format("woff2"); font-weight: 300 800; font-stretch: 75% 100%; font-display: swap; }
@font-face { font-family: "Instrument"; src: url("instrument-normal-400.woff2") format("woff2"); font-display: swap; }
@font-face { font-family: "Instrument"; src: url("instrument-italic-400.woff2") format("woff2"); font-style: italic; font-display: swap; }
@font-face { font-family: "SourceSerif"; src: url("sourceserif-normal-300-800.woff2") format("woff2"); font-weight: 300 800; font-display: swap; }

/* ——— Stilwelten ——— */
:root, [data-stil="meister"] {
  --f-kopf: "Archivo", sans-serif; --f-text: "Archivo", sans-serif; --kopf-gewicht: 850; --kopf-breite: 76%; --kopf-trans: uppercase; --kopf-stil: normal; --kopf-sperr: -.015em; --kopf-zeile: .95;
  --grund: #f4f5f2; --grund2: #ffffff; --tinte: #10212e; --leise: #465057; --akzent: #d4692b; --akzent-text: #fff; --dunkel: #10212e; --dunkel-text: #f4f5f2;
  --linie: rgba(16,33,46,.14); --radius: 4px; --text-gewicht: 400;
  /* Knopftexte tragen NIE eine Serifenschrift (Sebastian, 22.09.2026: „Mir
     fällt kein Beispiel ein, wo eine Serifenschrift im Button gut aussieht.")
     Jede Stilwelt und jedes Schriftpaar setzt hier die serifenlose Hälfte des
     Paars ein; wo beide Serifen tragen, bleibt Manrope. */
  --f-knopf: "Archivo", sans-serif;
  /* Rückfall für Stilwelten, die tools/farben.mjs noch nicht durchgerechnet hat. */
  --akzent-tief: color-mix(in oklab, var(--akzent) 88%, var(--tinte));
  --akzent-hell: #e39168;
 --akzent-tief: #b35300;  --auf-akzent: #ffffff;  --auf-akzent-hell: #111111; }
[data-stil="werkstatt"] { --f-knopf: "Manrope", sans-serif; --akzent: #e03a1f; --f-kopf: "Oswald", sans-serif; --f-text: "Manrope", sans-serif; --kopf-gewicht: 600; --kopf-breite: 100%; --kopf-trans: uppercase; --kopf-sperr: .01em; --kopf-zeile: 1; --grund: #efefeb; --grund2: #fff; --tinte: #161616; --leise: #444; --dunkel: #161616; --dunkel-text: #f2f2ee; --linie: rgba(0,0,0,.14); --radius: 0;  --akzent-tief: #d12a0b;  --akzent-hell: #ef7761;  --auf-akzent: #ffffff;  --auf-akzent-hell: #111111; }
[data-stil="hofladen"] { --f-knopf: "Manrope", sans-serif; --f-kopf: "Fraunces", serif; --f-text: "Manrope", sans-serif; --kopf-gewicht: 650; --kopf-breite: 100%; --kopf-trans: none; --kopf-sperr: -.01em; --kopf-zeile: 1.02; --grund: #f6efe2; --grund2: #fffaf1; --tinte: #23301f; --leise: #4b5446; --akzent: #b8432c; --dunkel: #2f4a2d; --dunkel-text: #f6efe2; --linie: rgba(35,48,31,.15); --radius: 20px;  --akzent-hell: #ff9465;  --akzent-tief: #a6432b;  --auf-akzent: #ffffff;  --auf-akzent-hell: #111111; }
[data-stil="atelier"] { --f-knopf: "Manrope", sans-serif; --f-kopf: "Instrument", serif; --f-text: "Manrope", sans-serif; --kopf-gewicht: 400; --kopf-breite: 100%; --kopf-trans: none; --kopf-stil: normal; --kopf-sperr: -.01em; --kopf-zeile: 1; --grund: #131211; --grund2: #1b1a18; --tinte: #efe9df; --leise: #a39c90; --akzent: #c9a45c; --akzent-text: #131211; --dunkel: #0c0b0a; --dunkel-text: #efe9df; --linie: rgba(239,233,223,.14); --radius: 0; --text-gewicht: 300;  --akzent-tief: #ceac6d;  --akzent-hell: #d7bc88;  --auf-akzent: #111111;  --auf-akzent-hell: #111111; }
[data-stil="freundlich"] { --f-knopf: "Bricolage", sans-serif; --akzent: #1b7f6b; --f-kopf: "Bricolage", sans-serif; --f-text: "Bricolage", sans-serif; --kopf-gewicht: 750; --kopf-breite: 92%; --kopf-trans: none; --kopf-sperr: -.025em; --kopf-zeile: 1; --grund: #fbf7ee; --grund2: #fff; --tinte: #1f1d1a; --leise: #4f4a43; --dunkel: #1f1d1a; --dunkel-text: #fbf7ee; --linie: rgba(31,29,26,.12); --radius: 26px;  --akzent-tief: #227260;  --akzent-hell: #629f8f;  --auf-akzent: #ffffff;  --auf-akzent-hell: #111111; }
[data-stil="klassisch"] { --f-knopf: "Manrope", sans-serif; --akzent: #2f5d8a; --f-kopf: "SourceSerif", serif; --f-text: "Manrope", sans-serif; --kopf-gewicht: 620; --kopf-breite: 100%; --kopf-trans: none; --kopf-sperr: -.01em; --kopf-zeile: 1.05; --grund: #ffffff; --grund2: #f5f3ef; --tinte: #1c1c1c; --leise: #4a4a4a; --dunkel: #1c1c1c; --dunkel-text: #fff; --linie: rgba(0,0,0,.12); --radius: 2px;  --akzent-hell: #5987c1;  --akzent-tief: #2e557c;  --auf-akzent: #ffffff;  --auf-akzent-hell: #111111; }

/* ——— Grundlagen ——— */
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body { margin: 0; background: var(--grund); color: var(--tinte); font: var(--text-gewicht) 18px/1.65 var(--f-text); -webkit-font-smoothing: antialiased; }
img { max-width: 100%; display: block; }
a { color: inherit; }
.rahmen { max-width: 1200px; margin: 0 auto; padding-inline: clamp(16px, 5vw, 64px); }
h1, h2, h3 { font-family: var(--f-kopf); font-weight: var(--kopf-gewicht); font-stretch: var(--kopf-breite); text-transform: var(--kopf-trans); font-style: var(--kopf-stil); letter-spacing: var(--kopf-sperr); line-height: var(--kopf-zeile); margin: 0 0 .45em; }
h1 { font-size: clamp(44px, 7.5vw, 104px); }
h2 { font-size: clamp(32px, 4.6vw, 58px); }
h3 { font-size: clamp(21px, 2vw, 26px); line-height: 1.15; }
.s { padding-block: clamp(64px, 9vw, 120px); }
.s-etikett { font: 700 13px/1.3 var(--f-text); text-transform: uppercase; letter-spacing: .14em; color: var(--akzent-tief); margin: 0 0 14px; }
.s-kopf { max-width: 760px; margin-bottom: clamp(28px, 4vw, 48px); }
.s-einleitung p { font-size: 20px; color: var(--leise); margin: 0 0 .6em; }
.unter { font-size: clamp(19px, 2vw, 23px); max-width: 40ch; }

.knopf { display: inline-flex; align-items: center; gap: 8px; background: var(--akzent); color: var(--akzent-text); text-decoration: none; font: 750 17px/1 var(--f-knopf, var(--f-text)); padding: 16px 24px; border-radius: var(--radius); border: 2px solid var(--akzent); transition: transform .15s, filter .15s; }
.knopf:hover { transform: translateY(-2px); filter: brightness(1.05); }
.knopf--zweit { background: transparent; color: inherit; border-color: currentColor; }
.knoepfe { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 8px; }
.sterne { display: inline-block; margin-top: 22px; font-weight: 700; font-size: 15px; text-decoration: none; }

/* Kopfzeile */
.kopf { position: sticky; top: 0; z-index: 20; background: var(--grund); border-bottom: 1px solid var(--linie); }
.kopf .rahmen { display: flex; justify-content: space-between; align-items: center; gap: 16px; padding-block: 12px; }
.logo { display: flex; align-items: center; gap: 12px; text-decoration: none; }
.logo img { height: 44px; width: auto; }
.logo b { font-family: var(--f-kopf); font-weight: var(--kopf-gewicht); font-stretch: var(--kopf-breite); text-transform: var(--kopf-trans); font-size: 24px; line-height: 1; display: block; }
.logo small { display: block; font: 600 11px/1.3 var(--f-text); letter-spacing: .1em; text-transform: uppercase; color: var(--leise); margin-top: 4px; }
.kopf nav { display: flex; gap: 22px; align-items: center; font-weight: 600; font-size: 15px; }
.kopf nav a:not(.knopf) { text-decoration: none; }
.kopf .knopf { padding: 13px 18px; font-size: 15px; white-space: nowrap; min-height: 44px; }
@media (max-width: 860px) { .kopf nav a:not(.knopf) { display: none; } }
@media (max-width: 520px) { .kopf .nur-breit { display: none; } .logo img { height: 34px; } .logo b { font-size: 20px; } }

/* ——— HELD ——— */
.s-held-vollbild, .s-held-karte, .s-held-notdienst { position: relative; min-height: min(86vh, 780px); display: flex; align-items: flex-end; color: #fff; overflow: clip; background: #222; }
.hintergrund { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.s-held-vollbild::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(0,0,0,.66), rgba(0,0,0,.2) 60%, rgba(0,0,0,0)), linear-gradient(0deg, rgba(0,0,0,.5), transparent 50%); }
.s-held-vollbild .rahmen, .s-held-karte .rahmen, .s-held-notdienst .rahmen { position: relative; z-index: 1; width: 100%; }
.s-held-vollbild h1 { max-width: 13ch; }
.s-held-vollbild .s-etikett { color: #fff; opacity: .85; }

.s-held-geteilt { padding-block: clamp(40px, 6vw, 80px); }
.s-held-geteilt .raster { display: grid; grid-template-columns: 1.1fr .9fr; gap: clamp(28px, 5vw, 72px); align-items: center; }
.s-held-geteilt figure { margin: 0; }
.s-held-geteilt figure { aspect-ratio: 4/5; border-radius: var(--radius); }
.s-held-geteilt figure img { width: 100%; height: 100%; object-fit: cover; }
[data-stil="meister"] .s-held-geteilt figure img { box-shadow: 18px 18px 0 var(--akzent); }

.s-held-karte { align-items: center; }
.s-held-karte .karte { background: var(--grund2); color: var(--tinte); max-width: 620px; padding: clamp(28px, 4vw, 52px); border-radius: var(--radius); box-shadow: 0 30px 80px rgba(0,0,0,.25); }
.s-held-karte h1 { font-size: clamp(40px, 6vw, 84px); }

.s-held-typo { padding-block: clamp(60px, 10vw, 140px) clamp(48px, 7vw, 90px); }
.s-held-typo h1 { font-size: clamp(56px, 11vw, 168px); line-height: .92; max-width: 11ch; }
[data-stil="atelier"] .s-held-typo h1 { font-style: italic; }
.s-held-typo .unten { display: grid; grid-template-columns: 1fr 1.2fr; gap: 40px; align-items: end; margin: 24px 0 32px; }
.s-held-typo .unten img { width: 100%; aspect-ratio: 16/9; object-fit: cover; }
.s-held-typo .unter { color: var(--leise); }

.s-held-collage { padding-block: clamp(40px, 6vw, 80px); }
.s-held-collage .raster { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 5vw, 72px); align-items: center; }
.s-held-collage .bilder { position: relative; aspect-ratio: 1 / 1; }
.s-held-collage .bilder figure {
  position: absolute; margin: 0; overflow: clip;
  border-radius: var(--radius); box-shadow: 0 16px 40px rgba(0,0,0,.18);
  border: var(--passepartout, 6px) solid var(--grund2);
  /* Drei Eigenschaften, drei Hände: `rotate` trägt die Grundlage, `transform`
     gehört dem Scrollverlauf, `translate` dem Mauszeiger. Als eine
     transform-Kette hätten sie einander überschrieben — dieselbe Falle wie
     schon beim Heldenbild. */
  rotate: var(--dreh-b, 0deg);
  transition: scale .5s cubic-bezier(.16,.84,.3,1), filter .5s ease, box-shadow .5s ease;
}
.s-held-collage .bilder img { display: block; width: 100%; height: 100%; object-fit: cover; }
.s-held-collage .b1 { left: 0; top: 4%; width: 72%; aspect-ratio: 4/3; --dreh-b: -3deg; }
.s-held-collage .b2 { right: 0; top: 34%; width: 62%; aspect-ratio: 4/3; --dreh-b: 2.5deg; z-index: 1; }
.s-held-collage .b3 { left: 10%; bottom: 0; width: 52%; aspect-ratio: 4/3; --dreh-b: -1deg; z-index: 2; }

.s-held-notdienst { align-items: center; }
.s-held-notdienst::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(10,10,10,.9), rgba(10,10,10,.55) 65%, rgba(10,10,10,.25)); }
.alarm { display: inline-flex; align-items: center; gap: 10px; background: var(--akzent); color: var(--akzent-text); font: 700 15px/1 var(--f-text); text-transform: uppercase; letter-spacing: .12em; padding: 10px 14px; margin-bottom: 22px; }
.puls { width: 10px; height: 10px; border-radius: 50%; background: #fff; animation: puls 1.4s infinite; flex: none; }
@keyframes puls { 0% { box-shadow: 0 0 0 0 rgba(255,255,255,.8); } 100% { box-shadow: 0 0 0 14px rgba(255,255,255,0); } }
.notruf { display: inline-block; font: 700 clamp(40px, 6vw, 76px)/1.1 var(--f-kopf); color: #fff; text-decoration: none; border-bottom: 5px solid var(--akzent); margin: 6px 0 18px; }
.s-held-notdienst .normal a { color: #fff; }

@media (max-width: 860px) {
  .s-held-geteilt .raster, .s-held-collage .raster, .s-held-typo .unten { grid-template-columns: 1fr; }
  .s-held-geteilt figure { aspect-ratio: 4/3; }
}

/* ——— VERTRAUEN ——— */
.s-leiste-fakten { padding-block: 0; background: var(--dunkel); color: var(--dunkel-text); }
.s-leiste-fakten ul { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.s-leiste-fakten li { padding: 28px 22px; border-left: 1px solid rgba(255,255,255,.14); }
.s-leiste-fakten li:first-child { border-left: 0; }
.s-leiste-fakten b { display: block; font: var(--kopf-gewicht) clamp(26px, 3.2vw, 40px)/1.05 var(--f-kopf); font-stretch: var(--kopf-breite); text-transform: var(--kopf-trans); color: var(--akzent-tief); }
.s-leiste-fakten span { font-size: 15px; opacity: .85; }

.s-bewertung-google .rahmen { display: grid; grid-template-columns: auto 1fr; gap: clamp(28px, 6vw, 80px); align-items: center; }
.s-bewertung-google .gross { text-decoration: none; display: grid; justify-items: start; background: var(--grund2); padding: 32px 40px; border-radius: var(--radius); border: 1px solid var(--linie); }
.s-bewertung-google .zahl { font: 800 88px/1 var(--f-kopf); }
.s-bewertung-google .sterne-reihe { color: #f5b301; font-size: 28px; letter-spacing: 4px; }
@media (max-width: 760px) { .s-bewertung-google .rahmen { grid-template-columns: 1fr; } }

/* Sebastian, 21.09.2026: „Was ist, wenn ich 7 Ansprechpartner zeigen will?"
   Mit `1fr` als Obergrenze streckte die letzte Reihe ihre zwei Karten über die
   volle Breite — bei 7 Personen stehen 5 oben und 2 riesige darunter. Eine feste
   Obergrenze plus zentrierte Reihen löst jede Anzahl: 7 werden zu 4 + 3, mittig. */
/* Flexbox statt Grid: Nur sie zentriert auch die ANGEBROCHENE letzte Reihe.
   Im Raster stand die siebte Karte allein am linken Rand — technisch richtig,
   optisch ein Fehler. */
.s-ansprechpartner .personen {
  display: flex; flex-wrap: wrap; gap: 20px; justify-content: center;
}
.s-ansprechpartner .personen > article { flex: 1 1 240px; max-width: 300px; }
/* Ab acht Personen wird die Karte kompakter, sonst wächst die Sektion auf drei
   Bildschirmhöhen — ein Betrieb mit zwölf Namen ist kein Sonderfall. */
.s-ansprechpartner .personen[data-anzahl="8"], .s-ansprechpartner .personen[data-anzahl="9"],
.s-ansprechpartner .personen:not([data-anzahl="1"],[data-anzahl="2"],[data-anzahl="3"],[data-anzahl="4"],[data-anzahl="5"],[data-anzahl="6"],[data-anzahl="7"]) {
  gap: 14px;
}
.s-ansprechpartner .personen[data-anzahl="8"] article, .s-ansprechpartner .personen[data-anzahl="9"] article,
.s-ansprechpartner .personen:not([data-anzahl="1"],[data-anzahl="2"],[data-anzahl="3"],[data-anzahl="4"],[data-anzahl="5"],[data-anzahl="6"],[data-anzahl="7"]) > article { padding: 20px; flex-basis: 190px; max-width: 240px; }
.s-ansprechpartner .personen[data-anzahl="8"] .initiale, .s-ansprechpartner .personen[data-anzahl="9"] .initiale,
.s-ansprechpartner .personen:not([data-anzahl="1"],[data-anzahl="2"],[data-anzahl="3"],[data-anzahl="4"],[data-anzahl="5"],[data-anzahl="6"],[data-anzahl="7"]) .initiale {
  width: 46px; height: 46px; font-size: 20px; margin-bottom: 10px;
}
.s-ansprechpartner article { background: var(--grund2); border: 1px solid var(--linie); border-radius: var(--radius); padding: 28px; }
.s-ansprechpartner .initiale { width: 64px; height: 64px; border-radius: 50%; background: var(--akzent); color: var(--akzent-text); display: grid; place-items: center; font: 800 28px/1 var(--f-kopf); margin-bottom: 16px; }
.s-ansprechpartner article a { font-weight: 800; font-size: 20px; text-decoration: none; color: var(--akzent-tief); }
.s-ansprechpartner article p { margin: 0 0 10px; color: var(--leise); }

.s-einsatzgebiet { background: var(--grund2); }
.s-einsatzgebiet .raster { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; align-items: start; }
.s-einsatzgebiet ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 10px; }
.s-einsatzgebiet li { border: 2px solid var(--tinte); padding: 8px 16px; font-weight: 700; border-radius: var(--radius); }
@media (max-width: 760px) { .s-einsatzgebiet .raster { grid-template-columns: 1fr; } }

.s-leitsatz { background: var(--dunkel); color: var(--dunkel-text); }
.s-leitsatz blockquote { margin: 0; max-width: 980px; }
.s-leitsatz p { font: var(--kopf-gewicht) clamp(32px, 5vw, 64px)/1.1 var(--f-kopf); text-transform: var(--kopf-trans); font-stretch: var(--kopf-breite); margin: 0; }
[data-stil="atelier"] .s-leitsatz p, [data-stil="hofladen"] .s-leitsatz p { font-style: italic; }
.s-leitsatz p::before { content: "„"; color: var(--akzent-tief); }
.s-leitsatz p::after { content: "“"; color: var(--akzent-tief); }
.s-leitsatz footer { margin-top: 20px; opacity: .7; }

/* ——— LEISTUNGEN ——— */
.s-leistungen-kacheln .kacheln { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 18px; }
.s-leistungen-kacheln article { background: var(--grund2); border: 1px solid var(--linie); border-radius: var(--radius); padding: 28px; }
.s-leistungen-kacheln article p { margin: 0; color: var(--leise); }
[data-stil="meister"] .s-leistungen-kacheln article { border-top: 5px solid var(--akzent); }

/* Die Überschrift steht jetzt über dem Raster, damit die erste Leistung auf
   Höhe des Bildoberkante beginnt (Sebastian, 21.09.2026). Das Bild bekommt
   außerdem mehr Gewicht: vorher .9fr gegen 1.1fr, jetzt gleichberechtigt — bei
   einer Sektion, in der ein einziges Foto die ganze Arbeit zeigt, war es zu
   klein. */
.s-leistungen-nummeriert .raster { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 5vw, 64px); align-items: start; }
.s-leistungen-nummeriert .ln-bild { margin: 0; position: relative; overflow: clip; border-radius: var(--radius); }
.s-leistungen-nummeriert .ln-bild .platzhalter { display: block; aspect-ratio: 4/3; background: var(--grund2); }
.s-leistungen-nummeriert ol > li:first-child { padding-top: 0; border-top: 0; }
.s-leistungen-nummeriert img { display: block; border-radius: inherit; aspect-ratio: 3/4; object-fit: cover; width: 100%; }
.s-leistungen-nummeriert ol { list-style: none; counter-reset: n; margin: 0; padding: 0; }
.s-leistungen-nummeriert li { counter-increment: n; display: grid; grid-template-columns: 70px 1fr; column-gap: 12px; padding: 22px 0; border-top: 1px solid var(--linie); }
.s-leistungen-nummeriert li::before { content: counter(n, decimal-leading-zero); grid-row: span 2; font: var(--kopf-gewicht) 34px/1 var(--f-kopf); font-stretch: var(--kopf-breite); color: var(--akzent-tief); }
.s-leistungen-nummeriert li p { margin: 0; color: var(--leise); }

.s-leistungen-akkordeon .raster { display: grid; grid-template-columns: .8fr 1.2fr; gap: clamp(28px, 6vw, 80px); }
.s-leistungen-akkordeon details { border-top: 1px solid var(--linie); }
.s-leistungen-akkordeon details:last-child { border-bottom: 1px solid var(--linie); }
.s-leistungen-akkordeon summary { cursor: pointer; list-style: none; padding: 22px 40px 22px 0; position: relative; font: var(--kopf-gewicht) clamp(24px, 2.8vw, 36px)/1.1 var(--f-kopf); }
[data-stil="atelier"] .s-leistungen-akkordeon summary { font-style: italic; }
.s-leistungen-akkordeon summary::-webkit-details-marker { display: none; }
.s-leistungen-akkordeon summary::after { content: "+"; position: absolute; right: 0; top: 18px; font: 300 32px/1 var(--f-text); color: var(--akzent-tief); }
.s-leistungen-akkordeon details[open] summary::after { content: "–"; }
.s-leistungen-akkordeon details p { margin: 0 0 22px; color: var(--leise); max-width: 52ch; }

.s-leistungen-wechsel img, .s-leistungen-wechsel .platzhalter { width: 100%; aspect-ratio: 16/10; object-fit: cover; border-radius: var(--radius); background: var(--grund2); }
/* Trägt die Zeile selbst eine Linie, muss sie denselben Radius haben wie das
   Bild darin — sonst sitzt ein eckiger Rahmen um ein rundes Bild (Sebastian,
   21.09.2026: „Eckige Rahmen aus der Hölle zu abgerundeten Bildern."). */
.s-leistungen-wechsel article { border-radius: var(--radius); }

.s-leistungen-chips ul { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 2px; background: var(--tinte); border: 2px solid var(--tinte); }
.s-leistungen-chips li { background: var(--grund2); padding: 24px; }
.s-leistungen-chips b { display: block; font: var(--kopf-gewicht) 22px/1.15 var(--f-kopf); text-transform: var(--kopf-trans); margin-bottom: 6px; }
.s-leistungen-chips b::before { content: ""; display: inline-block; width: 12px; height: 12px; background: var(--akzent); margin-right: 10px; }
.s-leistungen-chips span { color: var(--leise); font-size: 16px; }

.s-preisliste .spalten { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 40px; }
.s-preisliste ul { list-style: none; margin: 0; padding: 0; }
.s-preisliste li { display: flex; gap: 8px; align-items: baseline; padding: 8px 0; }
.s-preisliste i { flex: 1; border-bottom: 2px dotted var(--linie); }

@media (max-width: 860px) {
  .s-leistungen-nummeriert .raster, .s-leistungen-akkordeon .raster { grid-template-columns: 1fr; }
}

/* ——— INHALT ——— */
.s-ueber-geteilt .raster { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 6vw, 80px); align-items: center; }
.s-ueber-geteilt img { width: 100%; aspect-ratio: 4/3; object-fit: cover; border-radius: var(--radius); }
.s-ueber-geteilt p { font-size: 20px; }

.s-zeitleiste ol { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); border-top: 1px solid var(--akzent); }
.s-zeitleiste li { padding: 28px 24px 0 0; position: relative; }
.s-zeitleiste li::before { content: ""; position: absolute; top: -6px; left: 0; width: 11px; height: 11px; border-radius: 50%; background: var(--akzent); }
.s-zeitleiste b { font: var(--kopf-gewicht) clamp(40px, 5vw, 64px)/1 var(--f-kopf); display: block; margin-bottom: 10px; }
[data-stil="atelier"] .s-zeitleiste b { font-style: italic; color: var(--akzent-tief); }
.s-zeitleiste p { color: var(--leise); margin: 0; }

.s-werte-drei .drei { display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px; }
.s-werte-drei span { font: italic 400 22px/1 var(--f-kopf); color: var(--akzent-tief); }
.s-werte-drei p { color: var(--leise); }
@media (max-width: 760px) { .s-werte-drei .drei, .s-ueber-geteilt .raster { grid-template-columns: 1fr; } }

.s-text-lang .spalte { columns: 2 320px; column-gap: 48px; font-size: 19px; }
.s-text-lang .spalte p:first-child::first-letter { float: left; font: var(--kopf-gewicht) 76px/.8 var(--f-kopf); color: var(--akzent-tief); margin: 6px 10px 0 0; }

/* ——— BILDER ——— */
.s-galerie-raster .bilder { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.s-galerie-raster img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: var(--radius); }

.s-galerie-mosaik .bilder { display: grid; grid-template-columns: repeat(6, 1fr); grid-auto-rows: 150px; gap: 10px; }
.s-galerie-mosaik figure { margin: 0; position: relative; overflow: hidden; border-radius: var(--radius); grid-column: span 2; }
.s-galerie-mosaik .m0 { grid-column: span 4; grid-row: span 2; }
.s-galerie-mosaik .m1 { grid-row: span 2; }
.s-galerie-mosaik .m1 { grid-column: span 2; }
.s-galerie-mosaik .m2, .s-galerie-mosaik .m3, .s-galerie-mosaik .m4 { grid-column: span 2; grid-row: span 1; }
.s-galerie-mosaik .bilder { grid-auto-flow: dense; }
.s-galerie-mosaik img { width: 100%; height: 100%; object-fit: cover; transition: transform .4s; }
.s-galerie-mosaik figure:hover img { transform: scale(1.04); }
.s-galerie-mosaik figcaption { position: absolute; left: 10px; bottom: 10px; background: var(--grund2); color: var(--tinte); font-size: 13px; font-weight: 700; padding: 4px 10px; border-radius: max(0px, calc(var(--radius, 0px) - 10px)); }
@media (max-width: 760px) { .s-galerie-mosaik .bilder { grid-template-columns: 1fr 1fr; grid-auto-rows: 140px; } .s-galerie-mosaik figure, .s-galerie-mosaik .m1, .s-galerie-mosaik .m3, .s-galerie-mosaik .m4 { grid-column: span 1; grid-row: span 1; } .s-galerie-mosaik .m0 { grid-column: span 2; grid-row: span 2; } }

.s-bildband { padding: 0; position: relative; }
.s-bildband::after { content: ""; position: absolute; inset: auto 0 0 0; height: 60%; background: linear-gradient(transparent, rgba(0,0,0,.72)); pointer-events: none; }
.s-bildband { height: clamp(280px, 48vw, 600px); }
.s-bildband img { width: 100%; height: 100%; object-fit: cover; }
.s-bildband p { z-index: 1; position: absolute; left: clamp(16px, 5vw, 64px); bottom: clamp(16px, 4vw, 48px); margin: 0; max-width: 18ch; color: #fff; font: var(--kopf-gewicht) clamp(28px, 4vw, 52px)/1.05 var(--f-kopf); text-shadow: 0 2px 20px color-mix(in oklab, var(--tinte) 62%, transparent); }

.s-referenzen-karten .karten { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px; }
.s-referenzen-karten img { width: 100%; aspect-ratio: 4/3; object-fit: cover; border-radius: var(--radius); margin-bottom: 14px; }
.s-referenzen-karten p { color: var(--leise); margin: 0; }

/* ——— HANDLUNG ——— */
.s-cta-band { background: var(--akzent); color: var(--akzent-text); text-align: center; }
.s-cta-band h2 { max-width: 20ch; margin-inline: auto; }
.s-cta-band p { font-size: 20px; }
.s-cta-band .knoepfe { justify-content: center; }
.s-cta-band .knopf { background: var(--dunkel); border-color: var(--dunkel); color: var(--dunkel-text); }

.s-notdienst-leiste { position: fixed; right: 16px; bottom: 16px; z-index: 30; display: flex; align-items: center; gap: 10px; background: var(--akzent); color: var(--akzent-text); text-decoration: none; font: 600 15px/1.2 var(--f-text); padding: 12px 18px; box-shadow: 0 10px 30px rgba(0,0,0,.3); border-radius: var(--radius); }
.s-notdienst-leiste b { font-size: 18px; }

.s-kontakt-karte { background: var(--dunkel); color: var(--dunkel-text); }
.s-kontakt-karte .raster { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 6vw, 80px); }
.s-kontakt-karte .adresse { font-size: 21px; }
.s-kontakt-karte .nummern { list-style: none; margin: 0 0 20px; padding: 0; }
.s-kontakt-karte .nummern li { display: flex; justify-content: space-between; gap: 16px; padding: 10px 0; border-bottom: 1px solid rgba(255,255,255,.14); }
.s-kontakt-karte .nummern a { font-weight: 800; font-size: 20px; text-decoration: none; color: var(--akzent-tief); }
.s-kontakt-karte .knopf--zweit { color: var(--dunkel-text); }
.zeiten { width: 100%; border-collapse: collapse; font-size: 18px; }
.zeiten th, .zeiten td { text-align: left; padding: 9px 0; border-bottom: 1px solid rgba(255,255,255,.14); font-weight: 500; }
.zeiten td { text-align: right; font-weight: 700; }
.zeiten .zu { opacity: .5; }
.hinweis-zeiten { font-size: 20px; opacity: .8; }
/* Steht die Zeitentafel schon als eigener Abschnitt auf der Seite, zeigt die
   Kontaktkarte stattdessen die Anfahrt. Gibt es auch die nicht, bleibt nur die
   linke Spalte — dann nicht auf halber Breite stehen lassen, sondern zentriert
   auf Lesebreite. Radius: innen + Innenabstand = außen (hier 0, die Karte füllt
   den Kasten randlos). */
.s-kontakt-karte .raster--einspaltig { grid-template-columns: minmax(0, 54ch); justify-content: center; text-align: center; }
.s-kontakt-karte .raster--einspaltig .nummern li { justify-content: center; border-bottom: 0; padding-bottom: 0; }
.s-kontakt-karte .raster--einspaltig .knoepfe { justify-content: center; }
.s-kontakt-karte .raster--einspaltig .adresse { margin-bottom: 8px; }
.s-kontakt-karte .kontakt-karte-plan { overflow: hidden; border-radius: var(--radius); line-height: 0; }
.s-kontakt-karte .kontakt-karte-plan svg { width: 100%; height: auto; display: block; }
@media (max-width: 760px) { .s-kontakt-karte .raster { grid-template-columns: 1fr; } }

.s-oeffnungszeiten-tafel .tafel { background: var(--dunkel); color: var(--dunkel-text); border-radius: var(--radius); padding: clamp(28px, 5vw, 64px); max-width: 720px; margin: 0 auto; text-align: center; }
[data-stil="hofladen"] .s-oeffnungszeiten-tafel .tafel { border: 3px dashed rgba(246,239,226,.35); outline: 10px solid var(--dunkel); }
.s-oeffnungszeiten-tafel ul { list-style: none; margin: 0; padding: 0; text-align: left; }
.s-oeffnungszeiten-tafel li { display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px dashed rgba(255,255,255,.2); font-size: 20px; }
.s-oeffnungszeiten-tafel li.zu { opacity: .45; }

.s-ablauf-schritte ol { list-style: none; counter-reset: s; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px; }
.s-ablauf-schritte li { counter-increment: s; background: var(--grund2); border-radius: var(--radius); padding: 28px; border: 1px solid var(--linie); }
.s-ablauf-schritte li::before { content: counter(s); display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; background: var(--akzent); color: var(--akzent-text); font: 800 20px/1 var(--f-kopf); margin-bottom: 16px; }
.s-ablauf-schritte p { margin: 0; color: var(--leise); }

.s-faq .raster { display: grid; grid-template-columns: .8fr 1.2fr; gap: 48px; }
.s-faq details { border-bottom: 1px solid var(--linie); padding: 18px 0; }
.s-faq summary { cursor: pointer; font-weight: 700; font-size: 19px; }
@media (max-width: 760px) { .s-faq .raster { grid-template-columns: 1fr; } }

/* ——— LADEN ——— */
.s-sortiment .regal { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 24px; }
.s-sortiment article { background: var(--grund2); border-radius: var(--radius); overflow: hidden; border: 1px solid var(--linie); }
.s-sortiment img { width: 100%; aspect-ratio: 4/3; object-fit: cover; }
.s-sortiment h3, .s-sortiment p { padding-inline: 22px; }
.s-sortiment h3 { margin-top: 18px; }
.s-sortiment p { color: var(--leise); margin: 0 0 22px; }

.s-lieferung-abholung .zwei { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.s-lieferung-abholung article { background: var(--akzent); color: var(--akzent-text); border-radius: var(--radius); padding: clamp(28px, 4vw, 48px); }
.s-lieferung-abholung article:nth-child(2) { background: var(--dunkel); color: var(--dunkel-text); }
.s-lieferung-abholung .symbol { font-size: 44px; }
@media (max-width: 760px) { .s-lieferung-abholung .zwei { grid-template-columns: 1fr; } }

/* ——— Fuß & Rechtliches ——— */
.fuss { padding-block: 28px; font-size: 14px; color: var(--leise); border-top: 1px solid var(--linie); }
.fuss .rahmen { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 10px; }
.rechtlich { min-height: 60vh; }
.hinweis { border-left: 3px solid var(--akzent); padding-left: 14px; color: var(--leise); }

/* ——— Vorschau-Modus: darf NIE fertig wirken ——— */
/* Der Entwurf sieht aus wie die fertige Seite. Bis 20.09.2026 waren die Bilder
   entsättigt, der Text nicht markierbar und ein „VORSCHAU"-Wasserzeichen lag
   darüber — alles drei ließ die Arbeit schlechter aussehen, als sie ist. */
/* Platz für das feste Vorschau-Band — am Körper wäre es wieder ein heller
   Streifen unter der dunklen Fußzeile. */
.ist-vorschau .fuss { padding-bottom: calc(clamp(24px, 3vw, 36px) + 96px); }
.v-balken { position: static; z-index: 40; background: #ff5a1f; color: #fff; text-align: center; font: 700 14px/1.3 "Archivo", sans-serif; padding: 9px 16px; }
.v-balken b { text-transform: uppercase; letter-spacing: .12em; }
/* Der Balken scrollt mit weg. Klebte er oben, klebte der Kopf darunter fest —
   zwei Leisten übereinander, und nach dem Scrollen sah der Kopf verschoben aus. */
.ist-beispiel { position: relative; }
.ist-beispiel::before { content: attr(data-hinweis); position: absolute; top: 10px; right: clamp(16px, 5vw, 64px); max-width: calc(100% - 32px); z-index: 5; background: rgba(22,19,15,.72); color: #fff; font: 600 10px/1 "Archivo", sans-serif; letter-spacing: .06em; text-transform: uppercase; padding: 5px 8px; border-radius: 3px; }
.skizze { border: 3px dashed var(--linie); border-radius: var(--radius); min-height: 220px; display: grid; place-content: center; text-align: center; gap: 8px; padding: 32px; color: var(--leise); background: repeating-linear-gradient(-45deg, transparent 0 14px, var(--linie) 14px 15px); }
.skizze b { font: 700 24px/1.2 var(--f-text); color: var(--tinte); }
.v-cta { position: fixed; left: 50%; bottom: 16px; transform: translateX(-50%); z-index: 45; width: min(920px, calc(100% - 32px)); display: flex; flex-wrap: wrap; gap: 8px 20px; align-items: center; justify-content: space-between; background: #16130f; color: #f5f2ec; text-decoration: none; padding: 14px 20px; border: 3px solid #16130f; box-shadow: 6px 6px 0 #ffd21f; font: 500 15px/1.35 "Archivo", sans-serif; }
.v-cta__knoepfe { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* Runter scrollen = lesen, hoch scrollen = entscheiden. Der Balken geht beim
   Lesen aus dem Weg und kommt zurück, sobald jemand zurückblättert. */
.v-cta { transition: transform .28s ease, opacity .28s ease; will-change: transform; }
.v-cta.ist-weg { transform: translate(-50%, calc(100% + 32px)); opacity: 0; pointer-events: none; }
.v-cta.ohne-bewegung { transition: none; }
.v-ja { background: #ff5a1f; color: #fff; padding: 10px 14px; font-weight: 900; text-transform: uppercase; white-space: nowrap; text-decoration: none; font-size: 14px; }
.v-nein { color: #d8d2c6; text-decoration: underline; font-size: 14px; white-space: nowrap; }
.v-absage { display: none; position: fixed; inset: 0; z-index: 60; background: rgba(10,10,10,.72); padding: 16px; overflow: auto; }
.v-absage:target { display: grid; place-items: center; }
.v-absage__karte { background: #f5f2ec; color: #16130f; max-width: 620px; padding: clamp(24px, 4vw, 44px); border: 3px solid #16130f; box-shadow: 10px 10px 0 #ffd21f; font-family: "Archivo", sans-serif; }
.v-absage__karte h2 { font: 900 clamp(26px, 4vw, 38px)/1.05 "Archivo", sans-serif; font-stretch: 78%; text-transform: none; letter-spacing: -.01em; color: #16130f; }
.v-absage__karte p { font-size: 17px; line-height: 1.55; }
.v-absage__knoepfe { display: flex; flex-wrap: wrap; gap: 12px; }
.v-absage__knoepfe .knopf { background: #16130f; border-color: #16130f; color: #f5f2ec; font-size: 16px; }
.v-absage__knoepfe .knopf--zweit { background: transparent; color: #16130f; border-color: #16130f; }
.v-absage__klein { font-size: 14px; color: #6b645a; }
.v-absage__zu { display: inline-block; margin-top: 8px; font-size: 14px; color: #6b645a; }
.ist-vorschau .s-notdienst-leiste { bottom: 110px; }
/* Die Notdienst-Leiste weicht dem Bestellbalken aus. Rutscht der weg, rutscht sie
   nach: sonst schwebt sie mit 110 px Luft unter sich über dem Seitenrand. */
.ist-vorschau .s-notdienst-leiste { transition: bottom .28s ease; }
.ist-vorschau:has(.v-cta.ist-weg) .s-notdienst-leiste { bottom: 16px; }
@media (max-width: 520px) { .v-balken { font-size: 12px; } .v-balken span { display: none; } }

/* Startpaket-Checkliste: Sprungmarke, Brotkrumen, fester Anruf-Knopf */
.ueberspringen { position: absolute; left: -9999px; }
.ueberspringen:focus { position: fixed; left: 16px; top: 16px; z-index: 60; background: var(--akzent); color: var(--akzent-text); padding: 12px 18px; border-radius: var(--radius); }
.brotkrumen { max-width: 1200px; margin: 0 auto; padding: 18px clamp(16px, 5vw, 64px) 0; font-size: 14px; color: var(--leise); }
.brotkrumen a { color: inherit; }
.anruf-fest { position: fixed; right: 16px; bottom: 16px; z-index: 30; display: none; align-items: center; gap: 8px; background: var(--akzent); color: var(--akzent-text); text-decoration: none; font: 750 16px/1 var(--f-text); padding: 15px 20px; border-radius: 999px; box-shadow: 0 10px 30px rgba(0,0,0,.28); }
@media (max-width: 860px) { .anruf-fest { display: inline-flex; } body { padding-bottom: 76px; } }

/* ——— Bewegung (anim.js setzt die Klassen; ohne Skript bleibt alles sichtbar) ——— */
.mit-bewegung [data-auf] { opacity: 0; transform: translateY(54px); transition: opacity .8s cubic-bezier(.16,.84,.3,1), transform .8s cubic-bezier(.16,.84,.3,1); }
.mit-bewegung [data-auf].ist-sichtbar { opacity: 1; transform: none; }
.mit-bewegung [data-auf="rechts"] { transform: translateX(70px) rotate(1.2deg); }
.mit-bewegung [data-auf="links"] { transform: translateX(-70px) rotate(-1.2deg); }
.mit-bewegung [data-auf="gross"] { transform: scale(.9) translateY(30px); }
/* Am Handy nie seitlich einfliegen – das erzeugte 15 px Überlauf. */
@media (max-width: 900px) { .mit-bewegung [data-auf="rechts"], .mit-bewegung [data-auf="links"] { transform: translateY(44px); } }
.mit-bewegung [data-auf].ist-sichtbar { transition-delay: .05s; }
.mit-bewegung .s-kopf + * [data-auf] { transition-delay: .12s; }
.mit-bewegung [data-i="1"] { transition-delay: .12s; }
.mit-bewegung [data-i="2"] { transition-delay: .24s; }
.mit-bewegung [data-i="3"] { transition-delay: .36s; }
.mit-bewegung [data-i="4"] { transition-delay: .48s; }
.mit-bewegung [data-i="5"] { transition-delay: .60s; }
.s-bildband img, .s-held-geteilt figure img { will-change: transform; object-fit: cover; max-width: 100%; }
/* `max-width: none` ist hier die ganze Reparatur: `.hintergrund` ist ein
   <img>, und der globale `img { max-width: 100% }` hat die angesetzte
   Überbreite stillschweigend zurückgekappt. Gemessen auf dem Handy: gesetzt
   waren `calc(100% + 140px)` = 530 px, berechnet kamen 390 px heraus — die
   Höhe stimmte (984 = 844 + 140), die Breite nicht. Der linke Rand stand
   trotzdem bei −70 px, also fehlten rechts genau die 70 px, die als
   Bildrand sichtbar wurden.
   Das erklärt auch, warum der Fehler nur auf schmalen Schirmen auftrat: Dort
   deckt die Vergrößerung weniger absolute Pixel ab. (22.09.2026) */
.hintergrund { will-change: transform; inset: 0 auto auto 0; height: calc(100% + 80px); margin-top: -40px; width: calc(100% + 80px); margin-left: -40px; max-width: none; object-fit: cover; }
.s-held-geteilt figure, .s-bildband, .s-held-vollbild, .s-held-karte, .s-held-notdienst { overflow: clip; }
.s-held-geteilt figure { position: relative; }
.s-held-geteilt figure img { display: block; max-width: 100%; }
html { overflow-x: clip; }
.s-held-geteilt figure { overflow: hidden; border-radius: var(--radius); }
.s-bildband { overflow: hidden; }
.mit-bewegung .s-leiste-fakten b { transition: none; }
@media (prefers-reduced-motion: reduce) { .hintergrund, .s-bildband img, .s-held-geteilt figure img { transform: none; } }

@media print { .mit-bewegung [data-auf] { opacity: 1 !important; transform: none !important; } }

/* Deutlichere Bewegung: Bilder zoomen beim Zeigen, Titelbild zieht beim Laden auf */
.s-galerie-raster img, .s-sortiment img, .s-referenzen-karten img, .s-leistungen-wechsel img, .s-ueber-geteilt img { transition: scale .6s cubic-bezier(.2,.7,.3,1); }
.s-galerie-raster img:hover, .s-sortiment article:hover img, .s-referenzen-karten article:hover img, .s-leistungen-wechsel article:hover img, .s-ueber-geteilt img:hover { scale: 1.05; }
.s-galerie-raster .bilder, .s-sortiment .regal, .s-referenzen-karten .karten { overflow: visible; }
.s-galerie-raster img, .s-sortiment img, .s-referenzen-karten img { will-change: transform; }
.s-sortiment article, .s-referenzen-karten article, .s-leistungen-kacheln article, .s-ablauf-schritte li { transition: translate .35s ease, scale .35s ease, box-shadow .35s ease; }
.s-sortiment article:hover, .s-referenzen-karten article:hover, .s-leistungen-kacheln article:hover, .s-ablauf-schritte li:hover { translate: 0 -6px; box-shadow: 0 18px 40px rgba(0,0,0,.12); }
.s-sortiment article, .s-referenzen-karten article { overflow: hidden; }
.mit-bewegung .s-held-vollbild h1, .mit-bewegung .s-held-karte .karte, .mit-bewegung .s-held-notdienst .rahmen > * { animation: auftritt .9s cubic-bezier(.16,.84,.3,1) both; }
.mit-bewegung .s-held-karte .karte { animation-delay: .1s; }
@keyframes auftritt { from { opacity: 0; transform: translateY(40px); } to { opacity: 1; transform: none; } }
.zaehler { font-variant-numeric: tabular-nums; }
@media (prefers-reduced-motion: reduce) { .mit-bewegung .s-held-vollbild h1, .mit-bewegung .s-held-karte .karte, .mit-bewegung .s-held-notdienst .rahmen > * { animation: none; } }

/* ——— Alles, was man anklicken kann, reagiert auf Maus und Tastatur ——— */
a, button, summary, label.posten, .posten input { cursor: pointer; }
:where(a, button, summary, details, input, select, textarea):focus-visible { outline: 3px solid var(--akzent); outline-offset: 3px; border-radius: 2px; }

/* Leistungen zum Aufklappen */
.s-leistungen-akkordeon summary { transition: color .2s, padding-left .25s; }
.s-leistungen-akkordeon summary:hover { color: var(--akzent-tief); padding-left: 8px; }
.s-leistungen-akkordeon summary::after { transition: transform .25s, color .2s; }
.s-leistungen-akkordeon summary:hover::after { transform: scale(1.25) rotate(90deg); }
.s-leistungen-akkordeon details[open] summary:hover::after { transform: scale(1.25); }

/* Häufige Fragen */
.s-faq summary { transition: color .2s, padding-left .25s; }
.s-faq summary:hover { color: var(--akzent-tief); padding-left: 6px; }

/* Kopfzeile, Fußzeile, Sterne, Telefonnummern */
.kopf nav a:not(.knopf) { position: relative; transition: color .2s; }
.kopf nav a:not(.knopf)::after { content: ""; position: absolute; left: 0; right: 100%; bottom: -4px; height: 2px; background: var(--akzent); transition: right .25s; }
.kopf nav a:not(.knopf):hover { color: var(--akzent-tief); }
.kopf nav a:not(.knopf):hover::after { right: 0; }
.logo { transition: opacity .2s; }
.logo:hover { opacity: .75; }
.fuss a { text-decoration: underline; text-underline-offset: 3px; transition: color .2s; }
.fuss a:hover { color: var(--akzent-tief); }
.sterne { transition: transform .2s, opacity .2s; }
.sterne:hover { transform: translateY(-2px); opacity: .85; }
.s-kontakt-karte .nummern a, .gross, .s-ansprechpartner article a { transition: opacity .2s, letter-spacing .2s; }
.s-kontakt-karte .nummern a:hover, .gross:hover, .s-ansprechpartner article a:hover { opacity: .8; letter-spacing: .01em; }
.brotkrumen a:hover { color: var(--akzent-tief); text-decoration: underline; }
.s-bewertung-google .gross { transition: transform .25s, box-shadow .25s; }
.s-bewertung-google .gross:hover { transform: translateY(-4px); box-shadow: 0 16px 36px rgba(0,0,0,.12); }
.s-einsatzgebiet li { transition: background .2s, color .2s; }
.s-einsatzgebiet li:hover { background: var(--akzent); color: var(--akzent-text); border-color: var(--akzent-tief); }
.notruf { transition: border-color .2s, transform .2s; }
.notruf:hover { border-color: #fff; transform: translateY(-2px); }
.s-notdienst-leiste, .anruf-fest { transition: transform .2s, box-shadow .2s; }
.s-notdienst-leiste:hover, .anruf-fest:hover { transform: translateY(-3px); box-shadow: 0 16px 34px rgba(0,0,0,.35); }
.s-galerie-mosaik figure { cursor: default; }
.zeiten tr:hover th, .zeiten tr:hover td { color: var(--akzent-tief); }
/* Vorschau-Leiste */
.v-ja, .v-nein, .v-absage__zu { transition: transform .2s, opacity .2s; }
.v-ja:hover { transform: translateY(-2px); }
.v-nein:hover, .v-absage__zu:hover { opacity: .75; text-decoration: underline; }
@media (prefers-reduced-motion: reduce) { a, button, summary { transition: none !important; } }

/* Beispielseite (öffentlich) */
.demo-balken { position: sticky; top: 0; z-index: 41; background: #16130f; color: #f5f2ec; text-align: center; font: 500 14px/1.4 "Archivo", sans-serif; padding: 9px 16px; }
.demo-balken b { color: #ffd21f; }
.demo-balken a { color: #ffd21f; margin-left: 10px; white-space: nowrap; }
.demo-balken a:hover { text-decoration: underline; }
body:has(.demo-balken) .kopf { top: 40px; }
@media (max-width: 620px) { .demo-balken { position: static; font-size: 12px; } body:has(.demo-balken) .kopf { top: 0; } }

/* ——— Beispielseite: Preisschilder an jedem Abschnitt ——— */
.hat-preis { position: relative; }
.hat-preis::after {
  content: attr(data-preis);
  position: absolute; top: 0; left: 0; z-index: 6;
  font: 800 11px/1.1 "Archivo", sans-serif; letter-spacing: .05em; text-transform: uppercase;
  padding: 7px 11px; color: #fff; background: #16130f; border-bottom-right-radius: 4px;
  max-width: min(78vw, 420px);
}
.hat-preis.ist-extra::after { background: #ff5a1f; }
.hat-preis.ist-drin::after { background: #1f7a2e; }
@media (max-width: 620px) { .hat-preis::after { font-size: 10px; padding: 5px 8px; } }
@media print { .hat-preis::after { display: none; } }

/* Legende im Demo-Balken */
.demo-legende { display: flex; flex-wrap: wrap; gap: 8px 14px; justify-content: center; margin-top: 6px; font-size: 12px; }
.demo-legende span::before { content: ""; display: inline-block; width: 10px; height: 10px; margin-right: 6px; border-radius: 2px; vertical-align: baseline; }
.demo-legende .drin::before { background: #1f7a2e; }
.demo-legende .extra::before { background: #ff5a1f; }

/* ——— Kontaktformular (Zusatzleistung) ——— */
.s-kontakt-formular .formular { max-width: 640px; }
.s-kontakt-formular .feld { display: flex; flex-direction: column; gap: 6px; margin: 0 0 16px; }
.s-kontakt-formular label { font-weight: 600; font-size: 15px; }
.s-kontakt-formular input, .s-kontakt-formular textarea {
  font: inherit; font-size: 17px; padding: 11px 13px; border: 1px solid var(--linie);
  border-radius: var(--radius, 4px); background: #fff; color: inherit; width: 100%; max-width: 100%;
}
.s-kontakt-formular input:focus, .s-kontakt-formular textarea:focus { outline: 2px solid var(--akzent); outline-offset: 1px; border-color: var(--akzent-tief); }
.s-kontakt-formular textarea { resize: vertical; min-height: 120px; }
.s-kontakt-formular .honig { position: absolute; left: -9999px; }
.formular__fuss { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 18px; }
.formular__fuss button {
  font: 700 17px/1 "Archivo", sans-serif; padding: 15px 26px; border: 0; cursor: pointer;
  background: var(--akzent); color: #fff; border-radius: var(--radius, 4px); transition: filter .2s, transform .2s;
}
.formular__fuss button:hover { filter: brightness(1.08); transform: translateY(-1px); }
.formular__fuss button[disabled] { opacity: .55; cursor: not-allowed; transform: none; filter: none; }
.formular__fuss small { color: var(--leise); font-size: 13px; max-width: 34ch; }

/* Abgelaufene Vorschau */
.v-abgelaufen { max-width: 640px; margin: 0 auto; padding: 14vh 24px; font: 400 18px/1.6 "Archivo", system-ui, sans-serif; color: #16130f; }
.v-abgelaufen h1 { font-size: clamp(28px, 5vw, 40px); line-height: 1.15; margin: 0 0 18px; }
.v-abgelaufen p { margin: 0 0 14px; }
.v-abgelaufen a { color: inherit; }
.v-abgelaufen__fuss { margin-top: 40px; font-size: 14px; color: #6b6559; }

/* Der Vorschau-Balken muss auch auf dem Handy beide Sätze zeigen. */
.v-balken__zeile { display: block; font-weight: 400; opacity: .95; margin-top: 3px; }
@media (max-width: 620px) { .v-balken { font-size: 12px; line-height: 1.45; padding: 8px 12px; } }

/* Absage mit Grund */
.v-gruende { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 6px 18px; margin: 14px 0; text-align: left; }
.v-gruende label { display: flex; gap: 9px; align-items: center; font-size: 15px; cursor: pointer; padding: 5px 0; }
.v-gruende input { width: 19px; height: 19px; flex: none; }
.v-absage__feld { text-align: left; margin: 10px 0; }
.v-absage__feld label { display: block; font-size: 14px; margin-bottom: 4px; }
.v-absage__feld input, .v-retten input { width: 100%; font: inherit; font-size: 16px; padding: 10px 12px; border: 1px solid #c9c2b4; border-radius: 3px; }
.v-retten { text-align: left; background: #fffbe8; border-left: 4px solid #ffd21f; padding: 12px 14px; margin: 14px 0; font-size: 15px; }
.v-retten input { margin-top: 8px; max-width: 280px; }
.v-absage__danke { text-align: left; }
.v-absage__danke h3 { margin-top: 0; }

/* Kachel, die auf eine Unterseite führt */
.s-leistungen-kacheln .kachel-link { display: block; text-decoration: none; color: inherit; }
.s-leistungen-kacheln .kachel-link .mehr { display: inline-block; margin-top: 10px; font-weight: 700; color: var(--akzent-tief); }
.s-leistungen-kacheln .kachel-link:hover { border-color: var(--akzent-tief); }
.s-leistungen-kacheln .kachel-link:hover .mehr { text-decoration: underline; }

/* ═══════════════════════════════════════════════════════════════════════════
   BEWEGUNG UND TIEFE — Überarbeitung 21.09.2026
   ───────────────────────────────────────────────────────────────────────────
   Anlass (Sebastian): Die Seiten sind sauber, aber flach. Apple macht nichts
   anderes als wir — Text und Bild — es sieht nur zehnmal teurer aus. Der
   Unterschied liegt nicht im Inhalt, sondern in Bewegung, Größe und Tiefe.
   Und genau das kostet uns nichts: dieselben Daten, dasselbe HTML.

   Drei Bausteine, die ALLE Sektionen erben:
     1. --wucht   wie stark Bewegung ausfällt (dezent · mittel · laut)
     2. data-ton  hell/dunkel im Wechsel, damit die Seite atmet
     3. scrollgebundene Animation, wo der Browser sie kann
   ═══════════════════════════════════════════════════════════════════════════ */

/* ——— 1. Wucht: eine Stellschraube für die ganze Seite ——— */
:root, [data-wucht="mittel"] {
  --weg: 54px;          /* wie weit ein Element hereinfährt */
  --dauer: .9s;         /* wie lange es dafür braucht */
  --skala: .965;        /* Startgröße bei „gross" */
  --dreh: .8deg;        /* Neigung bei seitlichem Einlauf */
  --zoom: 1.06;         /* Bildzoom über die Scrollstrecke */
  --schub: 40px;        /* Parallaxe-Weg */
}
[data-wucht="dezent"] { --weg: 22px; --dauer: .7s; --skala: .99; --dreh: 0deg; --zoom: 1.02; --schub: 18px; }
[data-wucht="laut"]   { --weg: 96px; --dauer: 1.35s; --skala: .9; --dreh: 1.6deg; --zoom: 1.14; --schub: 80px; }
/* Eine einzelne Sektion darf lauter oder leiser sein als die Seite. */
.s[data-wucht] { }

/* ——— 2. Ton: heller und dunkler Abschnitt im Wechsel ——— */
.s[data-ton="dunkel"] {
  --grund: var(--dunkel); --grund2: color-mix(in oklab, var(--dunkel) 88%, #fff);
  --akzent-tief: var(--akzent-hell); --auf-akzent: var(--auf-akzent-hell, #111);
  --tinte: var(--dunkel-text); --leise: color-mix(in oklab, var(--dunkel-text) 72%, transparent);
  --linie: color-mix(in oklab, var(--dunkel-text) 18%, transparent);
  background: var(--dunkel); color: var(--dunkel-text);
}
.s[data-ton="dunkel"] .s-etikett { color: color-mix(in oklab, var(--akzent) 80%, #fff); }
.s[data-ton="ruhig"] { background: var(--grund2); }

/* ——— 3. Frosted Glass ——— */
.glas {
  background: color-mix(in oklab, var(--grund2) 62%, transparent);
  backdrop-filter: blur(22px) saturate(1.4);
  -webkit-backdrop-filter: blur(22px) saturate(1.4);
  border: 1px solid color-mix(in oklab, var(--tinte) 12%, transparent);
}
.s[data-ton="dunkel"] .glas {
  background: color-mix(in oklab, #fff 8%, transparent);
  border-color: color-mix(in oklab, #fff 16%, transparent);
}

/* ——— 4. Volle Breite: Galerien und Bänder dürfen ausbrechen ——— */
.s--voll > .rahmen { max-width: none; padding-inline: 0; }
.s--voll > .rahmen { max-width: 1200px; padding-inline: clamp(16px, 5vw, 64px); }
.s--voll > .rahmen:has(.s-kopf) + * { margin-top: 0; }

/* ——— 5. Einblenden: langsamer, weicher, gestaffelt ——— */
.mit-bewegung [data-auf] {
  opacity: 0; transform: translateY(var(--weg));
  transition: opacity var(--dauer) cubic-bezier(.16,.84,.3,1), transform var(--dauer) cubic-bezier(.16,.84,.3,1);
}
.mit-bewegung [data-auf="rechts"] { transform: translateX(calc(var(--weg) * 1.3)) rotate(var(--dreh)); }
.mit-bewegung [data-auf="links"]  { transform: translateX(calc(var(--weg) * -1.3)) rotate(calc(var(--dreh) * -1)); }
.mit-bewegung [data-auf="gross"]  { transform: scale(var(--skala)) translateY(calc(var(--weg) * .6)); }
.mit-bewegung [data-auf="unschaerfe"] { filter: blur(14px); transform: translateY(calc(var(--weg) * .5)); transition: opacity var(--dauer) ease, transform var(--dauer) cubic-bezier(.16,.84,.3,1), filter var(--dauer) ease; }
.mit-bewegung [data-auf].ist-sichtbar { opacity: 1; transform: none; filter: var(--filter-ruhe, none); }

/* Wörter einer Überschrift laufen nacheinander ein (anim.js zerlegt sie). */
.wort { display: inline-block; opacity: 0; transform: translateY(.5em) rotate(1.5deg); }
.mit-bewegung .ist-sichtbar .wort,
.ohne-bewegung .wort { opacity: 1; transform: none; }
.mit-bewegung .wort { transition: opacity .7s ease, transform .7s cubic-bezier(.16,.84,.3,1); transition-delay: calc(var(--w, 0) * 55ms); }

/* ——— 6. Scrollgebundene Bildeffekte ——— */
/* Wo der Browser es kann, hängt der Effekt am Scrollbalken statt an einem Auslöser:
   Das Bild bewegt sich genau so weit, wie gescrollt wird. Chrome und Safari können
   das; Firefox bekommt die Fassung mit Auslöser und sieht trotzdem ordentlich aus. */
@supports (animation-timeline: view()) {
  .mit-bewegung .bild-zoom img,
  .mit-bewegung .bild-zoom > picture > img {
    animation: bildZoom linear both;
    animation-timeline: view();
    animation-range: entry 0% exit 100%;
    will-change: transform;
  }
  @keyframes bildZoom { from { transform: scale(var(--zoom)) translateY(calc(var(--schub) * -.5)); } to { transform: scale(1) translateY(calc(var(--schub) * .5)); } }

  .mit-bewegung .schweben {
    animation: schweben linear both;
    animation-timeline: view();
    animation-range: entry 0% cover 45%;
  }
  @keyframes schweben { from { transform: translateY(var(--schub)) perspective(1200px) rotateX(6deg); opacity: .6; } to { transform: none; opacity: 1; } }

  /* Perspektivwechsel: Der Block kippt beim Hereinkommen leicht auf. */
  .mit-bewegung .kippen {
    animation: kippen linear both;
    animation-timeline: view();
    animation-range: entry 10% cover 40%;
    transform-origin: 50% 100%;
  }
  @keyframes kippen { from { transform: perspective(1400px) rotateX(11deg) scale(.94); opacity: .5; } to { transform: none; opacity: 1; } }
}
.bild-zoom { overflow: hidden; }
.bild-zoom img { width: 100%; height: 100%; object-fit: cover; }

/* ——— 7. Held: so groß wie der Bildschirm ——— */
.s-held-vollbild, .s-held-karte, .s-held-notdienst {
  min-height: min(100svh, 1100px);
  padding-block: clamp(80px, 12vh, 160px);
}
.s-held-vollbild h1 { font-size: clamp(44px, 8.4vw, 132px); line-height: .94; letter-spacing: -.02em; }
.s-held-typo h1 { font-size: clamp(56px, 12vw, 200px); }
.s-held-typo { min-height: min(92svh, 1000px); display: flex; flex-direction: column; justify-content: center; }
h1, h2 { text-wrap: balance; }

/* ——— 8. Karten heben sich beim Zeigen ——— */
.karte-hebt { transition: transform .5s cubic-bezier(.16,.84,.3,1), box-shadow .5s ease; }
@media (hover: hover) { .karte-hebt:hover { transform: translateY(-6px); box-shadow: 0 24px 60px rgba(0,0,0,.14); } }

/* ——— Laufwerk: Karten, die sich selbst weiterschalten ——— */
.s-lauf-karten { overflow: hidden; }
.lauf-bahn {
  display: flex; gap: clamp(14px, 1.6vw, 26px);
  padding-inline: clamp(16px, 5vw, 64px);
  overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; -ms-overflow-style: none;
  scroll-behavior: smooth;
}
.lauf-bahn::-webkit-scrollbar { display: none; }
.lauf-karte {
  position: relative; flex: 0 0 min(88vw, 1000px); scroll-snap-align: center;
  aspect-ratio: 16/10; border-radius: clamp(14px, 1.6vw, 26px); overflow: hidden;
  background: var(--grund2); display: flex; align-items: flex-end;
  transition: opacity .6s ease, transform .6s cubic-bezier(.16,.84,.3,1);
  opacity: .5; transform: scale(.96);
}
.lauf-karte.ist-dran { opacity: 1; transform: none; }
.lauf-bild { position: absolute; inset: 0; }
.lauf-karte:has(.lauf-bild)::after { content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(0deg, rgba(0,0,0,.86) 0%, rgba(0,0,0,.55) 26%, rgba(0,0,0,.12) 55%, transparent 75%); transition: opacity .5s ease; }
.lauf-bild img { width: 100%; height: 100%; object-fit: cover; transform: scale(1.04); transition: transform 7s linear; }
.lauf-karte.ist-dran .lauf-bild img { transform: scale(1.14); }
.lauf-text { position: relative; z-index: 1; padding: clamp(22px, 3.4vw, 54px); max-width: 44ch; }
.lauf-text.auf-bild { color: #fff; }

.lauf-text h3 { font: var(--kopf-gewicht, 700) clamp(24px, 3vw, 44px)/1.08 var(--f-kopf); margin: 0 0 .35em; letter-spacing: -.01em; }
.lauf-text p { font-size: clamp(16px, 1.3vw, 20px); margin: 0; opacity: .92; }
/* Text der aktiven Karte steigt auf — innerhalb der Karte, wie bei Apple.
   ACHTUNG (Sebastian, 21.09.2026): „Die Headline darf im Out-State nicht
   verschwinden." Richtig, und der Fehler saß im Prinzip: Ich hatte die Texte
   beim Wegblenden auf null gesetzt. Beim Wechsel fiel die Überschrift zuerst
   heraus (kleinste Verzögerung) — die Karte sah defekt aus. Jetzt bleibt jeder
   Text LESBAR; nicht-aktive Karten sind leiser, nicht leer. Bewegt wird nur
   beim ersten Erscheinen, nicht bei jedem Wechsel. */
.mit-bewegung .lauf-text > * { opacity: .82; transform: none; transition: opacity var(--ueber, .55s) ease, transform var(--ueber, .55s) cubic-bezier(.16,.84,.3,1); }
.mit-bewegung .lauf-karte.ist-dran .lauf-text > * { opacity: 1; }
/* Der Aufstieg gilt nur, solange die Sektion zum ersten Mal ins Bild kommt. */
.mit-bewegung .s-lauf-karten[data-auf]:not(.ist-sichtbar) .lauf-text > * { opacity: 0; transform: translateY(22px); }
.mit-bewegung .s-lauf-karten .lauf-karte.ist-dran .lauf-text > :nth-child(2) { transition-delay: .1s; }
.mit-bewegung .s-lauf-karten .lauf-karte.ist-dran .lauf-text > :nth-child(3) { transition-delay: .2s; }

.lauf-steuer { display: flex; align-items: center; justify-content: center; gap: 18px; margin-top: clamp(20px, 2.6vw, 34px); }
.lauf-fortschritt { display: flex; align-items: center; gap: 9px; background: color-mix(in oklab, var(--tinte) 8%, transparent); padding: 7px 11px; border-radius: 999px; }
.lauf-punkt { width: 9px; height: 9px; padding: 0; border: 0; border-radius: 999px; background: color-mix(in oklab, var(--tinte) 26%, transparent); cursor: pointer; transition: width .45s cubic-bezier(.16,.84,.3,1), background .3s; position: relative; overflow: hidden; }
.lauf-punkt.ist-dran { width: 40px; background: color-mix(in oklab, var(--tinte) 18%, transparent); }
.lauf-punkt span { position: absolute; inset: 0; width: 0; background: var(--akzent); border-radius: 999px; }
.lauf-punkt.ist-dran span { animation: laufBalken var(--lauf-dauer, 6s) linear forwards; }
.lauf-punkt.ist-pause span { animation-play-state: paused; }
@keyframes laufBalken { to { width: 100%; } }
.lauf-pause { width: 34px; height: 34px; border-radius: 999px; border: 0; cursor: pointer; background: color-mix(in oklab, var(--tinte) 8%, transparent); color: var(--tinte); font-size: 11px; line-height: 1; }
.ohne-bewegung .lauf-punkt span { display: none; }
@media (max-width: 720px) { .lauf-karte { flex-basis: 86vw; aspect-ratio: 4/5; } }

/* ——— Laufwerk: Zeigen, Lautstärke, Dauerbewegung ———
   Sebastian, 21.09.2026: „Die Karten haben KEINEN Mouseover? Das ist ein Muss."
   Und: Die laute Fassung muss laut sein, dann leiten wir die leisen davon ab.
   Deshalb hier erst die Vollfassung, darunter die Rücknahmen. */

/* Zeigen: Bild dunkelt ab und wird unscharf, der Text wächst und rückt auf. */
@media (hover: hover) {
  .lauf-karte { cursor: pointer; }
  .lauf-karte .lauf-bild img { transition: transform 1.2s cubic-bezier(.16,.84,.3,1), filter .55s ease, opacity .55s ease; }
  .lauf-karte:hover .lauf-bild img { filter: blur(7px) brightness(.55) saturate(1.15); transform: scale(1.1); }
  /* Der Textblock rückt beim Zeigen auf — gleich weit nach oben wie nach
     rechts. Vorher wuchs er (scale 1.09 aus der unteren linken Ecke): Das hat
     ihn bei Kästen mit Fläche ins Bild und über die Kartenkante geschoben.
     Sebastian, 22.09.2026: „im Hover ragt es auch noch ins bild rein — das
     sind echte UX FEHLER" und „bewegen sich stärker nach oben als nach
     rechts". Ein gleich langer Versatz kann beides nicht. */
  .lauf-karte .lauf-text { will-change: translate; }
  .lauf-karte:hover .lauf-text { translate: var(--lauf-ruck, 7px) calc(-1 * var(--lauf-ruck, 7px)); }
  /* Der Schleier weicht zurück, weil das Bild schon dunkel ist. */
  .lauf-karte:hover::after { opacity: .3; }
}

/* Dauerbewegung: In der lauten Fassung atmet die aktive Karte weiter, statt
   sieben Sekunden still zu stehen. Sehr langsam — sichtbar, nicht zappelig. */
[data-wucht="laut"] .mit-bewegung .lauf-karte.ist-dran .lauf-bild img,
.mit-bewegung [data-wucht="laut"] .lauf-karte.ist-dran .lauf-bild img {
  animation: kenBurns 18s ease-in-out infinite alternate;
}
@keyframes kenBurns {
  from { transform: scale(1.08) translate3d(-1.5%, -1%, 0); }
  to   { transform: scale(1.18) translate3d(1.5%, 1.5%, 0); }
}
[data-wucht="laut"] .lauf-karte { transition: opacity .8s ease, transform .8s cubic-bezier(.16,.84,.3,1), filter .8s ease; }
[data-wucht="laut"] .lauf-karte:not(.ist-dran) { filter: saturate(.55) brightness(.9); transform: scale(.92); opacity: .42; }
[data-wucht="laut"] .lauf-text h3 { font-size: clamp(30px, 4vw, 62px); }
[data-wucht="laut"] .lauf-karte { flex-basis: min(92vw, 1180px); }

/* Die leise Fassung nimmt genau das zurück: kein Ken Burns, weniger Abfall. */
[data-wucht="dezent"] .lauf-karte:not(.ist-dran) { opacity: .74; transform: none; }
[data-wucht="dezent"] .lauf-karte .lauf-bild img { transition: transform 1s ease; }
[data-wucht="dezent"] .lauf-karte.ist-dran .lauf-bild img { transform: scale(1.05); }
@media (hover: hover) {
  [data-wucht="dezent"] .lauf-karte:hover .lauf-bild img { filter: brightness(.7); transform: scale(1.06); }
  [data-wucht="dezent"] .lauf-karte:hover .lauf-text { --lauf-ruck: 4px; }
}

/* ——— Titelkarte: Glas, das anders scrollt als das Bild ———
   Sebastian, 21.09.2026: „Titelkarte darf frosted sein? Oder sogar liquid? Und
   anders scrollen als das Bild?" Ja, beides. Das Bild läuft langsam nach unten,
   die Karte langsam nach oben — dazwischen entsteht Tiefe. Das Glas nimmt die
   Farbe des Fotos auf, statt sie zuzudecken. */
.s-held-karte .karte.glas {
  background: color-mix(in oklab, var(--grund2) 58%, transparent);
  backdrop-filter: blur(30px) saturate(1.7) brightness(1.06);
  -webkit-backdrop-filter: blur(30px) saturate(1.7) brightness(1.06);
  border: 1px solid color-mix(in oklab, #fff 42%, transparent);
  box-shadow: 0 40px 100px rgba(0,0,0,.34), inset 0 1px 0 color-mix(in oklab, #fff 55%, transparent);
}
/* Der schmale helle Streifen oben lässt das Glas gewölbt wirken statt flach. */
.s-held-karte .karte.glas::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 45%; border-radius: inherit;
  background: linear-gradient(180deg, color-mix(in oklab, #fff 20%, transparent), transparent);
  pointer-events: none;
}
.s-held-karte .karte { position: relative; }

@supports (animation-timeline: view()) {
  .mit-bewegung .s-held-karte .hintergrund {
    animation: heldBild linear both; animation-timeline: view(); animation-range: cover 0% cover 100%;
  }
  @keyframes heldBild { from { transform: scale(var(--held-deckung, 1.18)) translateY(-3%); } to { transform: scale(var(--held-deckung, 1.18)) translateY(6%); } }
  .mit-bewegung .karte-schwebt {
    animation: karteSchwebt linear both; animation-timeline: view(); animation-range: cover 0% cover 100%;
  }
  /* Gegenläufig zum Bild — das ist der ganze Trick. */
  @keyframes karteSchwebt { from { transform: translateY(7%); } to { transform: translateY(-9%); } }
}
[data-wucht="laut"] .s-held-karte .karte.glas { backdrop-filter: blur(40px) saturate(2) brightness(1.1); }
[data-wucht="dezent"] .s-held-karte .karte.glas { backdrop-filter: blur(18px) saturate(1.25); box-shadow: 0 24px 60px color-mix(in oklab, var(--tinte) 30%, transparent); }

/* ——— Bewertungen im Coverflow ———
   Dieselbe Mechanik wie das Laufwerk, aber die Karten stehen schräg im Raum:
   Die aktive steht frontal, die Nachbarn kippen weg. Das ist der Coverflow. */
.s-bewertungen-lauf .bahn-flow { perspective: 1600px; padding-block: clamp(20px, 3vw, 44px); align-items: center; }
.s-bewertungen-lauf .lauf-karte {
  flex-basis: min(74vw, 620px); aspect-ratio: auto; background: none;
  transition: transform .8s cubic-bezier(.16,.84,.3,1), opacity .8s ease, filter .8s ease;
  transform: rotateY(26deg) scale(.86); opacity: .45; filter: saturate(.7);
  transform-style: preserve-3d;
}
.s-bewertungen-lauf .lauf-karte.ist-dran { transform: none; opacity: 1; filter: none; }
/* Die Karte LINKS der aktiven kippt in die andere Richtung. */
.s-bewertungen-lauf .lauf-karte.ist-dran ~ .lauf-karte { transform: rotateY(-26deg) scale(.86); }
.stimme-innen {
  border-radius: clamp(14px, 1.6vw, 24px); padding: clamp(26px, 3.4vw, 48px);
  display: flex; flex-direction: column; gap: 14px; min-height: 100%;
  box-shadow: 0 30px 70px rgba(0,0,0,.16);
}
.stimme .sterne-reihe { color: #f5a623; font-size: clamp(19px, 2vw, 26px); letter-spacing: .12em; margin: 0; }
.stimme .sterne-reihe .leer { color: color-mix(in oklab, var(--tinte) 22%, transparent); }
.stimme blockquote { margin: 0; font: 400 clamp(17px, 1.7vw, 24px)/1.5 var(--f-text); }
.stimme blockquote::before { content: "„"; }
.stimme blockquote::after { content: "“"; }
.stimme footer { display: flex; gap: 12px; align-items: baseline; margin-top: auto; padding-top: 6px; }
.stimme .wer { font-weight: 700; }
.stimme .wann { color: var(--leise); font-size: 14px; }
.stimme-quelle { text-align: center; margin: clamp(18px, 2.4vw, 30px) 0 0; }
.stimme-quelle a { color: var(--leise); }
[data-wucht="laut"] .s-bewertungen-lauf .lauf-karte { transform: rotateY(38deg) scale(.78); opacity: .3; }
[data-wucht="laut"] .s-bewertungen-lauf .lauf-karte.ist-dran ~ .lauf-karte { transform: rotateY(-38deg) scale(.78); }
[data-wucht="dezent"] .s-bewertungen-lauf .bahn-flow { perspective: none; }
[data-wucht="dezent"] .s-bewertungen-lauf .lauf-karte { transform: scale(.95); opacity: .6; filter: none; }
[data-wucht="dezent"] .s-bewertungen-lauf .lauf-karte.ist-dran ~ .lauf-karte { transform: scale(.95); }
@media (max-width: 720px) { .s-bewertungen-lauf .lauf-karte { flex-basis: 84vw; transform: none; opacity: .6; } }

/* ═══════════════════════════════════════════════════════════════════════════
   STELLSCHRAUBEN — dieselbe Sektion, ganz andere Wirkung
   ───────────────────────────────────────────────────────────────────────────
   Sebastian, 21.09.2026: „Es gibt wirklich extrem viele Möglichkeiten, dieses
   Element in Stil und Gefühl auf unterschiedlichste Kunden anzupassen."
   Stimmt — und keine davon kostet in der Herstellung etwas. Also werden sie zu
   Schrauben statt zu Sonderfällen. Jede sitzt als data-Attribut am Abschnitt
   oder am body; die Stilwelt gibt die Vorgabe, der Kunde darf abweichen.

   ecke · passepartout · neigung · schatten · bildlauf · textgrund · bildfilter
   ═══════════════════════════════════════════════════════════════════════════ */

/* ——— Ecken ——— */
[data-ecke="scharf"]  { --ecke: 0; }
[data-ecke="weich"]   { --ecke: 12px; }
[data-ecke="rund"]    { --ecke: 26px; }
[data-ecke="kapsel"]  { --ecke: 56px; --ecke-klein: 24px; }
[data-ecke="scharf"]  { --ecke-klein: 0; }
[data-ecke="weich"]   { --ecke-klein: 8px; }
[data-ecke="rund"]    { --ecke-klein: 16px; }
/* Kleine Kacheln, Chips und Personenkarten nehmen die flachere Stufe. */
.s .kacheln > article, .s .chips li, .s .drei > article, .s .person {
  border-radius: var(--ecke-klein, var(--radius));
}
.lauf-karte, .stimme-innen { border-radius: var(--ecke, clamp(14px, 1.6vw, 26px)); }

/* ——— Passepartout: das Bild sitzt in einem Rahmen wie ein Druck ——— */
[data-passepartout="schmal"] .lauf-karte { --innen-abstand: 10px; }
[data-passepartout="schmal"] .lauf-bild { inset: 10px; border-radius: max(0px, calc(var(--ecke, 20px) - 10px)); overflow: hidden; }
[data-passepartout="breit"]  .lauf-bild { inset: 26px; border-radius: calc(var(--ecke, 20px) - 10px); overflow: hidden; }
/* Das Passepartout ist ein Rahmen UM EIN FOTO — es setzt die Kartenfläche als
   Passepartoutkarton hinter das Bild. Eine Stimmenkarte hat kein Foto: Dort
   steht die Fläche hinter einer zweiten Fläche, und beide zusammen sehen aus
   wie eine Karte, die versehentlich doppelt gerendert wurde.
   Sebastian, 23.09.2026: „Wie kommt es zu dieser Doppelkarte? Es ist nur bei
   der mittleren." — nur die aktive, weil nur sie voll deckend ist. */
[data-passepartout="breit"]  .lauf-karte:has(.lauf-bild),
[data-passepartout="schmal"] .lauf-karte:has(.lauf-bild) { background: var(--grund2); }
/* Im Passepartout darf der Text nicht mehr auf dem Bild kleben. */
[data-passepartout="breit"] .lauf-text, [data-passepartout="schmal"] .lauf-text { padding: clamp(34px, 4vw, 62px); }

/* ——— Neigung: minimal aus der Achse, wie von Hand gelegt ——— */
[data-neigung="leicht"]   .lauf-karte { rotate: -.55deg; }
[data-neigung="leicht"]   .lauf-karte:nth-child(even) { rotate: .5deg; }
[data-neigung="deutlich"] .lauf-karte { rotate: -1.7deg; }
[data-neigung="deutlich"] .lauf-karte:nth-child(even) { rotate: 1.5deg; }

/* ——— Schatten ——— */
[data-schatten="keiner"] .lauf-karte { box-shadow: none; }
[data-schatten="weich"]  .lauf-karte:not(.ohne-flaeche) { box-shadow: 0 30px 70px rgba(0,0,0,.18); }
[data-schatten="weich"]  .lauf-karte.ohne-flaeche .stimme-innen { box-shadow: 0 30px 70px rgba(0,0,0,.14); }
[data-schatten="tief"]   .lauf-karte { box-shadow: 0 50px 110px rgba(0,0,0,.34); }
/* Hart: versetzter Vollton — dieselbe Sprache wie unsere eigene Landingpage. */
[data-schatten="hart"]   .lauf-karte:not(.ohne-flaeche) { box-shadow: 7px 7px 0 color-mix(in oklab, var(--akzent) 40%, var(--grund)); }
[data-schatten="linie"]  .lauf-karte { box-shadow: none; outline: 1px solid color-mix(in oklab, var(--tinte) 26%, transparent); outline-offset: -1px; }

/* ——— Bildlauf: verschiedene endlose Bewegungen ——— */
.mit-bewegung [data-bildlauf="kenburns"] .lauf-karte.ist-dran .lauf-bild img { animation: kenBurns 18s ease-in-out infinite alternate; }
.mit-bewegung [data-bildlauf="schwenk"]  .lauf-karte.ist-dran .lauf-bild img { animation: bildSchwenk 26s linear infinite alternate; }
.mit-bewegung [data-bildlauf="puls"]     .lauf-karte.ist-dran .lauf-bild img { animation: bildPuls 12s ease-in-out infinite; }
.mit-bewegung [data-bildlauf="schaukel"] .lauf-karte.ist-dran .lauf-bild img { animation: bildSchaukel 20s ease-in-out infinite alternate; }
.mit-bewegung [data-bildlauf="still"]    .lauf-karte.ist-dran .lauf-bild img { animation: none; }
@keyframes bildSchwenk  { from { transform: scale(1.22) translateX(-6%); } to { transform: scale(1.22) translateX(6%); } }
@keyframes bildPuls     { 0%, 100% { transform: scale(1.06); } 50% { transform: scale(1.14); } }
@keyframes bildSchaukel { from { transform: scale(1.12) rotate(-1.2deg); } to { transform: scale(1.12) rotate(1.2deg); } }

/* ——— Texthintergrund ——— */
[data-textgrund="verlauf"] .lauf-karte:has(.lauf-bild)::after { opacity: 1; }
[data-textgrund="keiner"]  .lauf-karte:has(.lauf-bild)::after { opacity: 0; }
[data-textgrund="balken"]  .lauf-karte:has(.lauf-bild)::after { background: none; }
[data-textgrund="balken"]  .lauf-text { background: color-mix(in oklab, var(--dunkel) 82%, transparent); border-radius: calc(var(--ecke, 18px) - 8px); margin: clamp(16px, 2vw, 30px); }
[data-textgrund="glas"]    .lauf-karte:has(.lauf-bild)::after { background: none; }
[data-textgrund="glas"]    .lauf-text { backdrop-filter: blur(24px) saturate(1.5); -webkit-backdrop-filter: blur(24px) saturate(1.5);
  background: color-mix(in oklab, #000 26%, transparent); border-radius: calc(var(--ecke, 18px) - 8px); margin: clamp(16px, 2vw, 30px);
  border: 1px solid color-mix(in oklab, #fff 22%, transparent); }
[data-textgrund="block"]   .lauf-karte:has(.lauf-bild)::after { background: none; }
[data-textgrund="block"]   .lauf-text { background: var(--akzent); color: var(--akzent-text); margin: 0; width: min(100%, 56ch); }

/* ——— Bildfilter: dieselbe Datei, andere Handschrift ——— */
[data-bildfilter="entsaettigt"] .lauf-bild img { filter: saturate(.35) contrast(1.05); }
[data-bildfilter="kontrast"]    .lauf-bild img { filter: contrast(1.42) saturate(1.15) brightness(.95); }
[data-bildfilter="korn"]        .lauf-bild::after { content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .3; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='r'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23r)' opacity='.55'/%3E%3C/svg%3E"); }
/* Raster: Punktraster wie im Zeitungsdruck, aus einem Farbverlauf gebaut. */
[data-bildfilter="raster"]      .lauf-bild img { filter: grayscale(1) contrast(1.5); }
[data-bildfilter="raster"]      .lauf-bild::after { content: ""; position: absolute; inset: 0; pointer-events: none; mix-blend-mode: screen; opacity: .55;
  background-image: radial-gradient(circle at center, #000 38%, transparent 40%); background-size: 5px 5px; }
/* Duotone: Graustufen plus Markenfarbe — bindet jedes Fremdfoto an den Kunden. */
[data-bildfilter="duotone"]     .lauf-bild { background: var(--akzent); }
[data-bildfilter="duotone"]     .lauf-bild img { filter: grayscale(1) contrast(1.25) brightness(1.05); mix-blend-mode: luminosity; opacity: .92; }
[data-bildfilter="mezzo"]       .lauf-bild img { filter: grayscale(1) contrast(1.9) brightness(1.1); }
[data-bildfilter="mezzo"]       .lauf-bild::after { content: ""; position: absolute; inset: 0; pointer-events: none; mix-blend-mode: multiply; opacity: .5;
  background-image: repeating-conic-gradient(#000 0% 25%, transparent 0% 50%); background-size: 4px 4px; }

/* ——— Zeigen: der Effekt darf zur Marke passen ——— */
[data-zeigen="unschaerfe"] .lauf-karte:hover .lauf-bild img { filter: blur(8px) brightness(.55); }
[data-zeigen="farbe"]      .lauf-karte:hover .lauf-bild img { filter: grayscale(0) saturate(1.6) brightness(.8); }
[data-zeigen="grau"]       .lauf-karte:hover .lauf-bild img { filter: grayscale(1) brightness(.6); }
[data-zeigen="zoom"]       .lauf-karte:hover .lauf-bild img { transform: scale(1.18); filter: brightness(.7); }
[data-zeigen="keiner"]     .lauf-karte:hover .lauf-bild img { filter: none; transform: none; }

/* ——— Vier Nachbesserungen (Sebastian, 21.09.2026) ———
   1. Die Texte hingen an „ist-dran". Wer eine andere Karte anzeigt, sah sie
      halb verschwinden — die Überschrift zuerst, weil sie die kleinste
      Verzögerung hatte. Wer hinzeigt, will LESEN. Also: Zeigen zählt wie aktiv.
   2. Die Überschrift brach beim Wachsen um, weil der Textblock auf 44 Zeichen
      stand. Er wächst jetzt mit.
   3. Klick aktiviert die Karte (in anim.js).
   4. Zeigen hält den Selbstlauf an (in anim.js). */
.mit-bewegung .lauf-karte:hover .lauf-text > * { opacity: 1; transform: none; transition-delay: 0s; }
.ohne-bewegung .lauf-text > * { opacity: 1; }
.lauf-karte:hover { opacity: 1; }
@media (hover: hover) {

}

/* ——— Übergangsgeschwindigkeit als eigene Schraube ———
   Sebastian, 21.09.2026: „Übergangsgeschwindigkeiten sind vielleicht auch eine
   Variable mit unterschiedlicher Wirkung." Und wie — dieselbe Bewegung wirkt bei
   0,3 s nervös, bei 1,8 s feierlich. Die Kurve gehört dazu: Ein schnelles
   Überschwingen wirkt sportlich, ein langes Ausklingen teuer.
   --ueber = Dauer · --kurve = Beschleunigung */
:root, [data-uebergang="normal"] { --ueber: .55s; --kurve: cubic-bezier(.16,.84,.3,1); }
[data-uebergang="flink"]    { --ueber: .3s;  --kurve: cubic-bezier(.3,1.4,.5,1); }   /* schwingt leicht über */
[data-uebergang="getragen"] { --ueber: 1.1s; --kurve: cubic-bezier(.22,1,.26,1); }
[data-uebergang="schwer"]   { --ueber: 1.9s; --kurve: cubic-bezier(.16,.9,.2,1); }   /* klingt lange aus */
[data-uebergang="hart"]     { --ueber: .45s; --kurve: cubic-bezier(.85,0,.15,1); }   /* schnappt in Position */

/* Überall dort anwenden, wo bisher feste Zeiten standen. */
.lauf-karte { transition: opacity var(--ueber) ease, transform var(--ueber) var(--kurve), filter var(--ueber) ease; }
.s-bewertungen-lauf .lauf-karte { transition: transform calc(var(--ueber) * 1.4) var(--kurve), opacity var(--ueber) ease, filter var(--ueber) ease; }
.lauf-punkt { transition: width var(--ueber) var(--kurve), background .3s; }
@media (hover: hover) {
  .lauf-karte .lauf-bild img { transition: transform calc(var(--ueber) * 2) var(--kurve), filter var(--ueber) ease, opacity var(--ueber) ease; }
  .lauf-karte .lauf-text { transition: translate var(--ueber) var(--kurve); }
}
/* Und für das Einblenden beim Scrollen: die Wucht bestimmt den Weg, der
   Übergang die Zeit. Zwei Schrauben, die sich nicht ins Gehege kommen. */
[data-uebergang] .mit-bewegung [data-auf],
.mit-bewegung [data-uebergang] [data-auf] { transition-duration: calc(var(--ueber) * 1.6); transition-timing-function: var(--kurve); }

/* ═══════════════════════════════════════════════════════════════════════════
   SCHRIFTSÄTZE — Varianz auch innerhalb einer Stilwelt
   ───────────────────────────────────────────────────────────────────────────
   Sebastian, 21.09.2026: „Auch die Schriftarten sollten in größerer Varianz
   vorliegen, auch innerhalb eines Bereichs wie klassisch."

   Grenze, die bleibt: Wir laden KEINE fremden Schriften. Kein Google Fonts,
   keine Adobe-Einbindung — sonst brauchen die Kundenseiten ein Cookie-Banner
   und verlieren ihr Versprechen. Alles hier liegt als woff2 auf unserem Server.

   Sieben Familien ergeben aber weit mehr als sechs Sätze: Es zählt nicht nur,
   WELCHE Schrift, sondern wie schwer, wie breit, wie gesperrt und ob Versalien.
   Dieselbe Archivo wirkt bei 850/76%/Versalien wie ein Bauschild und bei
   400/100%/gemischt wie ein Bürokatalog.
   ═══════════════════════════════════════════════════════════════════════════ */

/* — Serifen als Überschrift, Sans als Text: klassisch, ruhig, seriös — */
[data-schrift="s1"] { --f-knopf: "Manrope", sans-serif; --f-kopf: "SourceSerif", Georgia, serif; --f-text: "Manrope", sans-serif;
  --kopf-gewicht: 700; --kopf-breite: 100%; --kopf-trans: none; --kopf-sperr: -.015em; --kopf-zeile: 1.04; }
[data-schrift="s2"] { --f-knopf: "Manrope", sans-serif; --f-kopf: "Instrument", Georgia, serif; --f-text: "Manrope", sans-serif;
  --kopf-gewicht: 400; --kopf-breite: 100%; --kopf-trans: none; --kopf-sperr: -.005em; --kopf-zeile: 1; }
[data-schrift="s3"] { --f-knopf: "Manrope", sans-serif; --f-kopf: "Fraunces", Georgia, serif; --f-text: "Manrope", sans-serif;
  --kopf-gewicht: 650; --kopf-breite: 100%; --kopf-trans: none; --kopf-sperr: -.02em; --kopf-zeile: 1.02; }
/* — Serifen durchgehend: Kanzlei, Steuerbüro, Traditionsbetrieb — */
[data-schrift="s4"] { --f-knopf: "Manrope", sans-serif; --f-kopf: "SourceSerif", Georgia, serif; --f-text: "SourceSerif", Georgia, serif;
  --kopf-gewicht: 600; --kopf-breite: 100%; --kopf-trans: none; --kopf-sperr: -.01em; --kopf-zeile: 1.08; --text-gewicht: 400; }
/* — Sans als Überschrift, Serifen als Text: umgedreht, wirkt redaktionell — */
[data-schrift="s5"] { --f-knopf: "Archivo", sans-serif; --f-kopf: "Archivo", sans-serif; --f-text: "SourceSerif", Georgia, serif;
  --kopf-gewicht: 700; --kopf-breite: 92%; --kopf-trans: none; --kopf-sperr: -.025em; --kopf-zeile: .98; }
/* — Grotesk, laut: Bauschild — */
[data-schrift="s6"] { --f-knopf: "Archivo", sans-serif; --f-kopf: "Archivo", sans-serif; --f-text: "Archivo", sans-serif;
  --kopf-gewicht: 850; --kopf-breite: 76%; --kopf-trans: uppercase; --kopf-sperr: -.015em; --kopf-zeile: .95; }
[data-schrift="s7"] { --f-knopf: "Manrope", sans-serif; --f-kopf: "Oswald", sans-serif; --f-text: "Manrope", sans-serif;
  --kopf-gewicht: 600; --kopf-breite: 100%; --kopf-trans: uppercase; --kopf-sperr: .01em; --kopf-zeile: 1; }
/* — Grotesk, ruhig: dieselbe Familie, ganz andere Wirkung — */
[data-schrift="s8"] { --f-knopf: "Manrope", sans-serif; --f-kopf: "Archivo", sans-serif; --f-text: "Manrope", sans-serif;
  --kopf-gewicht: 600; --kopf-breite: 108%; --kopf-trans: none; --kopf-sperr: -.02em; --kopf-zeile: 1.05; }
/* — Rund und nahbar — */
[data-schrift="s9"] { --f-knopf: "Bricolage", sans-serif; --f-kopf: "Bricolage", sans-serif; --f-text: "Bricolage", sans-serif;
  --kopf-gewicht: 750; --kopf-breite: 92%; --kopf-trans: none; --kopf-sperr: -.025em; --kopf-zeile: 1; }
[data-schrift="s10"] { --f-knopf: "Bricolage", sans-serif; --f-kopf: "Fraunces", Georgia, serif; --f-text: "Bricolage", sans-serif;
  --kopf-gewicht: 600; --kopf-breite: 100%; --kopf-trans: none; --kopf-sperr: -.015em; --kopf-zeile: 1.04; }
/* — Warm, handgemacht — */
[data-schrift="s11"] { --f-knopf: "Manrope", sans-serif; --f-kopf: "Fraunces", Georgia, serif; --f-text: "Fraunces", Georgia, serif;
  --kopf-gewicht: 700; --kopf-breite: 100%; --kopf-trans: none; --kopf-sperr: -.02em; --kopf-zeile: 1.02; --text-gewicht: 400; }
/* — Edel und schmal — */
[data-schrift="s12"] { --f-knopf: "Manrope", sans-serif; --f-kopf: "Instrument", Georgia, serif; --f-text: "Instrument", Georgia, serif;
  --kopf-gewicht: 400; --kopf-breite: 100%; --kopf-trans: none; --kopf-sperr: 0; --kopf-zeile: 1.02; --text-gewicht: 400; }

/* ═══════════════════════════════════════════════════════════════════════════
   NACHBESSERUNG DER BILDEFFEKTE (21.09.2026)
   Sebastian: „Die Mechanik ist gut — die technische Umsetzung noch nicht, sehr
   viele Darstellungsfehler. Wo ist Duotone?" Vier Ursachen, alle handfest:
   ═══════════════════════════════════════════════════════════════════════════ */

/* 1. Die Bahn schnitt alles ab, was über die Karte hinausragt.
      „overflow-x: auto" für das Wischen kappt auch versetzte Schatten und
      Außenlinien — daher die abgeschnittenen Ecken in den Bildern. */
.lauf-bahn { padding-block: 26px 30px; padding-inline: clamp(16px, 5vw, 64px); }
.s-lauf-karten { overflow: clip; }

/* 2. Duotone war kein Duotone, sondern Monochrom: Luminanz über EINER Farbe
      färbt alles rot ein. Ein echtes Duotone braucht zwei Töne — dunkel für die
      Schatten, hell für die Lichter. Dazwischen liegt die Markenfarbe. */
[data-bildfilter="duotone"] .lauf-bild,
[data-bildfilter="duotone"] .bild-zoom {
  background: linear-gradient(155deg,
    color-mix(in oklab, var(--dunkel) 88%, var(--akzent)) 0%,
    var(--akzent) 52%,
    color-mix(in oklab, var(--akzent) 22%, #fff) 100%);
}
[data-bildfilter="duotone"] .lauf-bild img,
[data-bildfilter="duotone"] .bild-zoom img {
  filter: grayscale(1) contrast(1.18) brightness(1.02);
  mix-blend-mode: luminosity; opacity: 1;
}

/* 3. Raster und Mezzotinto waren unsichtbar: „screen" mit schwarzen Punkten
      ändert nichts (Schwarz ist das neutrale Element dieser Rechnung). Die
      Punkte müssen multiplizieren, und sie brauchen Kontrast darunter. */
[data-bildfilter="raster"] .lauf-bild::after,
[data-bildfilter="raster"] .bild-zoom::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  mix-blend-mode: multiply; opacity: .85;
  background-image: radial-gradient(circle at center, #fff 30%, #000 72%);
  background-size: 4px 4px;
}
[data-bildfilter="raster"] .lauf-bild img { filter: grayscale(1) contrast(1.35) brightness(1.12); }
[data-bildfilter="mezzo"] .lauf-bild::after,
[data-bildfilter="mezzo"] .bild-zoom::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  mix-blend-mode: multiply; opacity: .55;
  background-image: repeating-linear-gradient(48deg, #000 0 1px, #fff 1px 3px);
}
[data-bildfilter="mezzo"] .lauf-bild img { filter: grayscale(1) contrast(1.7) brightness(1.18); }
/* Das Bild braucht einen eigenen Stapelkontext, sonst mischt der Überzug mit
   dem Kartenhintergrund statt mit dem Foto. */
.lauf-bild, .bild-zoom { isolation: isolate; }

/* 4. Der harte Schatten hatte dieselbe Farbe wie ein Duotone-Bild — rot auf rot.
      Er nimmt jetzt die Tinte; die Markenfarbe steht schon im Bild. */
[data-schatten="hart"] .lauf-karte:not(.ohne-flaeche) { box-shadow: 7px 7px 0 color-mix(in oklab, var(--tinte) 24%, var(--grund)); }
[data-schatten="hart"][data-bildfilter="duotone"] .lauf-karte:not(.ohne-flaeche) { box-shadow: 7px 7px 0 color-mix(in oklab, var(--dunkel) 26%, var(--grund)); }
/* Die Außenlinie lag als dunkle Linie auf einem dunklen Foto — unsichtbar.
   Sie sitzt jetzt AUSSEN und trägt die Markenfarbe. */
[data-schatten="linie"] .lauf-karte { box-shadow: 0 0 0 1px color-mix(in oklab, var(--tinte) 26%, transparent); outline: none; }

/* Der Schleier darf das Passepartout nicht überdecken — er gehört aufs Bild. */
[data-passepartout="schmal"] .lauf-karte:has(.lauf-bild)::after { inset: 10px; border-radius: max(0px, calc(var(--ecke, 20px) - 10px)); }
[data-passepartout="breit"]  .lauf-karte:has(.lauf-bild)::after { inset: 18px; border-radius: max(0px, calc(var(--ecke, 20px) - 18px)); }
[data-passepartout="schmal"] .lauf-text,
[data-passepartout="breit"]  .lauf-text { background: color-mix(in oklab, var(--dunkel) 84%, transparent); border-radius: calc(var(--ecke, 18px) - 4px); }

/* — Drei Nachzügler (Sebastian, 21.09.2026): „Vielleicht auch bei jeder Gruppe
     immer mindestens eine Serif- und Sans-Serif-Schrift anbieten. Auch bei
     Atelier findest du eine schöne schlanke Sans, und auch bei Handwerks-
     betrieben kann eine Serife gut aussehen." Stimmt beides. — */

/* Schlanke, gesperrte Grotesk: edel ohne Serife — für Atelier und Kanzlei.
   Archivo kann schmal UND leicht; bei 300/112 %/gesperrt wirkt sie wie eine
   Modezeitschrift, nicht wie ein Bauschild. */
[data-schrift="s13"] { --f-knopf: "Manrope", sans-serif; --f-kopf: "Archivo", sans-serif; --f-text: "Manrope", sans-serif;
  --kopf-gewicht: 300; --kopf-breite: 112%; --kopf-trans: none; --kopf-sperr: .015em; --kopf-zeile: 1.08; --text-gewicht: 350; }

/* Serife mit Gewicht: Handwerk, das etwas auf sich hält. Kein Kontrastspiel,
   sondern eine schwere Serife über einer nüchternen Grotesk. */
[data-schrift="s14"] { --f-knopf: "Archivo", sans-serif; --f-kopf: "SourceSerif", Georgia, serif; --f-text: "Archivo", sans-serif;
  --kopf-gewicht: 800; --kopf-breite: 100%; --kopf-trans: none; --kopf-sperr: -.022em; --kopf-zeile: 1; }

/* Warme Serife mit Druck: Hofladen, Bäcker, Traditionsbetrieb mit Wucht. */
[data-schrift="s15"] { --f-knopf: "Archivo", sans-serif; --f-kopf: "Fraunces", Georgia, serif; --f-text: "Archivo", sans-serif;
  --kopf-gewicht: 800; --kopf-breite: 100%; --kopf-trans: none; --kopf-sperr: -.03em; --kopf-zeile: .98; }

/* ═══════════════════════════════════════════════════════════════════════════
   DIE SCHRAUBEN GELTEN ÜBERALL (21.09.2026)
   ───────────────────────────────────────────────────────────────────────────
   Bis hierher wirkten die neun Schrauben nur auf den Laufkarten. Sebastian:
   „Bewertungen und Laufkarten finde ich gut — die anderen hast du noch nicht
   gemacht, oder?" Nein. Jetzt schon.

   Der Hebel war kleiner als gedacht: 23 Regeln benutzen bereits --radius, und
   jedes <figure> bekommt vom Generator schon .bild-zoom. Es fehlte nur das
   Andocken. Deshalb hier bewusst KEINE neuen Klassen in den 36 Vorlagen —
   sondern eine Liste der Bausteine, die es ohnehin überall gibt.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Alles, was wie eine Fläche aussieht. Eine Liste statt „*", damit nichts
   erwischt wird, das keine Karte ist (Listenpunkte, Absätze, Tabellenzellen). */
.s article, .s .karte, .s .tafel, .s .teller, .s .kachel, .s figure, .s blockquote,
.s .person, .s .kasten, .s .stimme-innen { --flaeche: 1; }

/* ——— 1. Ecken: eine Zeile, 23 Regeln ziehen mit ——— */
[data-ecke] { --radius: var(--ecke); }

/* ——— 2. Schatten ——— */
[data-schatten="keiner"] .s article:not(.ohne-flaeche), [data-schatten="keiner"] .s .karte:not(.ohne-flaeche),
[data-schatten="keiner"] .s .kasten:not(.ohne-flaeche), [data-schatten="keiner"] .s figure:not(.ohne-flaeche) { box-shadow: none; }
[data-schatten="weich"] .s article:not(.ohne-flaeche), [data-schatten="weich"] .s .karte:not(.ohne-flaeche),
[data-schatten="weich"] .s .kasten:not(.ohne-flaeche) { box-shadow: 0 18px 44px rgba(0,0,0,.10); }
[data-schatten="tief"] .s article:not(.ohne-flaeche), [data-schatten="tief"] .s .karte:not(.ohne-flaeche),
[data-schatten="tief"] .s .kasten:not(.ohne-flaeche) { box-shadow: 0 34px 80px rgba(0,0,0,.22); }
[data-schatten="hart"] .s article:not(.ohne-flaeche), [data-schatten="hart"] .s .karte:not(.ohne-flaeche),
[data-schatten="hart"] .s .kasten:not(.ohne-flaeche) { box-shadow: 5px 5px 0 color-mix(in oklab, var(--tinte) 22%, var(--grund)); }
[data-schatten="linie"] .s article:not(.ohne-flaeche), [data-schatten="linie"] .s .karte:not(.ohne-flaeche),
[data-schatten="linie"] .s .kasten:not(.ohne-flaeche) { box-shadow: 0 0 0 1px color-mix(in oklab, var(--tinte) 24%, transparent); }

/* ——— 3. Bildeffekte auf JEDES Bild, nicht nur auf Karten ——— */
[data-bildfilter="entsaettigt"] .s img:not(.logo img) { filter: saturate(.35) contrast(1.05); }
[data-bildfilter="kontrast"]    .s img:not(.logo img) { filter: contrast(1.42) saturate(1.15) brightness(.95); }
[data-bildfilter="raster"]      .s .bild-zoom img,
[data-bildfilter="mezzo"]       .s .bild-zoom img { filter: grayscale(1) contrast(1.4) brightness(1.1); }
/* Duotone auch auf Hintergrundbildern der Helden — dort wirkt es am stärksten. */
[data-bildfilter="duotone"] .s-held-vollbild, [data-bildfilter="duotone"] .s-held-karte,
[data-bildfilter="duotone"] .s-held-notdienst {
  background: linear-gradient(155deg, color-mix(in oklab, var(--dunkel) 88%, var(--akzent)), var(--akzent) 58%, color-mix(in oklab, var(--akzent) 25%, #fff));
}
[data-bildfilter="duotone"] .hintergrund { filter: grayscale(1) contrast(1.15); mix-blend-mode: luminosity; }

/* ——— 4. Neigung: Kacheln liegen leicht schief, wie hingelegt ——— */
[data-neigung="leicht"] .s .kacheln > article,
[data-neigung="leicht"] .s .drei > article { rotate: -.5deg; }
[data-neigung="leicht"] .s .kacheln > article:nth-child(even),
[data-neigung="leicht"] .s .drei > article:nth-child(even) { rotate: .5deg; }
[data-neigung="deutlich"] .s .kacheln > article,
[data-neigung="deutlich"] .s .drei > article { rotate: -1.4deg; }
[data-neigung="deutlich"] .s .kacheln > article:nth-child(even),
[data-neigung="deutlich"] .s .drei > article:nth-child(even) { rotate: 1.4deg; }

/* ——— 5. Zeigen: gilt für jede Kachel und jedes Bild ——— */
@media (hover: hover) {
  .s .kacheln > article, .s .drei > article, .s figure {
    transition: translate var(--ueber, .55s) var(--kurve), scale var(--ueber, .55s) var(--kurve),
                box-shadow var(--ueber, .55s) ease, filter var(--ueber, .55s) ease;
  }
  [data-zeigen="zoom"]       .s .kacheln > article:hover { translate: 0 -10px; scale: 1.025; }
  [data-zeigen="zoom"]       .s figure:hover img { scale: 1.07; }
  [data-zeigen="unschaerfe"] .s .kacheln > article:hover { translate: 0 -6px; box-shadow: 0 26px 60px rgba(0,0,0,.18); }
  [data-zeigen="grau"]       .s figure:hover img { filter: grayscale(1); }
  [data-zeigen="farbe"]      .s figure:hover img { filter: saturate(1.5); }
  /* Ohne gesetzte Schraube bleibt die ruhige Grundbewegung aus dem Block am
     Dateiende — sie wird hier von den Stufen oben überschrieben, nicht ergänzt. */
}

/* ——— 6. Dauerbewegung auch für Held-Hintergründe ———
   Diese drei Regeln setzten `animation` auf dasselbe Element wie die
   scrollgebundene Parallaxe weiter unten — und weil die spätere Regel gewinnt,
   lief hier gar nichts. Das war eine von Sebastians „Einstellungen, bei denen
   sich nichts verändert". Jetzt laufen sie über `scale` beziehungsweise
   `translate`, also neben der Parallaxe statt gegen sie.
   `translate` teilen sie sich mit dem Mauszeiger-Effekt; anim.js lässt die
   Finger von Sektionen, die schwenken oder schaukeln. */
.mit-bewegung [data-bildlauf="kenburns"] .hintergrund { animation: hgZoom 26s ease-in-out infinite alternate; }
.mit-bewegung [data-bildlauf="schwenk"]  .hintergrund { animation: hgSchwenk 34s linear infinite alternate; }
.mit-bewegung [data-bildlauf="schaukel"] .hintergrund { animation: hgSchaukel 28s ease-in-out infinite alternate; }
.mit-bewegung [data-bildlauf="puls"]     .hintergrund { animation: hgPuls 18s ease-in-out infinite; }
/* Wo es view() gibt, laufen BEIDE: die Scrollbindung auf `transform`, die
   Dauerbewegung auf `scale`/`translate`. Zwei Einträge in einer Liste, zwei
   Zeitachsen — sonst verdrängt die eine die andere. */
@supports (animation-timeline: view()) {
  .mit-bewegung [data-bildlauf="kenburns"] .hintergrund {
    animation: heldEinzug linear both, hgZoom 26s ease-in-out infinite alternate;
    animation-timeline: view(), auto; animation-range: cover 0% cover 100%, normal;
  }
  .mit-bewegung [data-bildlauf="schwenk"] .hintergrund {
    animation: heldEinzug linear both, hgSchwenk 34s linear infinite alternate;
    animation-timeline: view(), auto; animation-range: cover 0% cover 100%, normal;
  }
  .mit-bewegung [data-bildlauf="schaukel"] .hintergrund {
    animation: heldEinzug linear both, hgSchaukel 28s ease-in-out infinite alternate;
    animation-timeline: view(), auto; animation-range: cover 0% cover 100%, normal;
  }
  .mit-bewegung [data-bildlauf="puls"] .hintergrund {
    animation: heldEinzug linear both, hgPuls 18s ease-in-out infinite;
    animation-timeline: view(), auto; animation-range: cover 0% cover 100%, normal;
  }
}
@keyframes hgZoom    { from { scale: 1; } to { scale: 1.09; } }
@keyframes hgSchwenk { from { translate: -1.8% 0; } to { translate: 1.8% 0; } }
@keyframes hgSchaukel{ from { translate: -1.6% -1%; } to { translate: 1.6% 1%; } }
@keyframes hgPuls    { 0%, 100% { scale: 1; } 50% { scale: 1.055; } }

/* ——— 7. Passepartout: auch bei Galerien und Bildbändern ——— */
[data-passepartout="schmal"] .s figure { padding: 8px; background: var(--grund2); }
[data-passepartout="breit"]  .s figure { padding: 18px; background: var(--grund2); }
[data-passepartout="schmal"] .s figure img,
[data-passepartout="breit"]  .s figure img { border-radius: calc(var(--radius) * .5); }

/* ═══════════════════════════════════════════════════════════════════════════
   HELD VOLLBILD — Sektionsdurchgang 1 (Sebastian, 21.09.2026)
   ───────────────────────────────────────────────────────────────────────────
   Befund: „Das Bild verändert sich GAR nicht." Kein fehlender Hebel, sondern
   toter Code: `.hintergrund` bewegte sich über die Variable --parallaxe, die
   die alte anim.js gesetzt hat. Seit der Neufassung setzt sie niemand mehr —
   das Bild stand still, und zwar in jedem Browser, der animation-timeline kann.
   ═══════════════════════════════════════════════════════════════════════════ */

/* 1. Das Heldenbild hängt jetzt am Scrollbalken wie alle anderen Bilder. */
@supports (animation-timeline: view()) {
  .mit-bewegung .hintergrund {
    animation: heldEinzug linear both;
    animation-timeline: view();
    animation-range: cover 0% cover 100%;
    will-change: transform;
  }
  /* Die Rechnung dahinter (Sebastian, 21.09.2026: „Sicherstellen, dass das Bild
     nicht weiter wandert, als man das Bild sehen kann — also nur innerhalb des
     Crops"): Bei Vergrößerung s ragt das Bild je Seite um (s−1)/2 über den
     Rahmen hinaus. Eine Verschiebung um t Prozent ist also nur gedeckt, solange
     t ≤ (s−1)/2 · 100. Der alte Endzustand hatte s = 1,02 und t = 5 % — gedeckt
     war 1 %, sichtbar wurde eine Kante von vier Prozent Bildhöhe.
     Jetzt: 5 % Verschiebung, 12 px Mauszeiger (rund 1,5 %) und ein wenig
     Reserve ergeben 1,16 als kleinste Vergrößerung über die ganze Strecke. */
  @keyframes heldEinzug {
    from { transform: scale(calc(var(--held-deckung, 1.16) + (var(--zoom) - 1) * 1.6)) translateY(-4.2%); }
    to   { transform: scale(var(--held-deckung, 1.16)) translateY(4.8%); }
  }
  /* 2. Ein- und Auszug des Textes: Beim Hereinkommen steigt er auf, beim
        Hinausgehen sinkt er ab und wird leiser. Das fehlte ganz. */
  .mit-bewegung .s-held-vollbild .rahmen,
  .mit-bewegung .s-held-karte .rahmen,
  .mit-bewegung .s-held-notdienst .rahmen {
    animation: heldText linear both;
    animation-timeline: view();
    animation-range: cover 0% cover 100%;
  }
  @keyframes heldText {
    0%   { opacity: 0; transform: translateY(42px) scale(.98); filter: blur(0); }
    28%  { opacity: 1; transform: none; filter: blur(0); }
    72%  { opacity: 1; transform: none; filter: blur(0); }
    100% { opacity: .12; transform: translateY(-40px) scale(.97); filter: blur(5px); }
  }
}

/* 3. Überzug: Wie liegt der Text auf dem Bild? Sechs Stellungen, von
      „kaum" bis „Maske". Der Verlauf ist das Übliche — die Maske nicht. */
.s-held-vollbild::after, .s-held-notdienst::after { transition: opacity var(--ueber, .55s) ease; }
[data-ueberzug="unten"] .s-held-vollbild::after {
  background: linear-gradient(0deg, rgba(0,0,0,.88) 2%, rgba(0,0,0,.45) 34%, transparent 68%); }
[data-ueberzug="seite"] .s-held-vollbild::after {
  background: linear-gradient(90deg, rgba(0,0,0,.86) 8%, rgba(0,0,0,.35) 46%, transparent 76%); }
[data-ueberzug="schleier"] .s-held-vollbild::after {
  background: color-mix(in oklab, var(--dunkel) 62%, transparent); }
[data-ueberzug="duplex"] .s-held-vollbild::after {
  background: linear-gradient(120deg, color-mix(in oklab, var(--akzent) 72%, transparent), color-mix(in oklab, var(--dunkel) 80%, transparent)); mix-blend-mode: multiply; }
[data-ueberzug="kaum"] .s-held-vollbild::after {
  background: linear-gradient(0deg, rgba(0,0,0,.55) 0%, transparent 42%); }
/* Maske: Das Bild läuft nach unten weich aus, statt an einer Kante zu enden. */
[data-ueberzug="maske"] .s-held-vollbild::after { background: none; }
[data-ueberzug="maske"] .s-held-vollbild .hintergrund {
  -webkit-mask-image: radial-gradient(120% 90% at 70% 30%, #000 42%, transparent 88%);
  mask-image: radial-gradient(120% 90% at 70% 30%, #000 42%, transparent 88%); }
[data-ueberzug="maske"] .s-held-vollbild { background: var(--dunkel); }

/* 4. KEIN Textkasten im Vollbild-Helden (Sebastian, 21.09.2026): „Es gibt ja
      noch die Titelkarte über Bild." Richtig — genau dafür ist `held-karte` da.
      Zwei Sektionen, die dasselbe tun, verwirren bei der Auswahl und machen
      die Entscheidung beliebig. Der Vollbild-Held bleibt, was er ist: Text
      DIREKT auf dem Bild, lesbar gemacht durch den Überzug. Wer einen Kasten
      will, nimmt die Titelkarte — die kann dafür Glas, Gegenlauf und alles.
      Die Lesbarkeit trägt hier allein der Überzug, und der hat sechs Stufen. */
[data-textgrund] .s-held-vollbild .rahmen {
  background: none; backdrop-filter: none; -webkit-backdrop-filter: none;
  border: 0; width: 100%; max-width: 1200px;
  padding-inline: clamp(16px, 5vw, 64px); padding-block: 0;
}
/* Nur ein Zugeständnis: Bei „glas" bekommt der Text einen weichen Schein, damit
   er auch auf hellen Fotos steht — ohne Kasten, ohne Kante. */
[data-textgrund="glas"] .s-held-vollbild h1,
[data-textgrund="glas"] .s-held-vollbild .unter { text-shadow: 0 2px 28px color-mix(in oklab, var(--tinte) 70%, transparent); }

/* 5. Knöpfe: Form, Füllung, Größe. Bisher sahen alle gleich aus. */
[data-knopf="voll"]  .knopf { }
[data-knopf="rahmen"] .knopf { background: transparent; color: currentColor; border: 2px solid currentColor; }
[data-knopf="rahmen"] .knopf--zweit { border-style: dashed; }
[data-knopf="glas"] .knopf {
  background: color-mix(in oklab, #fff 16%, transparent); color: #fff; border-color: color-mix(in oklab, #fff 40%, transparent);
  backdrop-filter: blur(14px) saturate(1.4); -webkit-backdrop-filter: blur(14px) saturate(1.4); }
[data-knopf="pille"] .knopf { border-radius: 999px; padding-inline: 30px; }
[data-knopf="gross"] .knopf { font-size: 19px; padding: 20px 32px; border-radius: calc(var(--radius) + 2px); }
[data-knopf="unterstrich"] .knopf {
  background: none; border: 0; border-bottom: 3px solid var(--akzent); color: currentColor;
  border-radius: 0; padding: 8px 2px; }
[data-knopf="unterstrich"] .knopf--zweit { border-bottom-color: currentColor; opacity: .75; }
@media (hover: hover) {
  .knopf { transition: transform var(--ueber, .3s) var(--kurve), filter var(--ueber, .3s) ease, background var(--ueber, .3s) ease; }
  [data-knopf="rahmen"] .knopf:hover, [data-knopf="unterstrich"] .knopf:hover { background: var(--akzent); color: var(--akzent-text); border-color: var(--akzent-tief); }
}

/* Die Überschrift im Textkasten war auf 13 Zeichen IHRER Schrift begrenzt, der
   Kasten auf 52 Zeichen der TEXTschrift — zwei verschiedene Maßstäbe. Bei großen
   Titelschriften lief sie heraus (Sebastian, 21.09.2026). Im Kasten gilt der Kasten. */
[data-textgrund="glas"] .s-held-vollbild .rahmen h1,
[data-textgrund="balken"] .s-held-vollbild .rahmen h1,
[data-textgrund="block"] .s-held-vollbild .rahmen h1 { max-width: 100%; overflow-wrap: break-word; }

/* ═══════════════════════════════════════════════════════════════════════════
   HELD GETEILT — Sektionsdurchgang 2 (Sebastian, 21.09.2026)
   „Headline-Animation, Entrance-Effekte, Buttons und Hovers. Bild rechts:
   entrance, Effekte, Skew/Rotate, Loop, Goo-Shadow, Outline, Passepartout."
   Fast alles davon sind vorhandene Schrauben, die diese Sektion nur nie
   erreicht haben. Neu ist der Goo-Schatten — ein farbiger Schein, der die
   Farbe des Bildes aufnimmt, statt grau darunter zu liegen.
   ═══════════════════════════════════════════════════════════════════════════ */

.s-held-geteilt { overflow: clip; }                      /* kein Scroll-Container */
.s-held-geteilt figure { position: relative; margin: 0; }

/* ——— 1. Einzug: Text von links, Bild von rechts, scrollgebunden ———
   ═══════════════════════════════════════════════════════════════════════════
   WARUM DER SEITENANFANG EINE ANDERE ZEITACHSE BRAUCHT (23.09.2026)

   Sebastian, zweimal: „Der Header ist kaputt — er ist schon im Start
   gedimmt." Und später: „Der Header ist immer noch verschwommen."

   Gemessen bei Scrollposition 0:  filter: blur(0.39px) · opacity: 0.875

   `animation-range: cover 0% exit 100%` zählt vom Eintritt ins Sichtfeld bis
   zum vollständigen Verlassen. Für jede Sektion in der Seitenmitte stimmt
   das. Der ERSTE Abschnitt ist beim Laden aber schon drin — bei ihm steht die
   Zeitachse sofort bei rund 30 %, also mitten in der Ausblendung, die eine
   Dreiviertelsekunde nach dem Öffnen niemand sehen soll.

   Für den Seitenanfang zählt deshalb nur der Abgang: `exit 0% exit 100%`
   beginnt erst, wenn die Sektion nach oben hinausläuft. Bis dahin steht der
   Text da, wie er soll.
   ═══════════════════════════════════════════════════════════════════════════ */
@supports (animation-timeline: view()) {
  .mit-bewegung .s-held-geteilt .text {
    animation: geteiltText linear both; animation-timeline: view(); animation-range: exit 0% exit 100%;
  }
  @keyframes geteiltText {
    0%, 25% { opacity: 1; transform: none; filter: blur(0); }
    100%    { opacity: .05; transform: translateX(calc(var(--weg) * -.8)) translateY(-20px); filter: blur(3px); }
  }
  .mit-bewegung .s-held-geteilt figure {
    animation: geteiltBild linear both; animation-timeline: view(); animation-range: exit 0% exit 100%;
  }
  /* Skew und Drehung kommen aus der Wucht: dezent fast gerade, laut schwungvoll. */
  /* Das Bild geht später und dreht sich dabei weg — es bleibt einen Moment
     länger stehen als der Text. Dieser Versatz macht den Abgang lebendig. */
  @keyframes geteiltBild {
    0%, 40% { opacity: 1; transform: none; }
    100%    { opacity: .12; transform: translateX(calc(var(--weg) * .8)) translateY(-40px) rotate(calc(var(--dreh) * 2.4)) skewY(calc(var(--dreh) * -.8)) scale(.9); }
  }
  /* Und weiter: Das Bild wandert über die ganze Sichtbarkeit leicht gegen die
     Scrollrichtung — dadurch entsteht Tiefe zwischen Text und Bild. */
  .mit-bewegung .s-held-geteilt figure img {
    animation: geteiltSchub linear both; animation-timeline: view(); animation-range: cover 0% cover 100%;
  }
  @keyframes geteiltSchub {
    from { transform: scale(var(--zoom)) translateY(calc(var(--schub) * -.4)); }
    to   { transform: scale(var(--zoom)) translateY(calc(var(--schub) * .4)); }
  }
}

/* ——— 2. Dauerbewegung auch hier ——— */
.mit-bewegung [data-bildlauf="kenburns"] .s-held-geteilt figure img { animation: kenBurns 22s ease-in-out infinite alternate; }
.mit-bewegung [data-bildlauf="schwenk"]  .s-held-geteilt figure img { animation: bildSchwenk 30s linear infinite alternate; }
.mit-bewegung [data-bildlauf="puls"]     .s-held-geteilt figure img { animation: bildPuls 14s ease-in-out infinite; }
.mit-bewegung [data-bildlauf="schaukel"] .s-held-geteilt figure img { animation: bildSchaukel 24s ease-in-out infinite alternate; }

/* ——— 3. Goo-Schatten: farbiger Schein statt grauem Kasten ———
   Ein zweites, unscharfes Abbild hinter dem Bild, in der Markenfarbe. Das ist
   der Unterschied zwischen „Bild mit Schatten" und „Bild, das leuchtet". */
.s-held-geteilt figure::before {
  content: ""; position: absolute; inset: 6% 4% -4%; z-index: -1; border-radius: inherit;
  background: radial-gradient(60% 60% at 50% 60%, color-mix(in oklab, var(--akzent) 55%, transparent), transparent 72%);
  filter: blur(42px); opacity: 0; transition: opacity var(--ueber, .6s) ease;
}
[data-schatten="tief"] .s-held-geteilt figure::before,
[data-schatten="weich"] .s-held-geteilt figure::before { opacity: .85; }
[data-schatten="hart"] .s-held-geteilt figure { box-shadow: 9px 9px 0 color-mix(in oklab, var(--tinte) 24%, var(--grund)); }
[data-schatten="linie"] .s-held-geteilt figure { box-shadow: 0 0 0 3px var(--akzent); }
[data-schatten="keiner"] .s-held-geteilt figure { box-shadow: none; }

/* ——— 4. Passepartout und Form ——— */
[data-passepartout="schmal"] .s-held-geteilt figure { padding: 12px; background: var(--grund2); }
[data-passepartout="breit"]  .s-held-geteilt figure { padding: 26px; background: var(--grund2); }
[data-ecke] .s-held-geteilt figure { border-radius: var(--ecke); }
[data-ecke] .s-held-geteilt figure img { border-radius: calc(var(--ecke) * .6); }
[data-neigung="leicht"]   .s-held-geteilt figure { rotate: 1deg; }
[data-neigung="deutlich"] .s-held-geteilt figure { rotate: 2.4deg; }

/* ——— 5. Zeigen ——— */
@media (hover: hover) {
  .s-held-geteilt figure { transition: transform var(--ueber, .6s) var(--kurve), box-shadow var(--ueber, .6s) ease; }
  .s-held-geteilt figure:hover::before { opacity: 1; }
  [data-zeigen="zoom"]       .s-held-geteilt figure:hover { transform: scale(1.03); }
  [data-zeigen="unschaerfe"] .s-held-geteilt figure:hover img { filter: brightness(.82); }
  [data-zeigen="grau"]       .s-held-geteilt figure:hover img { filter: grayscale(1); }
  [data-zeigen="farbe"]      .s-held-geteilt figure:hover img { filter: saturate(1.45); }
}

/* Das Seitenverhältnis darf nicht starr 4:5 bleiben — bei „modern" wird es
   quadratisch, bei „traditionell" hochformatig wie ein Portrait. */
[data-ecke="kapsel"] .s-held-geteilt figure,
[data-ecke="rund"]   .s-held-geteilt figure { aspect-ratio: 1; }
[data-ecke="scharf"] .s-held-geteilt figure { aspect-ratio: 3/4; }

/* ═══════════════════════════════════════════════════════════════════════════
   EINHEITLICHER BILDÜBERZUG (Sebastian, 21.09.2026)
   „Das Bild sollte denselben Overlay oder Tint haben wie die vorangegangenen
   Sektionen, damit es einheitlich ist." Richtig — der Überzug war bisher eine
   Eigenheit des Vollbild-Helden. Jetzt liegt er auf JEDEM Bild der Seite, nur
   in abgestufter Stärke: Auf dem Helden trägt er den Text, überall sonst sorgt
   er nur für eine gemeinsame Handschrift.
   ═══════════════════════════════════════════════════════════════════════════ */
.s figure, .s-bildband picture, .s-galerie-raster figure { position: relative; }
.s figure::after, .lauf-bild::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit;
  background: var(--tint, none); mix-blend-mode: var(--tint-misch, normal); opacity: var(--tint-kraft, 0);
  transition: opacity var(--ueber, .55s) ease;
}
/* Die sechs Überzüge setzen nur Variablen — die Regel oben verteilt sie. */
[data-ueberzug="unten"]    { --tint: linear-gradient(0deg, rgba(0,0,0,.55), transparent 62%); --tint-kraft: .55; }
[data-ueberzug="seite"]    { --tint: linear-gradient(90deg, rgba(0,0,0,.5), transparent 68%); --tint-kraft: .5; }
[data-ueberzug="schleier"] { --tint: color-mix(in oklab, var(--dunkel) 50%, transparent); --tint-kraft: .42; }
[data-ueberzug="duplex"]   { --tint: linear-gradient(120deg, var(--akzent), var(--dunkel)); --tint-misch: multiply; --tint-kraft: .38; }
[data-ueberzug="kaum"]     { --tint: linear-gradient(0deg, rgba(0,0,0,.4), transparent 38%); --tint-kraft: .3; }
[data-ueberzug="maske"]    { --tint: none; --tint-kraft: 0; }
/* Auf dem Helden bleibt er stark — dort muss er Schrift tragen. */
.s-held-vollbild::after, .s-held-notdienst::after { opacity: 1; }

/* ═══════════════════════════════════════════════════════════════════════════
   LUFT, FLÄCHE, AUSRICHTUNG, RUNDUNG (21.09.2026)
   Sebastian: „Diese beiden Regler haben bisher keine Auswirkung auf die
   Visualität." Belegt — `edel` und `naehe` hatten Stufen, die zur vorigen
   identisch waren, und ihre Wirkung (Schatten, Bildfilter) ist fein. Jede
   Achse braucht mindestens eine Schraube, die man aus drei Metern sieht.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ——— Luft: das stärkste Mittel für „edel". Teure Seiten atmen. ——— */
[data-luft="eng"]       { --luft: .7; }
[data-luft="knapp"]     { --luft: .85; }
[data-luft="normal"]    { --luft: 1; }
[data-luft="weit"]      { --luft: 1.35; }
[data-luft="sehr-weit"] { --luft: 1.75; }
[data-luft] .s { padding-block: calc(clamp(64px, 9vw, 120px) * var(--luft, 1)); }
[data-luft] .s-kopf { margin-bottom: calc(clamp(28px, 4vw, 48px) * var(--luft, 1)); }
[data-luft="weit"] .rahmen, [data-luft="sehr-weit"] .rahmen { max-width: 1100px; }
[data-luft="eng"] .rahmen { max-width: 1280px; }

/* ——— Fläche oder Linie: gefüllt wirkt handfest, Linien wirken teuer ——— */
[data-flaeche="linie"] .s article, [data-flaeche="linie"] .s .kasten,
[data-flaeche="linie"] .s .karte:not(.glas) {
  background: none; border: 1px solid var(--linie); box-shadow: none;
  color: var(--tinte);
}
[data-flaeche="linie"] .s article *, [data-flaeche="linie"] .s .karte:not(.glas) * { color: var(--tinte); }
[data-flaeche="linie"] .s article p, [data-flaeche="linie"] .s .karte:not(.glas) p { color: var(--leise); }
[data-flaeche="linie"] .s article a:not(.knopf), [data-flaeche="linie"] .s .karte:not(.glas) a:not(.knopf) { color: var(--akzent-tief); }
[data-flaeche="linie"] .s article .knopf:not(.knopf--zweit) { color: var(--auf-akzent, #fff); }
[data-flaeche="linie"] .s .kacheln > article { border-width: 0 0 1px; border-radius: 0; padding-inline: 0; }
[data-flaeche="linie"] .s-leiste-fakten li { border-left: 1px solid var(--linie); }

/* ——— Ausrichtung: sachlich steht links, persönlich rückt in die Mitte ——— */
[data-ausrichtung="mittig"] .s-kopf { margin-inline: auto; text-align: center; }
[data-ausrichtung="mittig"] .s-kopf .s-einleitung { margin-inline: auto; }
[data-ausrichtung="mittig"] .s .drei > article,
[data-ausrichtung="mittig"] .s .kacheln > article { text-align: center; }
[data-ausrichtung="mittig"] .s .personen article { text-align: center; }
[data-ausrichtung="mittig"] .s .personen .initiale { margin-inline: auto; }

/* ——— Rundung der Gesichter und Symbole: Nähe rundet ——— */
[data-rundung="eckig"] .initiale, [data-rundung="eckig"] .symbol { border-radius: 0; }
[data-rundung="weich"] .initiale, [data-rundung="weich"] .symbol { border-radius: 8px; }
[data-rundung="rund"]  .initiale, [data-rundung="rund"]  .symbol { border-radius: 22px; }
[data-rundung="kreis"] .initiale, [data-rundung="kreis"] .symbol { border-radius: 999px; }

/* ═══════════════════════════════════════════════════════════════════════════
   HELD TYPO — Sektionsdurchgang 3 (Sebastian, 21.09.2026)
   „Die Headline darf eine dicke Outline in der Hintergrundfarbe haben, die man
   nur dann sieht, wenn das Bild hinter die Überschrift wandert — das würde
   einen Tiefeneffekt geben. Lass das Bild in diesem Modul einfach entfernen,
   alles zentriert, und arbeite mit Texteffekten."

   Das Bild ist raus: Ein Modul namens „Großer Schriftzug" soll ein Schriftzug
   sein. Für Titel MIT Bild gibt es held-geteilt und held-vollbild.

   Wichtig bei der Kontur: `-webkit-text-stroke` allein zeichnet die Linie
   MITTIG auf den Buchstabenrand — sie frisst die Punzen von innen, und fette
   Schriften werden matschig. `paint-order: stroke fill` legt die Linie nach
   hinten, die Füllung deckt sie innen wieder ab. Erst dann trägt der Kniff.
   ═══════════════════════════════════════════════════════════════════════════ */

.s-held-typo {
  min-height: min(92svh, 1000px); display: flex; flex-direction: column; justify-content: center;
  text-align: center; overflow: clip; position: relative;
}
.s-held-typo .rahmen { display: grid; justify-items: center; gap: clamp(14px, 1.8vw, 26px); position: relative; z-index: 2; }
.s-held-typo h1 { max-width: 16ch; margin: 0; }
.s-held-typo .unter { max-width: 46ch; margin: 0; }
.s-held-typo .knoepfe { justify-content: center; }

/* ——— Die Kontur in Hintergrundfarbe, plus weicher Schein ——— */
.typo-zug {
  paint-order: stroke fill;                     /* Linie nach hinten, Füllung deckt */
  -webkit-text-stroke: var(--kontur, 0px) var(--kontur-farbe, var(--grund));
  text-stroke: var(--kontur, 0px) var(--kontur-farbe, var(--grund));
  filter: var(--kontur-schatten, none);
  --filter-ruhe: var(--kontur-schatten, none);
  position: relative; z-index: 2;
}
/* Stärke folgt der Wucht. Der Schatten bleibt in jeder Stufe dezent — er soll
   die Kontur abheben, nicht selbst auffallen. */
[data-wucht="dezent"] .typo-zug { --kontur: 6px;  --kontur-schatten: drop-shadow(0 3px 7px color-mix(in oklab, currentColor 34%, transparent)); }
:root, [data-wucht="mittel"] .typo-zug { --kontur: 10px; --kontur-schatten: drop-shadow(0 5px 12px color-mix(in oklab, currentColor 40%, transparent)); }
[data-wucht="laut"] .typo-zug { --kontur: 16px; --kontur-schatten: drop-shadow(0 8px 20px color-mix(in oklab, currentColor 46%, transparent)); }

/* ——— Über einem Foto: Schatten ja, Kontur nein ———
   (Sebastian, 21.09.2026: „Bei held-vollbild würde ich das mit der Outline
   nicht machen — Shadow ist okay, aber Outline hier nicht.")
   Der Versuch mit dunkler Kontur stand am Bild und wirkte wie ein Aufkleber:
   Das Foto trägt die Sektion, die Schrift liegt darauf. Ein weicher Schatten
   löst sie ausreichend vom Motiv, ohne sie davorzukleben. Die Kontur bleibt,
   wo die Schrift selbst das Motiv ist — in held-typo.
   Gilt für held-notdienst mit: gleicher Aufbau, gleiche Situation. */
.held-auf-bild {
  filter: var(--auf-bild-schatten, drop-shadow(0 4px 16px color-mix(in oklab, var(--tinte) 55%, transparent)));
  --filter-ruhe: var(--auf-bild-schatten, drop-shadow(0 4px 16px color-mix(in oklab, var(--tinte) 55%, transparent)));
}
[data-wucht="dezent"] .held-auf-bild { --auf-bild-schatten: drop-shadow(0 3px 10px color-mix(in oklab, var(--tinte) 45%, transparent)); }
[data-wucht="laut"] .auf-bild   { --auf-bild-schatten: drop-shadow(0 6px 22px color-mix(in oklab, var(--tinte) 62%, transparent)); }

/* Kein Hintergrundmotiv (Sebastian, 21.09.2026: „Mach das hässliche Ding im
   Hintergrund noch weg."). Der erste Entwurf zog ein unscharfes Farbband hinter
   der Schrift durch, damit die Kontur an der Kreuzung aufblitzt — als Fleck
   gelesen, nicht als Effekt. Die Kontur trägt sich auch allein: Rand in
   Hintergrundfarbe plus weicher Schatten löst die Schrift von der Fläche.
   Dafür braucht es kein Motiv, und auf tausend Kundenseiten kann keins schiefgehen. */

@supports (animation-timeline: view()) {
  /* Die Schrift selbst zieht gegenläufig und wird beim Verlassen größer —
     als liefe man an ihr vorbei. */
  .mit-bewegung .s-held-typo .rahmen {
    /* Dieselbe Rechnung wie beim geteilten Helden: Der Seitenanfang ist beim
       Laden schon im Sichtfeld, also zählt nur der Abgang. */
    animation: typoZug linear both; animation-timeline: view(); animation-range: exit 0% exit 100%;
  }
  @keyframes typoZug {
    0%      { transform: translateY(26px) scale(.97); opacity: .7; }
    35%, 62%{ transform: none; opacity: 1; }
    100%    { transform: translateY(-70px) scale(1.06); opacity: .08; }
  }
}
/* Wortweiser Einlauf: hier größer gestaffelt als sonst, die Schrift ist riesig. */
.s-held-typo .wort { transition-delay: calc(var(--w, 0) * 90ms) !important; }

/* ——— Einzug des Schriftzugs (Sebastian, 21.09.2026: „Der Text soll eine
   attraktive Entry-Animation bekommen.") ———
   Drei Dinge laufen zusammen, das macht den Unterschied zu „fährt rein":
     1. Die Sperrung zieht sich zusammen — von weit gesetzt auf normal.
     2. Die Kontur wächst von null auf ihre Stärke, das Wort wird „dicker".
     3. Jedes Wort steigt versetzt auf und dreht sich dabei zurück in die Waage.
   Für die Kontur braucht es @property: Ohne Typangabe kann der Browser eine
   eigene Eigenschaft nicht überblenden, sie springt nur. */
@property --kontur {
  syntax: "<length>"; inherits: true; initial-value: 0px;
}
.mit-bewegung .s-held-typo .typo-zug {
  animation: typoEinzug 1.5s cubic-bezier(.16,.84,.3,1) both;
  animation-play-state: paused;
}
.mit-bewegung .s-held-typo .typo-zug.ist-sichtbar { animation-play-state: running; }
@keyframes typoEinzug {
  from { letter-spacing: .12em; --kontur: 0px; }
}
.mit-bewegung .s-held-typo .wort {
  transform: translateY(.42em) rotate(2deg) scale(.96);
  transition: opacity .85s ease, transform .95s cubic-bezier(.16,.84,.3,1);
}
.mit-bewegung .s-held-typo .ist-sichtbar .wort { transform: none; }
/* Etikett, Unterzeile, Knöpfe folgen der Schrift — gestaffelt, nicht gleichzeitig. */
.mit-bewegung .s-held-typo .s-etikett { transition-delay: 0s; }
.mit-bewegung .s-held-typo .unter { transition-delay: .35s; }
.mit-bewegung .s-held-typo .knoepfe { transition-delay: .5s; }
.mit-bewegung .s-held-typo .sterne { transition-delay: .62s; }

/* ═══════════════════════════════════════════════════════════════════════════
   HELD-COLLAGE (21.09.2026, eigenständig nach Sebastians bisherigem Feedback)
   Die Vorgaben aus den vorigen Sektionen, hier angewandt:
     · Hero → Schwerpunkt auf den EXIT, nicht auf den Einzug
     · Bilder dürfen nicht stillstehen, und nicht alle gleich
     · gleicher Tint wie überall (liegt schon auf .s figure::after)
     · Hover ist Pflicht
     · in der lauten Stufe darf es loopen
     · die Stellschrauben müssen greifen
   Der Kniff: Einzug, Parallaxe und Exit sind EINE scrollgebundene Animation je
   Bild statt drei konkurrierende. Der Scrollverlauf liefert die Dramaturgie
   ohnehin — die Collage schiebt sich zusammen, steht kurz, und driftet beim
   Verlassen auseinander. Drei getrennte Animationen hätten sich um `transform`
   gestritten, wie es beim Heldenbild schon einmal passiert ist.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Wie weit die Bilder auseinanderlaufen — die Wucht bestimmt den Ausschlag. */
.s-held-collage { --coll-weg: 34px; --coll-dreh: 3deg; --coll-zoom: .06; }
[data-wucht="dezent"] .s-held-collage { --coll-weg: 18px; --coll-dreh: 1.5deg; --coll-zoom: .03; }
[data-wucht="laut"] .s-held-collage   { --coll-weg: 58px; --coll-dreh: 5deg;   --coll-zoom: .1; }

@supports (animation-timeline: view()) {
  .mit-bewegung .s-held-collage .bilder figure {
    animation: collageZug linear both;
    animation-timeline: view();
    animation-range: entry 10% exit 90%;
  }
  /* Die Tiefe staffelt den Ausschlag: Das hintere Bild bewegt sich am wenigsten,
     das vorderste am meisten. Genau so verhält sich echte Tiefenschärfe — und
     genau daran erkennt das Auge, dass die drei Bilder nicht auf einer Ebene
     liegen. */
  .mit-bewegung .s-held-collage .b1 { --t: .6; --seite: -1; }
  .mit-bewegung .s-held-collage .b2 { --t: 1;  --seite:  1; }
  .mit-bewegung .s-held-collage .b3 { --t: 1.5; --seite: -1; }
  @keyframes collageZug {
    0% {
      transform: translate3d(calc(var(--seite) * var(--coll-weg) * var(--t) * 1.4), calc(var(--coll-weg) * var(--t)), 0)
                 scale(calc(1 - var(--coll-zoom)));
      opacity: .2;
    }
    26%, 62% { transform: none; opacity: 1; }
    100% {
      transform: translate3d(calc(var(--seite) * var(--coll-weg) * var(--t) * 2.2), calc(var(--coll-weg) * var(--t) * -1.6), 0)
                 scale(calc(1 + var(--coll-zoom)));
      opacity: .12;
    }
  }
  /* Der Text zieht gegenläufig weg — beim Verlassen schneller als die Bilder,
     damit der Blick den Bildern folgt und nicht der Schrift hinterherliest. */
  .mit-bewegung .s-held-collage .text {
    animation: collageText linear both;
    animation-timeline: view();
    animation-range: entry 10% exit 90%;
  }
  @keyframes collageText {
    0%       { transform: translateY(calc(var(--coll-weg) * .8)); opacity: .45; }
    26%, 58% { transform: none; opacity: 1; }
    100%     { transform: translateY(calc(var(--coll-weg) * -2.4)); opacity: .1; }
  }
}

/* Firefox und alles ohne view(): ein einfacher Einzug über den Beobachter.
   Lieber schlicht und richtig als gar nichts — die Sektion muss überall stehen. */
@supports not (animation-timeline: view()) {
  .mit-bewegung .s-held-collage .bilder figure {
    opacity: 0; transform: translateY(26px);
    transition: opacity .8s ease var(--verzug, 0s), transform .9s cubic-bezier(.16,.84,.3,1) var(--verzug, 0s);
  }
  .mit-bewegung .s-held-collage .b2 { --verzug: .12s; }
  .mit-bewegung .s-held-collage .b3 { --verzug: .24s; }
  .mit-bewegung .s-held-collage .ist-sichtbar .bilder figure,
  .mit-bewegung .s-held-collage.ist-sichtbar .bilder figure { opacity: 1; transform: none; }
}

/* ——— Hover: eines kommt nach vorn, die anderen treten zurück ———
   Pflicht laut Sebastian. Wichtig ist der zweite Teil: Ohne das Zurücktreten
   der Nachbarn wirkt das Anheben wie ein Fehler statt wie eine Auswahl. */
@media (hover: hover) {
  .s-held-collage .bilder:hover figure { scale: .97; filter: saturate(.75) brightness(.94); }
  .s-held-collage .bilder figure:hover {
    scale: calc(1 + var(--coll-zoom) * 1.6); filter: none; z-index: 5;
    box-shadow: 0 30px 70px rgba(0,0,0,.3);
  }
}

/* ——— Das Atmen läuft IMMER, nur unterschiedlich weit ———
   (Sebastian, 21.09.2026: „Keine dezente Animation der Collage-Bilder?")
   Der Loop hing zuerst allein an der lauten Stufe — in den anderen beiden stand
   die Collage still, sobald man nicht scrollte. Ein Standbild fällt genau dann
   auf, wenn der Besucher liest. Jetzt atmet sie überall, in dezent nur 2 %.
   Je Bild eine eigene Dauer und ein negativer Versatz: im Gleichschritt liest
   man dasselbe als Ruckeln. */
.s-held-collage { --atem-weg: 1.045; }
[data-wucht="dezent"] .s-held-collage { --atem-weg: 1.02; }
[data-wucht="laut"] .s-held-collage   { --atem-weg: 1.08; }
.mit-bewegung .s-held-collage .bilder figure img {
  animation: collageAtmen var(--atem, 14s) ease-in-out infinite alternate;
}
.mit-bewegung .s-held-collage .b1 img { --atem: 13s; animation-delay: -2s; }
.mit-bewegung .s-held-collage .b2 img { --atem: 17s; animation-delay: -7s; }
.mit-bewegung .s-held-collage .b3 img { --atem: 11s; animation-delay: -4s; }
@keyframes collageAtmen { from { scale: 1; } to { scale: var(--atem-weg); } }

/* ——— Die Stellschrauben greifen auch hier ——— */
[data-ecke] .s-held-collage .bilder figure { border-radius: var(--ecke); }
[data-passepartout="keins"]  .s-held-collage .bilder figure { --passepartout: 0px; }
[data-passepartout="schmal"] .s-held-collage .bilder figure { --passepartout: 5px; }
[data-passepartout="breit"]  .s-held-collage .bilder figure { --passepartout: 12px; }
[data-neigung="keine"]    .s-held-collage .bilder figure { --dreh-b: 0deg; }
[data-neigung="deutlich"] .s-held-collage .b1 { --dreh-b: -6deg; }
[data-neigung="deutlich"] .s-held-collage .b2 { --dreh-b: 5deg; }
[data-neigung="deutlich"] .s-held-collage .b3 { --dreh-b: -2.5deg; }
[data-schatten="keiner"] .s-held-collage .bilder figure { box-shadow: none; }
[data-schatten="tief"]   .s-held-collage .bilder figure { box-shadow: 0 30px 70px rgba(0,0,0,.26); }
[data-schatten="hart"]   .s-held-collage .bilder figure { box-shadow: 6px 6px 0 color-mix(in oklab, var(--tinte) 24%, var(--grund)); }
[data-schatten="linie"]  .s-held-collage .bilder figure { box-shadow: 0 0 0 1px color-mix(in oklab, var(--tinte) 28%, transparent); }

@media (prefers-reduced-motion: reduce) {
  .mit-bewegung .s-held-collage .bilder figure img { animation: none; }
}

/* ——— Zwei Schrauben, die einander widersprechen ———
   (Sebastian, 21.09.2026: „ACHTUNG — Darstellungsfehler")
   `flaeche=linie` nimmt den Karten ihren Hintergrund, `schatten=*` gibt ihnen
   einen Schlagschatten. Zusammen ergibt das einen Schatten um nichts. Der
   Flächenschatten verliert: Wo keine Fläche ist, wirft nichts einen Schatten.
   Steht bewusst am Dateiende — die Regel muss jede spätere Sektionsregel
   überstimmen, sonst gewinnt in einer von sechs Stilwelten wieder die falsche. */
[data-flaeche="linie"] .s article, [data-flaeche="linie"] .s .karte:not(.glas),
[data-flaeche="linie"] .s .kasten, [data-flaeche="linie"] .s .kachel,
[data-flaeche="linie"] .s .person, [data-flaeche="linie"] .lauf-karte {
  box-shadow: none;
}
/* Beim Überfahren darf sie trotzdem antworten — dann aber mit der Linie, nicht
   mit einem Schatten, den es in dieser Gestaltung nicht gibt. */
@media (hover: hover) {
  [data-flaeche="linie"] .s article:hover, [data-flaeche="linie"] .s .karte:not(.glas):hover {
    box-shadow: none; border-color: var(--akzent-tief);
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   LEISTE-FAKTEN (21.09.2026)
   Sebastian: „leiste-fakten sieht noch EXTREM langweilig aus — hier musst du
   noch ran. Gradient im Hintergrund? Entrance-Effekte?"
   Beides, plus das, was die Sektion eigentlich ist: die erste Zahl, die ein
   Besucher sieht. Sie darf nicht dastehen wie eine Tabelle.
   ═══════════════════════════════════════════════════════════════════════════ */
.s-leiste-fakten {
  position: relative; overflow: clip;
  background:
    radial-gradient(120% 180% at 12% -30%, color-mix(in oklab, var(--akzent) 42%, var(--dunkel)), transparent 62%),
    linear-gradient(112deg, color-mix(in oklab, var(--dunkel) 92%, var(--akzent)), var(--dunkel) 58%);
}
/* Ein breiter, sehr weicher Lichtstreifen, der beim Scrollen quer durchzieht.
   Er trägt keine Information — er nimmt der Fläche das Tote. */
.s-leiste-fakten::before {
  content: ""; position: absolute; z-index: 0; inset: -60% -30%;
  background: linear-gradient(100deg, transparent 32%, color-mix(in oklab, var(--akzent) 30%, transparent) 50%, transparent 68%);
  opacity: .8; pointer-events: none;
}
/* Der Lichtstreifen stand hier zuerst am Scrollbalken und zog quer durch die
   Leiste. Sebastian, 21.09.2026: „Irgendwie sieht es buggy aus, wenn die
   Hintergründe ins Bild wandern." Er hat recht, und der Grund ist erklärbar:
   Ein Foto, das sich beim Scrollen verschiebt, liest das Auge als Tiefe — es
   weiß, dass hinter dem Fenster ein Raum liegt. Eine FARBFLÄCHE hat keinen
   Raum, in dem sie liegen könnte. Sie wandert einfach, und Bewegung ohne Grund
   liest sich als Fehler.
   Seitdem gilt: Bilder dürfen am Scrollbalken hängen, Farbflächen und Verläufe
   stehen still. Die Leiste bezieht ihre Lebendigkeit aus dem Einzug der Zahlen
   und dem Hover — beides hat einen Anlass. */
.s-leiste-fakten::before { transform: skewX(-12deg); }
.s-leiste-fakten .rahmen { position: relative; z-index: 1; }

/* ——— Einzug: eine Zahl nach der anderen, nicht alle auf einmal ———
   Der Versatz ist der ganze Trick. Gleichzeitig eingeblendet wirken vier Zahlen
   wie ein Umschalten, nacheinander wie ein Aufbau. */
.mit-bewegung .s-leiste-fakten li {
  opacity: 0; transform: translateY(18px);
  transition: opacity .7s ease calc(var(--n, 0) * 110ms), transform .8s cubic-bezier(.16,.84,.3,1) calc(var(--n, 0) * 110ms);
}
.mit-bewegung .s-leiste-fakten li.ist-sichtbar { opacity: 1; transform: none; }
/* Die Trennlinie wächst mit, statt schon dazustehen. */
.s-leiste-fakten li { position: relative; border-left: 0; }
.s-leiste-fakten li + li::before {
  content: ""; position: absolute; left: 0; top: 0; width: 1px; height: 100%;
  background: color-mix(in oklab, var(--dunkel-text) 26%, transparent);
  transform: scaleY(0); transform-origin: center;
  transition: transform .7s cubic-bezier(.16,.84,.3,1) calc(var(--n, 0) * 110ms + 140ms);
}
.mit-bewegung .s-leiste-fakten li.ist-sichtbar + li::before,
.s-leiste-fakten li.ist-sichtbar::before,
.ohne-bewegung .s-leiste-fakten li + li::before { transform: scaleY(1); }

/* ——— Hover: die Spalte antwortet ——— */
@media (hover: hover) {
  .s-leiste-fakten li { transition-property: opacity, transform, background; }
  .s-leiste-fakten li:hover { background: color-mix(in oklab, var(--akzent) 14%, transparent); }
  .s-leiste-fakten li:hover b { color: color-mix(in oklab, var(--akzent) 70%, #fff); }
  .s-leiste-fakten b { transition: color .35s ease; }
}

/* Die Zahl darf größer atmen als der Text daneben — sie ist das Argument. */
.s-leiste-fakten li { padding: clamp(26px, 3.4vw, 40px) clamp(18px, 2.4vw, 30px); }
.s-leiste-fakten span { display: block; margin-top: 6px; opacity: .78; letter-spacing: .01em; }
/* Die Leiste ist eine LEISTE — ihre Höhe kommt aus dem Innenabstand der Spalten,
   nicht aus dem Sektionsabstand. Die Luft-Schraube hatte ihr oben und unten je
   120 px angehängt; der Inhalt klebte dann in der oberen Hälfte. Die Luft wirkt
   hier über die Spalten weiter, nur eben ohne toten Raum darunter. */
.s-leiste-fakten, [data-luft] .s-leiste-fakten { padding-block: 0; }
[data-luft] .s-leiste-fakten li { padding-block: calc(clamp(26px, 3.4vw, 40px) * var(--luft, 1)); }

/* ═══════════════════════════════════════════════════════════════════════════
   KARTEN (21.09.2026)
   Sebastian: „Warum haben wir kein cooles Kartenwidget? […] Wir haben NOCH
   bessere Möglichkeiten der Verzerrung und Manipulation der Kartendarstellung."
   Weil wir die Karte selbst zeichnen (tools/karte.mjs), ist sie kein Bild,
   sondern SVG — jede Linie erbt unsere Farbvariablen und lässt sich bewegen.
   ═══════════════════════════════════════════════════════════════════════════ */
.s-karte-standort, .s-einsatzgebiet--karte, .s-kontakt-formular--karte {
  position: relative; overflow: clip;
  display: flex; align-items: center;
  min-height: min(82svh, 780px);
}
.karte-flaeche { position: absolute; inset: -6%; z-index: 0; pointer-events: none; }
.karte-flaeche .karte-svg { width: 100%; height: 100%; display: block; }
.s-karte-standort .rahmen, .s-einsatzgebiet--karte .rahmen, .s-kontakt-formular--karte .rahmen {
  position: relative; z-index: 1; width: 100%;
}

/* Der Kasten steht auf der Karte, nicht daneben — so bleibt die Karte ganz. */
.karte-kasten, .gebiet-kasten {
  max-width: 460px; padding: clamp(24px, 3vw, 38px);
  border-radius: var(--radius); box-shadow: 0 26px 70px rgba(0,0,0,.16);
}
.karte-kasten h2 { margin: 0 0 12px; }
.karte-kasten .adresse { margin: 0 0 14px; font-size: 19px; line-height: 1.5; }
.karte-kasten .knoepfe { margin: 20px 0 0; display: flex; flex-wrap: wrap; gap: 10px; }
/* Einsatzgebiet: Text links, Diagramm rechts. Als Vollflächen-Hintergrund lag
   der Textkasten genau auf dem Betrieb — dem einzigen Punkt, der zählt. */
.s-einsatzgebiet--karte .raster { display: grid; grid-template-columns: minmax(240px, .8fr) minmax(360px, 1.5fr); gap: clamp(28px, 4vw, 56px); align-items: center; }
.s-einsatzgebiet--karte .gebiet-text ul { list-style: none; margin: 18px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 20px; }
.s-einsatzgebiet--karte .gebiet-text li {
  padding: 6px 0 6px 18px; position: relative; flex: 0 0 auto; min-width: 42%;
  background: none; border: 0; border-radius: 0; box-shadow: none;
}
/* Keine Schraube darf aus einer Ortsangabe einen Knopf machen. */
[data-flaeche] .s-einsatzgebiet--karte .gebiet-text li,
[data-schatten] .s-einsatzgebiet--karte .gebiet-text li,
[data-ecke] .s-einsatzgebiet--karte .gebiet-text li {
  background: none; border: 0; box-shadow: none; border-radius: 0; padding-inline: 0 0;
  padding-left: 18px;
}
.s-einsatzgebiet--karte .gebiet-text li::before {
  content: ""; position: absolute; left: 0; top: 50%; width: 7px; height: 7px; margin-top: -3px;
  border-radius: 50%; background: var(--akzent);
}
.gebiet-bild { margin: 0; }
.gebiet-bild .karte-svg { width: 100%; height: auto; border-radius: var(--radius); display: block; }
.gebiet-bild figcaption { margin-top: 10px; font-size: 14px; color: var(--leise); }
/* Die Ortspunkte erscheinen nacheinander — das liest sich wie ein Aufzählen. */
/* Der Versatz kommt über `data-n`, nicht über ein Stil-Attribut — die
   Sicherheitsrichtlinie (style-src 'self') verwirft Attribute. */
.mit-bewegung .gebiet-bild .karte-ort { opacity: 0; transition: opacity .5s ease calc(var(--n, 0) * 130ms + .3s); }
.gebiet-bild .karte-ort[data-n="0"] { --n: 0; } .gebiet-bild .karte-ort[data-n="1"] { --n: 1; }
.gebiet-bild .karte-ort[data-n="2"] { --n: 2; } .gebiet-bild .karte-ort[data-n="3"] { --n: 3; }
.gebiet-bild .karte-ort[data-n="4"] { --n: 4; } .gebiet-bild .karte-ort[data-n="5"] { --n: 5; }
.gebiet-bild .karte-ort[data-n="6"] { --n: 6; } .gebiet-bild .karte-ort[data-n="7"] { --n: 7; }
.gebiet-bild .karte-ort[data-n="8"] { --n: 8; } .gebiet-bild .karte-ort[data-n="9"] { --n: 9; }
.mit-bewegung .gebiet-bild.ist-sichtbar .karte-ort { opacity: 1; }
.mit-bewegung .gebiet-bild .karte-ring { opacity: 0; transition: opacity .8s ease .15s; }
.mit-bewegung .gebiet-bild.ist-sichtbar .karte-ring { opacity: 1; }
.s-kontakt-formular--karte .formular { max-width: 560px; padding: clamp(24px, 3vw, 38px); border-radius: var(--radius); }

/* ——— Perspektive: die Karte liegt wie auf einem Tisch ———
   Sebastians Wunsch nach Perspektivwechseln. Sehr dezent — 6 Grad reichen, um
   Tiefe zu erzeugen; ab 12 Grad wird die Schrift auf der Karte unlesbar. */
.s-karte-standort[data-kartenstil] .karte-svg { transform: scale(1.06); transform-origin: 50% 45%; }

/* ——— Scrollbindung: die Karte zieht langsamer als der Kasten ———
   Der klassische Tiefeneindruck, hier besonders wirksam: Eine Karte, die sich
   mitbewegt, wirkt wie ein Fenster; eine, die stillsteht, wie eine Tapete. */
@supports (animation-timeline: view()) {
  .mit-bewegung :is(.s-karte-standort, .s-einsatzgebiet--karte, .s-kontakt-formular--karte) .karte-flaeche {
    animation: karteZug linear both; animation-timeline: view(); animation-range: cover 0% cover 100%;
  }
  @keyframes karteZug {
    from { transform: translate3d(0, -2.4%, 0) scale(1.08); }
    to   { transform: translate3d(0, 2.4%, 0) scale(1.08); }
  }
}

/* ——— Die Nadel schlägt einmal auf und pulst dann weiter ——— */
.mit-bewegung .karte-nadel { animation: nadelAuf .7s cubic-bezier(.2,1.5,.4,1) both; transform-box: fill-box; transform-origin: 50% 50%; }
@keyframes nadelAuf { from { scale: 0; opacity: 0; } to { scale: 1; opacity: 1; } }
.mit-bewegung .karte-puls { animation: nadelPuls 2.8s ease-out infinite; transform-box: fill-box; transform-origin: 50% 50%; }
@keyframes nadelPuls {
  0%   { scale: .6; opacity: .45; }
  70%  { scale: 2.1; opacity: 0; }
  100% { scale: 2.1; opacity: 0; }
}
/* Die Fahrzeit-Ringe zeichnen sich beim Sichtbarwerden. */
.mit-bewegung .karte-ring circle { stroke-dashoffset: 0; animation: ringAuf 1.4s ease-out both; transform-box: fill-box; transform-origin: 50% 50%; }
.mit-bewegung .karte-ring text { animation: ringText 1s ease-out .5s both; }
@keyframes ringAuf { from { scale: .6; opacity: 0; } to { scale: 1; opacity: 1; } }
@keyframes ringText { from { opacity: 0; } to { opacity: 1; } }

@media (hover: hover) {
  /* Beim Überfahren richtet sich die Karte auf — als schaue man genauer hin. */
  .s-karte-standort .karte-svg { transition: transform .9s cubic-bezier(.16,.84,.3,1); }
  .s-karte-standort:hover .karte-svg { transform: scale(1.12); }
}

@media (max-width: 860px) {
  .s-einsatzgebiet--karte .raster { grid-template-columns: 1fr; }
  .gebiet-kasten ul { columns: 2; }
}
/* Der Kasten durfte ab 860 px die volle Breite nehmen — und lag damit auf
   Tablet über dem Standortmarker. Sebastian dazu: „Der pulsierende Standort
   ist immer noch hinter der Box." Gemessen bei 820 px: Kasten 41–779, Nadel
   736–802. Erst ab 620 px ist die Sektion so schmal, dass volle Breite sein
   muss — und dort liegt die Nadel nicht mehr im Kastenbereich. */
@media (max-width: 620px) {
  .karte-kasten, .gebiet-kasten { max-width: none; }
}
@media (prefers-reduced-motion: reduce) {
  .mit-bewegung .karte-puls, .mit-bewegung .karte-nadel, .mit-bewegung .karte-ring circle { animation: none; }
}

/* Schrift IM Diagramm: Sie lebt im viewBox-Raum, wird also mitskaliert. Bei
   760 Einheiten auf 351 Pixel Handybreite werden aus 16 Einheiten 7,4 Pixel —
   unlesbar. CSS überschreibt das font-size-Attribut des SVG, deshalb lässt sich
   die Beschriftung hier gegensteuern, ohne zwei Grafiken zu erzeugen. */
.gebiet-bild .karte-ort text { font-size: 18px; }
.gebiet-bild .karte-ring text { font-size: 16px; }
@media (max-width: 1100px) {
  .gebiet-bild .karte-ort text { font-size: 21px; }
  .gebiet-bild .karte-ring text { font-size: 18px; }
  .gebiet-bild .karte-ort circle { r: 7; }
}
@media (max-width: 700px) {
  .gebiet-bild .karte-ort text { font-size: 30px; }
  .gebiet-bild .karte-ring text { font-size: 25px; }
  .gebiet-bild .karte-ort circle { r: 10; }
  .gebiet-bild .karte-ort text, .gebiet-bild .karte-ring text { stroke-width: 6; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   HOVER, DER IMMER FUNKTIONIERT (21.09.2026)
   Sebastian: „Im Hover bleibt ne orange Linie" — und gemessen tat der Hover auf
   den Kacheln GAR nichts: `[data-schatten="hart"]` setzte box-shadow fest, und
   die Hover-Regel darunter verlor. Ein Effekt, der von der Schattenstufe
   abhängt, ist kein Effekt.
   Deshalb läuft der Hover jetzt über `translate` und `scale` — Eigenschaften,
   die keine Schraube belegt. Der Schatten darf dazukommen, muss aber nicht.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (hover: hover) {
  .s .kacheln > article, .s .drei > article, .s .person,
  .s-sortiment article, .s-referenzen-karten article, .s-ablauf-schritte li {
    transition: translate .35s cubic-bezier(.16,.84,.3,1), scale .35s cubic-bezier(.16,.84,.3,1),
                border-color .35s ease, background .35s ease;
  }
  .s .kacheln > article:hover, .s .drei > article:hover, .s .person:hover,
  .s-sortiment article:hover, .s-referenzen-karten article:hover, .s-ablauf-schritte li:hover {
    translate: 0 -7px; scale: 1.015; border-color: color-mix(in oklab, var(--akzent) 55%, var(--linie));
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   DIE HINTEREN SEKTIONEN (21.09.2026)
   Sebastian: „Leistungen-nummeriert hat noch gar keine Aufarbeitung genossen —
   keine Animation, Effekte, Entrances, nix." Stimmt, und für die meisten
   anderen galt dasselbe. Hier bekommen sie, was die Held-Sektionen schon haben:
   einen gestaffelten Einzug, eine Scrollbindung und eine Antwort auf den
   Mauszeiger.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ——— Leistungen nummeriert ———
   Die Nummer ist der Held dieser Sektion. Sie zieht von links herein, während
   der Text steht — dadurch liest man sie als Abfolge statt als Liste. */
.s-leistungen-nummeriert ol { counter-reset: schritt; }
.mit-bewegung .s-leistungen-nummeriert li {
  opacity: 0; translate: 0 22px;
  transition: opacity .7s ease calc(var(--n, 0) * 110ms), translate .8s cubic-bezier(.16,.84,.3,1) calc(var(--n, 0) * 110ms);
}
.mit-bewegung .s-leistungen-nummeriert li.ist-sichtbar { opacity: 1; translate: none; }
.s-leistungen-nummeriert li { position: relative; transition: translate .35s ease; }
.s-leistungen-nummeriert li::marker { color: var(--akzent-tief); }
@media (hover: hover) {
  .s-leistungen-nummeriert li:hover { translate: 6px 0; }
  .s-leistungen-nummeriert li:hover h3 { color: var(--akzent-tief); }
  .s-leistungen-nummeriert h3 { transition: color .3s ease; }
}

/* ——— Akkordeon: sanft auf, sanft zu ———
   Sebastian: „Ausklappen klappt die anderen zu, aber sanft und edel mit Easing."
   Das `name`-Attribut macht die Gruppe exklusiv — der Browser schließt die
   anderen von selbst. Damit dabei nichts springt, wächst der Inhalt über
   grid-template-rows von 0fr auf 1fr; das ist der einzige Weg, eine unbekannte
   Höhe zu überblenden, der ohne JavaScript und in jedem Browser läuft. */
.s-leistungen-akkordeon details { border-bottom: 1px solid var(--linie); }
.s-leistungen-akkordeon summary {
  cursor: pointer; padding: 18px 40px 18px 0; position: relative;
  font-weight: 700; font-size: clamp(17px, 1.6vw, 21px); list-style: none;
  transition: color .3s ease, padding-left .35s cubic-bezier(.16,.84,.3,1);
}
.s-leistungen-akkordeon summary::-webkit-details-marker { display: none; }
.s-leistungen-akkordeon summary::after {
  content: ""; position: absolute; right: 8px; top: 50%; width: 11px; height: 11px;
  border-right: 2px solid var(--akzent); border-bottom: 2px solid var(--akzent);
  translate: 0 -60%; rotate: 45deg; transition: rotate .4s cubic-bezier(.16,.84,.3,1);
}
.s-leistungen-akkordeon details[open] summary::after { rotate: -135deg; }
.s-leistungen-akkordeon details[open] summary { color: var(--akzent-tief); }
@media (hover: hover) { .s-leistungen-akkordeon summary:hover { padding-left: 8px; } }
.s-leistungen-akkordeon .ak-huelle {
  display: grid; grid-template-rows: 0fr; overflow: hidden;
  transition: grid-template-rows .45s cubic-bezier(.16,.84,.3,1), opacity .35s ease;
  opacity: 0;
}
.s-leistungen-akkordeon .ak-huelle > p { min-height: 0; margin: 0; padding-bottom: 0; color: var(--leise); transition: padding-bottom .45s cubic-bezier(.16,.84,.3,1); }
.s-leistungen-akkordeon details[open] .ak-huelle > p { padding-bottom: 20px; }
.s-leistungen-akkordeon details[open] .ak-huelle { grid-template-rows: 1fr; opacity: 1; }

/* ——— Kacheln: erscheinen und verschwinden am Scrollbalken ———
   Sebastian: „Hier wäre ein scrollbasierter (Dis)Appearance ganz schön."
   Beim Hereinkommen steigen sie versetzt auf, beim Hinausgehen sinken sie ab.
   Der Versatz kommt aus der Spaltenposition, nicht aus der Reihenfolge — sonst
   läuft die vierte Kachel noch, wenn die erste längst oben aus dem Bild ist. */
@supports (animation-timeline: view()) {
  .mit-bewegung .s-leistungen-kacheln .kacheln > article {
    animation: kachelZug linear both;
    animation-timeline: view();
    animation-range: entry 0% exit 100%;
  }
  .mit-bewegung .s-leistungen-kacheln .kacheln > article:nth-child(2) { animation-range: entry -4% exit 104%; }
  .mit-bewegung .s-leistungen-kacheln .kacheln > article:nth-child(3) { animation-range: entry -8% exit 108%; }
  .mit-bewegung .s-leistungen-kacheln .kacheln > article:nth-child(4) { animation-range: entry -12% exit 112%; }
  @keyframes kachelZug {
    0%       { opacity: 0; transform: translateY(46px) scale(.96); }
    24%, 72% { opacity: 1; transform: none; }
    100%     { opacity: .25; transform: translateY(-34px) scale(.985); }
  }
}

/* ——— Referenzen: eine Karte, die wie eine Karte aussieht ———
   Sebastian: „Referenzen ist ne Katastrophe." Das Bild klebte am Text, es gab
   keine Fläche, keinen Abstand und keinen Einzug — drei Dinge, die zusammen
   den Eindruck ergeben, da sei etwas kaputt. */
.s-referenzen-karten .karten { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: clamp(18px, 2vw, 28px); }
.s-referenzen-karten article {
  background: var(--grund2); border: 1px solid var(--linie); border-radius: var(--radius);
  overflow: clip; display: flex; flex-direction: column;
}
.s-referenzen-karten .lupe { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; }
.s-referenzen-karten img { width: 100%; aspect-ratio: 4/3; object-fit: cover; border-radius: 0; margin: 0; display: block; }
.s-referenzen-karten h3 { margin: 18px clamp(16px, 1.6vw, 22px) 6px; font-size: clamp(18px, 1.7vw, 22px); }
.s-referenzen-karten article p { margin: 0 clamp(16px, 1.6vw, 22px) 20px; color: var(--leise); }
.mit-bewegung .s-referenzen-karten article {
  opacity: 0; translate: 0 26px;
  transition: opacity .7s ease calc(var(--n, 0) * 120ms), translate .85s cubic-bezier(.16,.84,.3,1) calc(var(--n, 0) * 120ms);
}
.mit-bewegung .s-referenzen-karten article.ist-sichtbar { opacity: 1; translate: none; }

/* ——— Bildband: der Satz stand ohne Einzug auf dem Bild ——— */
.mit-bewegung .s-bildband p { opacity: 0; translate: 0 18px; transition: opacity .8s ease .15s, translate .9s cubic-bezier(.16,.84,.3,1) .15s; }
.mit-bewegung .s-bildband p.ist-sichtbar { opacity: 1; translate: none; }
@supports (animation-timeline: view()) {
  .mit-bewegung .s-bildband img { animation: bildbandZug linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
  @keyframes bildbandZug { from { transform: scale(1.18) translateY(-3.5%); } to { transform: scale(1.18) translateY(3.5%); } }
}

/* ——— Mosaik: gestaffelt herein, Bildunterschrift kommt beim Überfahren ——— */
.mit-bewegung .s-galerie-mosaik figure {
  opacity: 0; scale: .96;
  transition: opacity .6s ease calc(var(--n, 0) * 80ms), scale .7s cubic-bezier(.16,.84,.3,1) calc(var(--n, 0) * 80ms);
}
.mit-bewegung .s-galerie-mosaik figure.ist-sichtbar { opacity: 1; scale: 1; }
.s-galerie-mosaik .lupe { position: absolute; inset: 0; display: block; width: 100%; height: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; }

/* ——— Leuchtkasten ——— */
.lupe { display: block; padding: 0; border: 0; background: none; cursor: zoom-in; width: 100%; }
.lupe img { display: block; width: 100%; }
.s-galerie-raster .lupe img { aspect-ratio: 1; object-fit: cover; border-radius: var(--radius); }
.leuchtkasten {
  border: 0; padding: 0; background: none; max-width: 100vw; max-height: 100dvh;
  width: 100%; height: 100%; overflow: hidden;
}
.leuchtkasten[open] {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 12px;
  place-items: center;
}
.leuchtkasten:not([open]) { display: none; }
.leuchtkasten::backdrop { background: rgba(8,10,12,.92); backdrop-filter: blur(6px); }
.leuchtkasten img {
  grid-column: 2; max-width: min(96vw, 1500px); max-height: 86dvh;
  width: auto; height: auto; object-fit: contain; border-radius: 6px;
  box-shadow: 0 30px 90px rgba(0,0,0,.5);
}
.leuchtkasten button {
  background: rgba(255,255,255,.12); color: #fff; border: 0; border-radius: 50%;
  width: 52px; height: 52px; font-size: 30px; line-height: 1; cursor: pointer;
  display: grid; place-items: center; transition: background .25s ease, scale .25s ease;
}
.leuchtkasten button:hover { background: rgba(255,255,255,.26); scale: 1.08; }
.lk-zu { position: fixed; top: 18px; right: 18px; font-size: 34px; }
.lk-vor { grid-column: 1; margin-left: 14px; }
.lk-zurueck { grid-column: 3; margin-right: 14px; }
/* 15 px ist die untere Grenze für Fließtext (tools/pruefen.mjs). Sie gilt auch
   hier: „3 von 8" auf dunklem Grund ist genau die Stelle, an der jemand mit
   müden Augen nachsieht, wie viele Bilder noch kommen. */
.lk-zaehler { position: fixed; bottom: 20px; left: 0; right: 0; text-align: center; color: rgba(255,255,255,.78); font-size: 15px; margin: 0; }
.leuchtkasten[open] { animation: lkAuf .28s ease both; }
@keyframes lkAuf { from { opacity: 0; scale: .97; } to { opacity: 1; scale: 1; } }
@media (max-width: 700px) {
  .leuchtkasten { grid-template-columns: 1fr; }
  .lk-vor, .lk-zurueck { position: fixed; bottom: 54px; margin: 0; }
  .lk-vor { left: 20px; } .lk-zurueck { right: 20px; }
}

/* Das Bildband ist eine Bildfläche, keine Textsektion: Die Luft-Schraube hängte
   ihm oben und unten je 137 px Polsterung an, das Bild füllte nur den Innenraum
   und der Satz hing unter dem Bild in der Leere (Sebastian, 21.09.2026: „Wo
   hängt der Text beim Bildband?"). Dieselbe Falle wie bei der Fakten-Leiste. */
.s-bildband, [data-luft] .s-bildband { padding-block: 0; }
[data-luft] .s-bildband { height: calc(clamp(280px, 48vw, 600px) * var(--luft, 1)); }

/* ═══════════════════════════════════════════════════════════════════════════
   KEINE SEKTION VERBREITERT DIE SEITE (21.09.2026)
   Gefunden von der Gesamtprüfung, nachdem sie auch bei 390 px lief: Auf dem
   Handy war die Seite in JEDER Einstellung seitlich verschiebbar. Täter war
   eine Collage-Kachel, die beim Hinausscrollen 127 px nach rechts driftet —
   ein Effekt von heute Nachmittag, der am Schreibtisch nie auffiel.
   `overflow-x: clip` statt `hidden`: `hidden` würde aus jeder Sektion einen
   Scroll-Container machen und damit scrollgebundene Animationen einfrieren —
   dieselbe Falle, die hier schon zweimal zugeschlagen hat.
   ═══════════════════════════════════════════════════════════════════════════ */
.s { overflow-x: clip; }

/* Auf schmalen Schirmen ist der Ausschlag ohnehin zu groß: 58 px Drift neben
   einer 196 px breiten Kachel sind keine Tiefe mehr, sondern Unruhe. */
@media (max-width: 720px) {
  .s-held-collage { --coll-weg: 14px; --coll-dreh: 1deg; --coll-zoom: .03; }
  [data-wucht="laut"] .s-held-collage { --coll-weg: 22px; }
}


/* ——— Glasflächen werfen weiche, durchscheinende Schatten ———
   (Sebastian, 21.09.2026: „Harte opake Schatten sind nicht so schön, und
   insbesondere nicht, wenn die schattenwerfende Fläche eine geringere Opazität
   hat als der Schatten — das wirkt falsch.")
   Die Regel dahinter ist einfach: Was man durchschauen kann, wirft keinen
   vollen Schatten. Die Prüfung vergleicht beide Werte und meldet jeden Verstoß. */
.glas, .karte.glas, .stimme-innen.glas, .karte-kasten.glas,
[data-schatten] .glas, [data-schatten] .s .karte.glas, [data-schatten] .s article.glas {
  box-shadow: 0 22px 58px color-mix(in oklab, var(--tinte) 26%, transparent);
}
[data-schatten="tief"] .glas { box-shadow: 0 34px 78px color-mix(in oklab, var(--tinte) 34%, transparent); }
[data-schatten="hart"] .glas, [data-schatten="hart"] .s .karte.glas { box-shadow: 6px 6px 0 color-mix(in oklab, var(--tinte) 18%, transparent); }
[data-schatten="keiner"] .glas, [data-schatten="keiner"] .s .karte.glas { box-shadow: none; }

/* ——— A7: Trennlinie so hoch wie ihre Fläche ———
   Die Linie stand auf 64 % Höhe, der Hover färbte die ganze Spalte — dadurch
   sah die Linie aus, als hätte man sie vergessen zu verlängern. */
.s-leiste-fakten li + li::before { top: 0; height: 100%; }

/* ——— A2: Wo eine Linie ist, braucht der Text Abstand ——— */
[data-flaeche="linie"] .s article, [data-flaeche="linie"] .s .karte:not(.glas),
[data-flaeche="linie"] .s .kasten, [data-flaeche="linie"] .s .kachel, [data-flaeche="linie"] .s .person {
  padding: clamp(14px, 1.6vw, 22px);
}
.s-sortiment article > :not(img):not(picture):not(.lupe) { padding-inline: clamp(14px, 1.6vw, 20px); }
.s-sortiment article > :last-child { padding-bottom: clamp(14px, 1.6vw, 20px); }
.s-sortiment article > :is(h3, h4):first-of-type { padding-top: clamp(12px, 1.4vw, 16px); }

/* Auf dem Handy steht das Formular über der ganzen Breite. Der erste Versuch,
   den Marker freizustellen, hat die Karte unten um 40 % gekappt — und damit
   genau den Fehler erzeugt, den Sebastian am 21.09.2026 gemeldet hat: „bei
   diesem Modul ist der Hintergrund NICHT vollständig — das Bild soll den
   GESAMTEN Hintergrund ausfüllen." Die eigene Prüfung hat es zwölfmal
   bestätigt: „Hintergrund lässt 314 px der Sektion frei."

   Der Marker ist dort inzwischen ohnehin ausgeblendet (siehe „Kein Marker
   hinter einem Kasten"), also braucht es die Kappung nicht mehr. Die Karte
   füllt wieder die ganze Sektion; das Formular bleibt nach unten versetzt,
   damit oben Karte zu sehen ist und nicht nur Milchglas. */
@media (max-width: 860px) {
  .s-kontakt-formular--karte { align-items: flex-end; padding-top: 38vh; }
  .s-einsatzgebiet--karte .gebiet-bild { margin-top: 18px; }
}

/* ——— Heldenbilder: auf dem Handy reichte die Reserve nicht ———
   Gemessen 8 px freier Rand bei 390 px Breite. Der Grund: Die Reserve steht in
   Pixeln (80 px), der Ausschlag der Parallaxe in Prozent — auf einem schmalen
   Schirm ist ein Prozent aber viel weniger wert, während der Mauszeiger-Effekt
   bei festen 12 px bleibt. Also mehr Vergrößerung statt mehr Pixel, und zwar
   über eine Variable: Keyframes zu verdoppeln geht beim nächsten Umbau schief. */
/* `--held-deckung: 1.3` stand hier, solange der Rand nur über Vergrößerung zu
   decken war. Seit `max-width: none` greift die Pixelreserve wieder, und die
   reicht allein:

     Bild 530 px breit in einer 390 px breiten Sektion → 70 px je Seite = 13,2 %
     Gebraucht werden   1,8 % (Schwenk) + 2,3 % (Mauszeiger)        =  4,1 %
     Senkrecht:  70 px von 984 px = 7,1 %, gebraucht 4,8 + 1 + 2,3  =  8,1 %
                 dazu die Grundvergrößerung 1,16 → 8 % je Seite

   Zurück auf den Wert der großen Schirme: Das Bild steht auf dem Handy nicht
   mehr 30 % über seinem Ausschnitt, sondern zeigt, was das Foto zeigt.
   Nachgemessen über 10 Breiten × 6 Stilwelten × 5 Bildlaufarten × 5 Punkte des
   Scrollwegs. (22.09.2026) */
@media (max-width: 720px) {
  .hintergrund { inset: 0 auto auto 0; height: calc(100% + 140px); margin-top: -70px; width: calc(100% + 140px); margin-left: -70px; }
  .gebiet-bild .karte-ort text { font-size: 34px; }
  .gebiet-bild .karte-ring text { font-size: 30px; }
}



/* ——— Farbige Flächen mit hellem Text ———
   Reine Akzentfarben liegen bei weißer Schrift oft knapp unter 4,5:1 — gemessen
   4,4:1 in werkstatt. Eine Spur dunkler reicht, und der Farbeindruck bleibt. */

.knopf:not(.knopf--zweit), button[type="submit"], .s .formular__fuss button, .notruf, .cta-knopf {
  background: var(--akzent-tief); border-color: var(--akzent-tief);
  color: var(--auf-akzent, #fff);
}
.s[data-ton="dunkel"] .knopf:not(.knopf--zweit),
.s-kontakt-karte .knopf:not(.knopf--zweit), .s-leitsatz .knopf:not(.knopf--zweit) {
  color: var(--auf-akzent-hell, #111);
}
/* Jede Fläche, die den Akzent trägt und hellen Text zeigt, nimmt die
   abgedunkelte Variante — reiner Akzent bleibt bei Weiß unter 4,5:1. */
.s-lieferung-abholung article, .s-werte-drei article[data-akzent], .balken, .s-cta-band .akzentflaeche,
.s-notdienst-leiste, .notdienst-leiste, .s-cta-band {
  background: var(--akzent-tief);
  color: var(--auf-akzent, #fff);
}
/* In dunklen Sektionen zeigt --akzent-tief auf den hellen Wert; dort gehört
   die dazu berechnete dunkle Schrift darauf. */
.s[data-ton="dunkel"] .s-lieferung-abholung article,
.s-lieferung-abholung article:is([data-weg="0"], [data-weg="1"]) { color: var(--auf-akzent, #fff); }
.s-lieferung-abholung article * { color: inherit; }



/* ═══════════════════════════════════════════════════════════════════════════
   WER DUNKEL AUSSIEHT, MUSS AUCH DUNKEL RECHNEN (21.09.2026)
   Gefunden über die Kontrastprüfung: `.s-kontakt-karte` trägt einen dunklen
   Hintergrund, ließ aber `--tinte` auf dem hellen Wert stehen. Jede daraus
   abgeleitete Farbe war damit falsch — das Etikett kam auf 1,2:1, also
   praktisch unsichtbar. Genau der Fehlertyp, den Sebastian als „schwarze
   Schrift auf schwarzem Grund" gemeldet hat.
   Diese Sektionen setzen den Hintergrund fest, deshalb bekommen sie hier
   denselben Variablensatz wie [data-ton="dunkel"].
   ═══════════════════════════════════════════════════════════════════════════ */
.s-leiste-fakten, .s-leitsatz, .s-kontakt-karte,
body:not([data-flaeche="linie"]) .s-oeffnungszeiten-tafel .tafel,
body:not([data-flaeche="linie"]) .s-lieferung-abholung article:nth-child(2) {
  --tinte: var(--dunkel-text);
  --grund: var(--dunkel);
  --grund2: color-mix(in oklab, var(--dunkel) 88%, #fff);
  --leise: color-mix(in oklab, var(--dunkel-text) 72%, transparent);
  --linie: color-mix(in oklab, var(--dunkel-text) 18%, transparent);
  --akzent-tief: var(--akzent-hell); --auf-akzent: var(--auf-akzent-hell, #111);
}

/* Die Ordnungszahlen in „Werte" standen im reinen Akzent auf hellem Grund —
   3,8:1. Als Überschrift wären 3:1 erlaubt, sie sind aber klein gesetzt. */
.s-werte-drei article > span { color: var(--akzent-tief); }

/* ═══════════════════════════════════════════════════════════════════════════
   KNÖPFE — fünf Stellungen (21.09.2026)
   Sebastian: „Die Buttons können bitte noch mehr Varianz und Effekt bekommen",
   mit Verweis auf 21st.dev. Die Vorlagen dort sind React plus Tailwind; hier
   stehen sie als reines CSS, ohne ein einziges zusätzliches Byte JavaScript.
   Zwei Dinge, die die Vorlagen nicht leisten und die hier Pflicht sind:
     · mindestens 44 px Höhe — die Hälfte der Besucher trifft mit dem Daumen
     · der Effekt darf die Beschriftung nie verdecken oder verzerren; „Anrufen"
       muss im Notdienst in jedem Moment lesbar bleiben
   Bewusst NICHT übernommen: der Buchstabentausch beim Überfahren. Er macht den
   wichtigsten Knopf der Seite für einen Moment unlesbar.
   ═══════════════════════════════════════════════════════════════════════════ */
.knopf {
  position: relative; overflow: hidden; isolation: isolate;
  min-height: 44px;
  transition: translate .18s var(--kurve, cubic-bezier(.16,.84,.3,1)),
              scale .18s var(--kurve, cubic-bezier(.16,.84,.3,1)),
              filter .18s ease, background .25s ease, border-color .25s ease, box-shadow .25s ease;
}
.knopf:hover { translate: 0 -2px; filter: brightness(1.04); transform: none; }
.knopf:active { translate: 0 0; scale: .985; }

/* ——— 1. schlicht: nur die Grundbewegung, sonst nichts ——— */
[data-knopf="schlicht"] .knopf:hover { filter: brightness(1.08); }

/* ——— 2. rahmen: zwei Linien laufen gegenläufig um den Knopf ———
   Aus „Dual Border Animation". Wirkt teuer, ohne eine zweite Farbe zu brauchen,
   und funktioniert deshalb auch in Stilwelten ohne kräftigen Akzent. */
[data-knopf="rahmen"] .knopf::before,
[data-knopf="rahmen"] .knopf::after {
  content: ""; position: absolute; inset: -2px; border-radius: inherit;
  border: 2px solid transparent; pointer-events: none; z-index: -1;
  transition: border-color .45s ease, inset .45s var(--kurve, cubic-bezier(.16,.84,.3,1));
}
[data-knopf="rahmen"] .knopf:hover::before {
  border-top-color: currentColor; border-right-color: currentColor; inset: -5px;
}
[data-knopf="rahmen"] .knopf:hover::after {
  border-bottom-color: currentColor; border-left-color: currentColor; inset: -5px;
  transition-delay: .1s;
}

/* ——— 3. schein: ein ruhiger Lichtsaum steigt auf ———
   (Sebastian, 21.09.2026: „Nimm die Rotation komplett raus und lass nur den
   anderen Shine, aber mach den dezenter.") Die rotierende Lichtsichel war zu
   unruhig: Ein Knopf, der sich dreht, zieht den Blick von dem ab, was
   daraufsteht. Jetzt hebt sich nur ein weicher Saum von unten — sichtbar
   genug, dass man die Reaktion bemerkt, still genug, dass man weiterliest. */
[data-knopf="schein"] .knopf::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit;
  background: radial-gradient(120% 90% at 50% 120%, color-mix(in oklab, #fff 24%, transparent), transparent 70%);
  opacity: 0; transition: opacity .4s ease;
}
[data-knopf="schein"] .knopf:hover::before { opacity: 1; }
[data-knopf="schein"] .knopf:hover { box-shadow: 0 6px 22px color-mix(in oklab, var(--akzent) 30%, transparent); }

/* ——— 6. motion: ein Kreis wächst von links zur vollen Fläche ———
   Aus Sebastians Vorlage „motion-button". Der eleganteste der Sätze: In Ruhe
   steht nur ein Kreis mit Pfeil, beim Überfahren wächst er über die ganze
   Breite und nimmt den Text mit. Die Vorlage löst das mit einem zweiten
   Element; hier reicht ein Pseudo-Element, das von einer festen Breite auf
   100 % geht — dadurch bleibt der Knopf ein einziges anklickbares Ding und
   die Beschriftung an ihrem Platz.
   Wichtig ist die Reihenfolge: Der Kreis liegt UNTER dem Text (z-index −1),
   sonst blinkt die Schrift beim Wachsen kurz weg. */
[data-knopf="motion"] .knopf:not(.knopf--zweit) {
  background: none; border-color: transparent; border-width: 0;
  color: var(--tinte); padding: 6px 26px 6px 58px; min-height: 50px;
}
[data-knopf="motion"] .knopf:not(.knopf--zweit)::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 50px;
  border-radius: 99px; background: var(--akzent-tief); z-index: -1;
  transition: width .55s var(--kurve, cubic-bezier(.16,.84,.3,1));
}
[data-knopf="motion"] .knopf:not(.knopf--zweit)::after {
  content: "→"; position: absolute; left: 19px; top: 50%; translate: 0 -50%;
  color: var(--auf-akzent, #fff); font-size: 19px; line-height: 1;
  transition: translate .55s var(--kurve, cubic-bezier(.16,.84,.3,1));
}
[data-knopf="motion"] .knopf:not(.knopf--zweit):hover { color: var(--auf-akzent, #fff); }
[data-knopf="motion"] .knopf:not(.knopf--zweit):hover::before { width: 100%; }
[data-knopf="motion"] .knopf:not(.knopf--zweit):hover::after { translate: 6px -50%; }

/* ——— 7. fuellung: die Farbe läuft von der Berührungsstelle aus ———
   Aus „ripple-button". Der einzige Effekt im Satz, der weiß, WO angefasst
   wurde — anim.js schreibt die Stelle in zwei Variablen. Auf dem Handy ist das
   die Stelle, an der der Daumen aufsetzt, und genau dort beginnt die Farbe.
   Das ist der Unterschied zu einem Effekt, der nur abläuft: Dieser antwortet. */
[data-knopf="fuellung"] .knopf:not(.knopf--zweit) {
  background: none; border-color: var(--akzent-tief); color: var(--akzent-tief);
}
[data-knopf="fuellung"] .knopf:not(.knopf--zweit)::before {
  content: ""; position: absolute; z-index: -1;
  left: var(--zeiger-x, 50%); top: var(--zeiger-y, 50%);
  width: 0; height: 0; translate: -50% -50%;
  border-radius: 50%; background: var(--akzent-tief);
  transition: width .55s var(--kurve, cubic-bezier(.16,.84,.3,1)),
              height .55s var(--kurve, cubic-bezier(.16,.84,.3,1));
}
[data-knopf="fuellung"] .knopf:not(.knopf--zweit):hover { color: var(--auf-akzent, #fff); }
[data-knopf="fuellung"] .knopf:not(.knopf--zweit):hover::before { width: 260%; height: 620%; }

/* ——— 4. glanz: ein Lichtstreifen zieht einmal durch ———
   Aus „Shiny Button". Der auffälligste der fünf, deshalb an der Mut-Achse ganz
   außen — ein Notdienst bekommt ihn, eine Steuerkanzlei nie. */
[data-knopf="glanz"] .knopf::before {
  content: ""; position: absolute; top: 0; bottom: 0; width: 45%; left: -60%;
  background: linear-gradient(100deg, transparent, color-mix(in oklab, #fff 30%, transparent), transparent);
  transform: skewX(-18deg); pointer-events: none;
}
[data-knopf="glanz"] .knopf:hover::before { animation: knopfGlanz .85s ease-out; }
@keyframes knopfGlanz { from { left: -60%; } to { left: 115%; } }

/* ——— 5. presse: der Knopf lässt sich sichtbar eindrücken ———
   Aus „Button Retro". Handfest statt digital — passt zum Handwerk.
   Der Schatten sitzt UNTER dem Knopf und verschwindet beim Drücken, dadurch
   wirkt die Bewegung wie Tiefe und nicht wie ein Wackeln. */
[data-knopf="presse"] .knopf {
  box-shadow: 0 4px 0 color-mix(in oklab, var(--tinte) 55%, transparent);
  transition: translate .09s ease, box-shadow .09s ease, filter .18s ease;
}
[data-knopf="presse"] .knopf:hover { translate: 0 -1px; box-shadow: 0 5px 0 color-mix(in oklab, var(--tinte) 55%, transparent); }
[data-knopf="presse"] .knopf:active { translate: 0 4px; box-shadow: 0 0 0 color-mix(in oklab, var(--tinte) 55%, transparent); scale: 1; }

/* ——— Glas: nicht über den Regler, sondern über den Untergrund ———
   Ein Knopf auf einem Foto braucht eine andere Behandlung als einer auf einer
   Fläche — unabhängig davon, welchen Charakter der Betrieb hat. */
.s-held-vollbild .knopf--zweit, .s-held-karte .knopf--zweit,
.s-held-notdienst .knopf--zweit, .s-kontakt-formular--karte .knopf--zweit {
  background: color-mix(in oklab, #fff 16%, transparent);
  backdrop-filter: blur(14px) saturate(1.4);
  border-color: color-mix(in oklab, #fff 42%, transparent);
  color: #fff;
}
.s-held-vollbild .knopf--zweit:hover, .s-held-karte .knopf--zweit:hover,
.s-held-notdienst .knopf--zweit:hover, .s-kontakt-formular--karte .knopf--zweit:hover {
  background: color-mix(in oklab, #fff 26%, transparent);
  border-color: color-mix(in oklab, #fff 62%, transparent);
}

/* Der Pfeil rückt beim Überfahren nach — gilt in jeder Stellung. */
.knopf .pfeil, .knopf::marker { transition: translate .25s var(--kurve, cubic-bezier(.16,.84,.3,1)); }
.knopf:hover .pfeil { translate: 4px 0; }

@media (prefers-reduced-motion: reduce) {
  .knopf, .knopf::before, .knopf::after { animation: none !important; transition: background .2s ease; }
  .knopf:hover { translate: 0; }
}

/* ——— Knöpfe auf einer Akzentfläche behalten ihre eigene Gestaltung ———
   Die Varianten „motion" und „fuellung" machen den Knopf absichtlich flächenlos
   und setzen die Schrift auf --tinte. Auf einer farbigen Fläche wie dem CTA-Band
   steht die dann dunkel auf dunkelrot — gemessen 3,5:1. Dort gilt weiter der
   Kontrastknopf in der dunklen Grundfarbe, der genau dafür gedacht ist. */
.s-cta-band .knopf:not(.knopf--zweit),
.s-notdienst-leiste .knopf:not(.knopf--zweit),
.s-lieferung-abholung article .knopf:not(.knopf--zweit) {
  background: var(--dunkel); border-color: var(--dunkel); color: var(--dunkel-text);
  padding-left: 24px;
}
[data-knopf] .s-cta-band .knopf::before, [data-knopf] .s-cta-band .knopf::after,
[data-knopf] .s-notdienst-leiste .knopf::before, [data-knopf] .s-notdienst-leiste .knopf::after,
[data-knopf] .notdienst-leiste .knopf::before, [data-knopf] .notdienst-leiste .knopf::after,
.s-cta-band .knopf::before, .s-cta-band .knopf::after,
.s-notdienst-leiste .knopf::before, .s-notdienst-leiste .knopf::after { content: none; }
/* Und die Polsterung, die der Kreis gebraucht hätte, entfällt mit ihm. */
[data-knopf] :is(.s-cta-band, .s-notdienst-leiste, .notdienst-leiste) .knopf:not(.knopf--zweit) {
  padding: 16px 24px; background: var(--dunkel); border-color: var(--dunkel); color: var(--dunkel-text);
}

/* ═══════════════════════════════════════════════════════════════════════════
   DIE AKTIVE KARTE IST DIE AKTIVE KARTE (21.09.2026)
   Sebastian: „Was soll der Autoplay, wenn sich NIX verändert? Im aktivierten
   Zustand immer noch im Hintergrund?"
   Gemessen: Im Coverflow hatte die aktive Karte dieselbe Deckkraft wie die
   inaktiven — 0,3 gegen 0,3. Die Wucht-Regeln stehen weiter unten in der Datei
   als die Hervorhebung und haben dieselbe Spezifität, also gewannen sie. Der
   Selbstlauf schaltete brav weiter, nur sah man es nicht.
   Diese Regeln stehen bewusst am Dateiende: Was gerade dran ist, muss jede
   Stellung jeder Schraube überstimmen. Sonst gibt es wieder eine Kombination,
   in der die Hervorhebung verschwindet.
   ═══════════════════════════════════════════════════════════════════════════ */
.s-bewertungen-lauf .lauf-karte.ist-dran,
.lauf-karte.ist-dran {
  opacity: 1;
  filter: none;
  z-index: 3;
}
.s-bewertungen-lauf .lauf-karte.ist-dran { transform: none; scale: 1; }
/* Die Nachbarn treten zurück — in jeder Wucht-Stufe unterschiedlich weit, aber
   immer deutlich genug, dass man den Wechsel bemerkt. */
.s-bewertungen-lauf .lauf-karte:not(.ist-dran) { opacity: var(--neben-deckung, .38); }
[data-wucht="dezent"] .s-bewertungen-lauf .lauf-karte:not(.ist-dran) { --neben-deckung: .55; }
[data-wucht="laut"]   .s-bewertungen-lauf .lauf-karte:not(.ist-dran) { --neben-deckung: .26; }


/* ═══════════════════════════════════════════════════════════════════════════
   RADIEN PASSEN ZUEINANDER (21.09.2026)
   Sebastian: „Eckige Bilder in runden Rahmen? Sieht nicht gut aus" und „bitte
   die Radien aneinander angleichen."
   Die Regel ist einfach und gilt überall: Ein Bild in einem gerundeten Behälter
   erbt dessen Rundung — oder der Behälter schneidet es zu. Zwei verschiedene
   Radien übereinander sieht immer nach Versehen aus, nie nach Absicht.
   ═══════════════════════════════════════════════════════════════════════════ */
.s figure, .s .karte, .s article, .s .kachel, .s .person, .lauf-karte { overflow: clip; }
.s figure > img, .s figure > picture > img, .s figure > .lupe > img,
.s article > img, .s article > .lupe > img,
.s .karte > img, .s .kachel > img { border-radius: inherit; }
/* ——— Die Radienformel ———
   innen = außen − Abstand. Bei gemeinsamer Kante ist der Abstand null, dann
   sind beide Radien gleich — auch das ist die Formel, nur eingesetzt.
   Jede Stelle, die einen Innenabstand erzeugt (Passepartout, Polsterung,
   Rahmenstärke), setzt dafür `--innen-abstand`. */
.s :is(figure, article, .karte, .kachel, .person, .lauf-karte, .tafel) >
:is(img, picture, .lupe, .lauf-bild, .stimme-innen, video),
.s :is(figure, article, .karte, .kachel) > .lupe > img,
.s :is(figure, article, .karte, .kachel) > picture > img {
  border-radius: max(0px, calc(var(--radius, 0px) - var(--innen-abstand, 0px)));
}

[data-passepartout="schmal"] .s figure { --innen-abstand: 8px; }
[data-passepartout="breit"]  .s figure { --innen-abstand: 18px; }

/* ═══════════════════════════════════════════════════════════════════════════
   FLÄCHE = LINIE: EINE ENTSCHEIDUNG, DREI FOLGEN (21.09.2026)
   Diese Schraube nimmt den Karten ihren Hintergrund. Das hat drei Folgen, die
   alle mitgezogen werden müssen — sonst bleibt jedes Mal ein Rest stehen, der
   vorher von der Fläche verdeckt wurde:
     1. Kein Schlagschatten, denn es gibt nichts mehr, das ihn wirft.
     2. Die Schrift wechselt auf die normale Textfarbe — eine helle Schrift, die
        für einen farbigen Grund gedacht war, wird sonst unsichtbar.
     3. Die Polsterung bleibt, sonst klebt der Text an der Linie.
   Jede dieser drei Folgen war einzeln schon einmal aufgefallen. Sie stehen
   deshalb hier zusammen und am Dateiende, damit keine spätere Regel sie
   auseinanderreißt.
   ═══════════════════════════════════════════════════════════════════════════ */
[data-flaeche="linie"] :is(.s article, .s .karte:not(.glas), .s .kasten, .s .kachel,
  .s .person, .stimme-innen:not(.glas), .s-leistungen-kacheln .kacheln > article) {
  box-shadow: none;
  background: none;
  color: var(--tinte);
}
/* Laufkarten tragen ihren Text auf einem Foto — sie behalten ihre helle
   Schrift und ihren Überzug, egal was die Flächen-Schraube sagt. */
[data-flaeche="linie"] .lauf-karte { box-shadow: none; }
[data-flaeche="linie"] .lauf-karte .lauf-text,
[data-flaeche="linie"] .lauf-karte .lauf-text * { color: #fff; }
[data-flaeche="linie"] [data-textgrund="block"] .lauf-karte .lauf-text,
[data-textgrund="block"] .lauf-karte .lauf-text * { color: var(--auf-akzent, #fff); }
[data-flaeche="linie"] .s-leistungen-kacheln .kacheln > article {
  border: 1px solid var(--linie);
  padding: clamp(16px, 1.8vw, 24px);
  border-radius: var(--ecke-klein, var(--radius));
}
[data-flaeche="linie"] :is(.s article, .s .karte:not(.glas), .s .kachel, .s .person) p {
  color: var(--leise);
}
/* Die Lieferkarten trugen eine helle Schrift für ihren farbigen Grund — ohne
   den Grund stand sie auf dem Seitengrund und war weg. */
[data-flaeche="linie"] .s-lieferung-abholung article,
[data-flaeche="linie"] .s-lieferung-abholung article * {
  color: var(--tinte);
}
[data-flaeche="linie"] .s-lieferung-abholung article p { color: var(--leise); }

/* Telefonnummern und Links in dunklen Sektionen nehmen die aufgehellte
   Akzentfarbe — die reine Markenfarbe liegt dort bei 2,5:1 und ist damit für
   die wichtigste Angabe der Seite zu schwach. */
.s-kontakt-karte a, .s-leitsatz a, .s-leiste-fakten a,
.s[data-ton="dunkel"] a:not(.knopf) {
  color: var(--akzent-hell);
}
.s-kontakt-karte .knopf:not(.knopf--zweit) {
  background: var(--akzent-hell); border-color: var(--akzent-hell);
  color: var(--auf-akzent-hell, #111);
}

/* ═══════════════════════════════════════════════════════════════════════════
   NACHARBEIT 21.09.2026, Runde 3 (Sebastian)
   ═══════════════════════════════════════════════════════════════════════════ */

/* 12. „Ich dachte, es gibt keine Schraube mehr, die den Hintergrund beim Radar
   wieder herstellen kann?????" — Berechtigt. Ich hatte das Rechteck aus dem SVG
   genommen, aber die Passepartout-Schraube setzt `background: var(--grund2)`
   auf JEDE Figur, und das Einsatzgebiet steckt in einer. Das Diagramm ist keine
   Abbildung: Es bekommt weder Fläche noch Rahmen noch Polsterung, von keiner
   Schraube. */
.gebiet-bild,
[data-passepartout] .s figure.gebiet-bild, [data-flaeche] .s figure.gebiet-bild,
[data-schatten] .s figure.gebiet-bild, [data-ecke] .s figure.gebiet-bild,
[data-bildfilter] .s figure.gebiet-bild, [data-ueberzug] .s figure.gebiet-bild {
  background: none; padding: 0; border: 0; box-shadow: none; border-radius: 0;
  filter: none;
}
.gebiet-bild::after, .s figure.gebiet-bild::after { content: none; }   /* auch kein Tint-Überzug */

/* 6. „Sind die Zahlen I, II, III hier angeschnitten?" — Ja, und zwar durch
   meine eigene Radien-Lösung: `overflow: clip` auf jeder Karte schneidet alles
   ab, was über ihren Rand ragt. Die Ordnungszahlen sitzen bewusst halb außen.
   Geklippt wird deshalb nur noch dort, wo ein Bild die Kante berührt — und das
   sagt die Karte selbst über eine Klasse, statt dass es alle trifft. */
.s article, .s .karte, .s .kachel, .s .person { overflow: visible; }
.s figure, .lauf-karte, .s-referenzen-karten article, .s-sortiment article,
.s-galerie-mosaik figure, .s-leistungen-wechsel article { overflow: clip; }

/* 4. „Der Mouseover über die Orte lässt diese verschwinden????" — Die
   allgemeine Hover-Regel für Listenpunkte hat auch die Ortsangaben erfasst und
   ihnen eine Bewegung gegeben; zusammen mit dem Einblend-Zustand wurden sie
   unsichtbar. Das Einsatzgebiet ist eine Aufzählung, kein Bedienelement. */
.s-einsatzgebiet--karte .gebiet-text li,
.s-einsatzgebiet--karte .gebiet-text li:hover {
  opacity: 1; translate: none; scale: none; transform: none; filter: none;
  background: none; box-shadow: none;
}

/* 3./10. Knöpfe nebeneinander tragen dieselbe Form, und der Zweitknopf braucht
   auf hellem Glas eine dunkle Schrift — „Route planen" stand dort weiß auf
   weiß. Die Form kommt aus derselben Variable wie beim Hauptknopf, damit nicht
   ein runder neben einem eckigen steht. */
.knoepfe .knopf, .knoepfe .knopf--zweit { border-radius: var(--radius); }
[data-ecke="kapsel"] .knoepfe .knopf { border-radius: 99px; }
.karte.glas .knopf--zweit, .karte-kasten .knopf--zweit, .s-held-karte .knopf--zweit {
  color: var(--tinte); border-color: color-mix(in oklab, var(--tinte) 38%, transparent);
  background: color-mix(in oklab, var(--grund) 45%, transparent);
}
.karte.glas .knopf--zweit:hover, .karte-kasten .knopf--zweit:hover {
  background: color-mix(in oklab, var(--grund) 75%, transparent);
  border-color: var(--tinte);
}

/* 9. Der Schatten im Coverflow wurde abgeschnitten: Die Bahn scrollt waagerecht
   und klippt damit senkrecht mit. Polsterung schafft den Platz, den der
   Schatten braucht. */
.s-bewertungen-lauf .bahn-flow { padding-block: clamp(34px, 4vw, 58px); overflow-y: visible; }
.s-bewertungen-lauf { overflow-x: clip; overflow-y: visible; }

/* 5. Bild-Hovers ohne Übergang: `filter` und `scale` standen in getrennten
   Regeln, von denen eine keine Übergangszeit mitbrachte. */
.s figure img, .s .lupe img, .lauf-bild img {
  transition: scale .55s var(--kurve, cubic-bezier(.16,.84,.3,1)),
              filter .45s ease, opacity .45s ease, translate .55s var(--kurve, cubic-bezier(.16,.84,.3,1));
}

/* ═══════════════════════════════════════════════════════════════════════════
   NUR EINE EBENE SKALIERT (21.09.2026)
   Sebastian: „Hier ist der Radius im Hover falsch und der Abstand links und
   unten unterschiedlich."
   Gemessen: Beim Überfahren bekam die Karte `scale: 1.015` UND das Bild darin
   `scale: 1.05`. Zwei Vergrößerungen übereinander — das Bild ragte um 7,6 px
   nach links und 5,4 px nach oben aus seiner Karte. Weil die Karte klippt, sah
   man davon nur die Folge: Die Ecken des Bildes verschwanden hinter dem Radius
   der Karte, und die Abstände stimmten nicht mehr ringsum.
   Die Regel ist dieselbe wie bei den Animationen: eine Eigenschaft, eine Hand.
   Der Behälter HEBT sich (translate), das Bild ZOOMT (scale). Nie beide.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (hover: hover) {
  .s .kacheln > article:hover, .s .drei > article:hover, .s .person:hover,
  .s-sortiment article:hover, .s-referenzen-karten article:hover,
  .s-leistungen-wechsel article:hover, .s-ablauf-schritte li:hover,
  [data-zeigen="zoom"] .s .kacheln > article:hover {
    scale: none;
  }
  /* Der Zoom bleibt dem Bild vorbehalten — dort trägt er, weil das Bild mehr
     zeigt, statt nur größer zu werden. */
  .s-sortiment article:hover img, .s-referenzen-karten article:hover img,
  .s-leistungen-wechsel article:hover img, .s .kacheln > article:hover img {
    scale: 1.06;
  }
}

/* ——— Die Radienformel gilt auch im Formular ———
   Gemessen: Der Kasten hat 12 px Radius bei 38 px Polsterung, die Eingabefelder
   darin ebenfalls 12 px. Nach der Formel (innen = außen − Abstand) müssten sie
   eckig sein — bei einem Abstand, der größer ist als der Radius, bleibt nichts
   übrig. Man sieht es an den Ecken: Die Felder wirken runder als ihr Kasten,
   obwohl sie weiter innen liegen. */
.formular { --innen-abstand: clamp(24px, 3vw, 38px); }
.formular :is(input, textarea, select, .feld > input, .feld > textarea) {
  border-radius: max(0px, calc(var(--radius, 0px) - var(--innen-abstand, 0px)));
}
/* Der Absendeknopf ist eine eigene Form und folgt der Kontur nicht — er behält
   seine Knopfrundung, damit er als Knopf lesbar bleibt. */
.formular button { border-radius: var(--radius); }
[data-ecke="kapsel"] .formular button { border-radius: 99px; }

/* ——— Der wachsende Knopf im CTA-Band ———
   Dort trägt die Sektion selbst die Akzentfarbe, der Knopf steht in der dunklen
   Grundfarbe. Die Motion-Variante wollte ihn flächenlos machen und ihren Kreis
   darunterlegen — beides zusammen ergab einen runden Fleck neben eckigem Text.
   Im CTA-Band und in der Notdienst-Leiste gilt deshalb der schlichte Knopf. */
.s-cta-band .knopf, .s-notdienst-leiste .knopf, .notdienst-leiste .knopf {
  padding: 16px 24px; min-height: 48px; border-radius: var(--radius);
}
[data-ecke="kapsel"] :is(.s-cta-band, .s-notdienst-leiste) .knopf { border-radius: 99px; }


/* ═══════════════════════════════════════════════════════════════════════════
   TEXT AUF EINEM BILD HAT IMMER EINEN GRUND (21.09.2026)
   Vier Schrauben konnten den Überzug der Laufkarten abschalten: Passepartout
   ganz, `textgrund=keiner` über die Deckkraft, und Balken/Glas/Block ersetzen
   ihn durch etwas Eigenes. Die ersten beiden ließen den Text ungeschützt auf
   dem Foto zurück — und ob das lesbar ist, entscheidet dann das Bild.
   Ein heller Himmel im Hintergrund macht weiße Schrift unsichtbar, egal wie
   gut alles andere eingestellt ist. Deshalb: Der Überzug darf durch einen
   anderen Grund ERSETZT, aber nie ersatzlos entfernt werden.
   ═══════════════════════════════════════════════════════════════════════════ */
[data-textgrund="keiner"] .lauf-karte:has(.lauf-bild)::after { opacity: .72; }
.lauf-karte:has(.lauf-bild) .lauf-text { text-shadow: 0 1px 12px rgba(0,0,0,.55); }
/* Ein Balken oder Block DECKT — dort braucht es den Schatten nicht mehr.
   Glas dagegen ist durchscheinend: Es dämpft das Bild, ersetzt es aber nicht.
   Deshalb behält es den Schatten und bekommt mehr Deckung, sobald heller Text
   darauf steht. */
[data-textgrund="balken"] .lauf-karte .lauf-text,
[data-textgrund="block"]  .lauf-karte .lauf-text { text-shadow: none; }
[data-textgrund="glas"] .lauf-karte:has(.lauf-bild) .lauf-text {
  background: color-mix(in oklab, #000 62%, transparent);
  backdrop-filter: blur(20px) saturate(1.2) brightness(.7);
  color: #fff;
}
[data-textgrund="glas"] .lauf-karte:has(.lauf-bild)::after { background: linear-gradient(0deg, rgba(0,0,0,.5) 0%, rgba(0,0,0,.18) 45%, transparent 72%); }

/* Der Block deckt mit einer HELLEN Fläche — dort muss die Schrift dunkel
   werden. In `freundlich` stand weiße Schrift auf weißem Block: gemessen
   0 % dunkler Grund im Textbereich, also unsichtbar. Die Regel gilt für alle
   Stilwelten, weil der Block überall die Grundfarbe nimmt. */
[data-textgrund="block"] .lauf-karte .lauf-text {
  background: var(--akzent-tief);
}
[data-textgrund="block"] .lauf-karte .lauf-text,
[data-textgrund="block"] .lauf-karte .lauf-text * { color: var(--auf-akzent, #fff); }

/* ═══════════════════════════════════════════════════════════════════════════
   LICHTSCHEIN UNTER DEM MAUSZEIGER (21.09.2026)
   Sebastian: „Kein Hintergrund, kein Mouse-Tracking-Gradient, kein Effekt,
   keine Animation, kein Wow."
   Ein Schein, der der Hand folgt, macht aus einer Fläche einen Raum — das Auge
   liest Helligkeit als Nähe. Ohne Zeiger (Handy, Tastatur) steht er in der
   Mitte und wirkt als ruhige Aufhellung; niemand vermisst etwas.
   ═══════════════════════════════════════════════════════════════════════════ */
[data-schein] {
  position: relative;
  --schein-x: 50%;
  --schein-y: 0%;
}
[data-schein]::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(42rem 42rem at var(--schein-x) var(--schein-y),
    color-mix(in oklab, var(--akzent) 22%, transparent), transparent 62%);
  opacity: 0; transition: opacity .6s ease;
  border-radius: inherit;
}
[data-schein]:hover::before, .ohne-bewegung [data-schein]::before { opacity: 1; }
[data-schein] > * { position: relative; z-index: 1; }

/* ——— Akkordeon: Fläche, Tiefe, Bewegung ——— */
.s-leistungen-akkordeon .raster {
  padding: clamp(24px, 3vw, 44px);
  border-radius: var(--radius);
  background: color-mix(in oklab, var(--grund2) 70%, var(--grund));
  border: 1px solid var(--linie);
  overflow: clip;
}
.s-leistungen-akkordeon details {
  border-bottom: 1px solid var(--linie);
  transition: background .35s ease;
}
.s-leistungen-akkordeon details:last-child { border-bottom: 0; }
.s-leistungen-akkordeon details[open] {
  background: color-mix(in oklab, var(--akzent) 7%, transparent);
  border-radius: max(0px, calc(var(--radius) - clamp(24px, 3vw, 44px)));
}
.mit-bewegung .s-leistungen-akkordeon details {
  opacity: 0; translate: 0 14px;
  transition: opacity .6s ease calc(var(--n, 0) * 90ms), translate .7s cubic-bezier(.16,.84,.3,1) calc(var(--n, 0) * 90ms), background .35s ease;
}
.mit-bewegung .s-leistungen-akkordeon details.ist-sichtbar { opacity: 1; translate: none; }
/* Die Ziffer zeigt, wie viele es sind — und wo man gerade ist. */
.s-leistungen-akkordeon .liste { counter-reset: ak; }
.s-leistungen-akkordeon summary { counter-increment: ak; padding-left: 46px; }
.s-leistungen-akkordeon summary::before {
  content: counter(ak, decimal-leading-zero);
  position: absolute; left: 0; top: 50%; translate: 0 -50%;
  font: 700 14px/1 var(--f-text); color: var(--akzent-tief);
  letter-spacing: .06em; transition: color .3s ease, scale .3s ease;
}
.s-leistungen-akkordeon details[open] summary::before { scale: 1.25; }

/* ——— Leitsatz: der Satz IST die Sektion ——— */
.s-leitsatz { position: relative; overflow: clip; text-align: center; }
.s-leitsatz .ls-marke {
  position: absolute; left: 50%; top: -.08em; translate: -50% 0; z-index: 0;
  font: 900 clamp(280px, 40vw, 620px)/1 var(--f-kopf);
  color: color-mix(in oklab, var(--dunkel-text) 7%, transparent);
  pointer-events: none; user-select: none;
}
.s-leitsatz blockquote { position: relative; z-index: 1; margin: 0; max-width: 22ch; margin-inline: auto; }
.s-leitsatz blockquote p {
  font: var(--kopf-gewicht) clamp(30px, 4.6vw, 62px)/1.18 var(--f-kopf);
  font-stretch: var(--kopf-breite); text-transform: var(--kopf-trans);
  letter-spacing: var(--kopf-sperr); margin: 0;
}
.s-leitsatz footer { margin-top: clamp(18px, 2vw, 28px); color: color-mix(in oklab, var(--dunkel-text) 66%, transparent); font-size: 16px; }
.mit-bewegung .s-leitsatz .wort { transition-delay: calc(var(--w, 0) * 70ms) !important; }
@supports (animation-timeline: view()) {
  .mit-bewegung .s-leitsatz .ls-marke {
    animation: leitMarke linear both; animation-timeline: view(); animation-range: cover 0% cover 100%;
  }
  @keyframes leitMarke { from { transform: translate(-50%, 4%) scale(.92); } to { transform: translate(-50%, -6%) scale(1.04); } }
}

/* ═══════════════════════════════════════════════════════════════════════════
   ABLAUF-SCHRITTE (21.09.2026)
   Steht auf der Hälfte aller Kundenseiten und hatte bisher keinen einzigen
   Effekt. Ein Ablauf ist eine FOLGE — genau das muss man sehen: Die Schritte
   kommen nacheinander, nicht gleichzeitig, und eine Linie verbindet sie.
   Die Linie wächst am Scrollbalken mit; so liest man die Reihenfolge, noch
   bevor man die Überschriften gelesen hat.
   ═══════════════════════════════════════════════════════════════════════════ */
.s-ablauf-schritte ol { position: relative; }
.s-ablauf-schritte ol::before {
  content: ""; position: absolute; left: 0; right: 0; top: 50px; height: 2px; z-index: 0;
  background: linear-gradient(90deg, var(--akzent-tief), color-mix(in oklab, var(--akzent) 25%, transparent));
  transform-origin: left center; scale: 0 1;
  transition: scale 1.2s cubic-bezier(.16,.84,.3,1) .2s;
}
.s-ablauf-schritte ol.ist-sichtbar::before, .ohne-bewegung .s-ablauf-schritte ol::before { scale: 1 1; }
.s-ablauf-schritte li { position: relative; z-index: 1; transition: translate .35s ease, border-color .35s ease; }
.mit-bewegung .s-ablauf-schritte li {
  opacity: 0; translate: 0 26px;
  transition: opacity .6s ease calc(var(--n, 0) * 150ms), translate .7s cubic-bezier(.16,.84,.3,1) calc(var(--n, 0) * 150ms),
              border-color .35s ease;
}
.mit-bewegung .s-ablauf-schritte li.ist-sichtbar { opacity: 1; translate: none; }
.s-ablauf-schritte li::before {
  background: var(--akzent-tief); color: var(--auf-akzent, #fff);
  transition: scale .35s cubic-bezier(.2,1.4,.4,1), box-shadow .35s ease;
  box-shadow: 0 0 0 6px var(--grund);
}
@media (hover: hover) {
  .s-ablauf-schritte li:hover { translate: 0 -6px; border-color: color-mix(in oklab, var(--akzent) 45%, var(--linie)); }
  .s-ablauf-schritte li:hover::before { scale: 1.12; box-shadow: 0 0 0 6px var(--grund), 0 8px 20px color-mix(in oklab, var(--akzent) 35%, transparent); }
}
@media (max-width: 720px) { .s-ablauf-schritte ol::before { display: none; } }

/* ═══════════════════════════════════════════════════════════════════════════
   SEITENFUSS (21.09.2026)
   Vorher eine Zeile mit zwei Links. Ein Fuß beantwortet die letzten Fragen,
   ohne dass jemand zurückscrollt, und er verlinkt intern — für viele kleine
   Betriebe ist er die einzige Stelle, an der „Dachdecker Luckenwalde"
   überhaupt als Wortpaar auf der Seite steht.
   ═══════════════════════════════════════════════════════════════════════════ */
.fuss {
  background: var(--dunkel); color: var(--dunkel-text);
  --tinte: var(--dunkel-text);
  --leise: color-mix(in oklab, var(--dunkel-text) 68%, transparent);
  --linie: color-mix(in oklab, var(--dunkel-text) 16%, transparent);
  --akzent-tief: var(--akzent-hell); --auf-akzent: var(--auf-akzent-hell, #111);
  /* Die Luft über der Fußzeile gehört IN die Fußzeile, nicht davor: Ein
     Außenabstand zeigt den Körpergrund, und wenn der letzte Abschnitt dunkel
     ist, steht zwischen zwei dunklen Flächen ein heller Streifen (Sebastian,
     23.09.2026: „was ist mit dem hellen Streifen?"). */
  padding-block: clamp(84px, 9vw, 170px) clamp(24px, 3vw, 36px);
  margin-top: 0;
}
.fuss-raster {
  display: grid; gap: clamp(28px, 4vw, 56px);
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.fuss-spalte--breit { grid-column: span 1; }
.fuss h2 { font: 700 14px/1.3 var(--f-text); text-transform: uppercase; letter-spacing: .12em; margin: 0 0 14px; color: var(--akzent-hell); }
.fuss-name { font: var(--kopf-gewicht) clamp(20px, 2vw, 26px)/1.2 var(--f-kopf); margin: 0 0 10px; }
.fuss-adresse { margin: 0 0 14px; color: var(--leise); line-height: 1.6; }
.fuss-kontakt { margin: 0 0 12px; line-height: 1.7; }
.fuss-kontakt a { color: var(--dunkel-text); text-decoration: none; font-weight: 700; font-size: 19px; }
.fuss-kontakt a:hover { color: var(--akzent-hell); }
.fuss-sterne { margin: 0; font-size: 14px; }
.fuss-sterne a { color: var(--leise); text-decoration: none; }
.fuss-sterne a:hover { color: var(--akzent-hell); }
.fuss-zeiten { border-collapse: collapse; font-size: 15px; width: 100%; max-width: 230px; }
.fuss-zeiten th { text-align: left; font-weight: 400; color: var(--leise); padding: 3px 14px 3px 0; white-space: nowrap; }
.fuss-zeiten td { padding: 3px 0; }
.fuss-zeiten tr.zu td { color: var(--leise); }
.fuss-liste { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; font-size: 15px; color: var(--leise); }
.fuss-orte li { font-size: 14px; }
.fuss-unten {
  display: flex; flex-wrap: wrap; gap: 10px 22px; justify-content: space-between;
  margin-top: clamp(30px, 4vw, 52px); padding-top: 20px;
  border-top: 1px solid var(--linie); font-size: 14px; color: var(--leise);
}
.fuss-unten a { color: var(--leise); }
.fuss-unten a:hover { color: var(--dunkel-text); }
@media (max-width: 640px) {
  .fuss-raster { grid-template-columns: 1fr 1fr; }
  .fuss-spalte--breit { grid-column: 1 / -1; }
  .fuss-unten { flex-direction: column; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   ANSPRECHPARTNER (21.09.2026)
   Sebastian: „Das sieht sehr langweilig aus — hier sollte der Team-Charakter
   eine Rolle spielen."
   Fotos haben die wenigsten Betriebe, also trägt die Initiale. Zwei Buchstaben
   statt einem lesen sich als Person, und jede Karte bekommt einen eigenen
   Farbton aus derselben Markenfarbe — dadurch wird aus einer Reihe gleicher
   Kästen eine Mannschaft. Die Töne sind abgeleitet, nicht ausgewählt: Sie
   passen in jeder Stilwelt, ohne dass jemand sie pflegen muss.
   ═══════════════════════════════════════════════════════════════════════════ */
.s-ansprechpartner .personen > article {
  position: relative; overflow: clip;
  border: 1px solid var(--linie); border-radius: var(--radius);
  background: var(--grund2); padding: clamp(22px, 2.4vw, 30px);
  transition: translate .35s cubic-bezier(.16,.84,.3,1), border-color .35s ease, box-shadow .35s ease;
}
/* Jede Person eine Nuance: 0°, +18°, −16°, +34° um den Markenton herum. */
.s-ansprechpartner article { --ton: var(--akzent); }
.s-ansprechpartner article:nth-child(4n+2) { --ton: color-mix(in oklab, var(--akzent) 76%, var(--dunkel)); }
.s-ansprechpartner article:nth-child(4n+3) { --ton: color-mix(in oklab, var(--akzent) 72%, #fff); }
.s-ansprechpartner article:nth-child(4n+4) { --ton: color-mix(in oklab, var(--akzent) 60%, var(--tinte)); }
.s-ansprechpartner .initiale {
  width: 62px; height: 62px; border-radius: 50%;
  background: var(--ton); color: #fff;
  display: grid; place-items: center;
  font: 800 22px/1 var(--f-kopf); letter-spacing: .02em;
  margin-bottom: 18px;
  transition: scale .4s cubic-bezier(.2,1.4,.4,1);
}
/* Ein weicher Farbschimmer in der Ecke — nimmt der Karte das Formularhafte. */
.s-ansprechpartner article::before {
  content: ""; position: absolute; right: -40px; top: -40px; width: 140px; height: 140px;
  border-radius: 50%; background: var(--ton); opacity: .1;
  transition: scale .5s cubic-bezier(.16,.84,.3,1), opacity .4s ease;
}
.s-ansprechpartner h3 { margin: 0 0 4px; font-size: clamp(18px, 1.8vw, 22px); }
.s-ansprechpartner .rolle { margin: 0 0 14px; color: var(--leise); font-size: 15px; }
.s-ansprechpartner .person-tel { font-weight: 800; font-size: 19px; text-decoration: none; color: var(--akzent-tief); }
.mit-bewegung .s-ansprechpartner article {
  opacity: 0; translate: 0 22px;
  transition: opacity .6s ease calc(var(--n, 0) * 110ms), translate .7s cubic-bezier(.16,.84,.3,1) calc(var(--n, 0) * 110ms),
              border-color .35s ease, box-shadow .35s ease;
}
.mit-bewegung .s-ansprechpartner article.ist-sichtbar { opacity: 1; translate: none; }
@media (hover: hover) {
  .s-ansprechpartner article:hover { translate: 0 -7px; border-color: color-mix(in oklab, var(--ton) 50%, var(--linie)); box-shadow: 0 20px 46px color-mix(in oklab, var(--ton) 18%, transparent); }
  .s-ansprechpartner article:hover .initiale { scale: 1.08; }
  .s-ansprechpartner article:hover::before { scale: 1.35; opacity: .16; }
  .s-ansprechpartner .person-tel:hover { text-decoration: underline; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   LEISTUNGEN ALS KACHELN (21.09.2026)
   Sebastian: „Die müssen entweder als Masonry gezeigt werden oder horizontal
   addieren. Auch diese Sektion ist extrem unspektakulär — wir sollten auch
   Icon-Sätze aussuchen."
   Masonry über `columns`: Die Kacheln behalten ihre natürliche Höhe, statt alle
   auf die Höhe der längsten gezogen zu werden. Das nimmt dem Raster das Starre,
   ohne Lücken zu erzeugen — und es funktioniert ohne eine Zeile JavaScript.
   ═══════════════════════════════════════════════════════════════════════════ */
.s-leistungen-kacheln .kacheln {
  display: block;
  columns: 3; column-gap: clamp(14px, 1.6vw, 22px);
}
.s-leistungen-kacheln .kacheln > * {
  break-inside: avoid;
  margin-bottom: clamp(14px, 1.6vw, 22px);
  display: block;
}
/* Bei wenigen Kacheln wirken drei Spalten zerfasert. */
.s-leistungen-kacheln .kacheln[data-anzahl="1"],
.s-leistungen-kacheln .kacheln[data-anzahl="2"] { columns: 2; }
.s-leistungen-kacheln .kacheln[data-anzahl="4"] { columns: 2; }
@media (max-width: 900px) { .s-leistungen-kacheln .kacheln { columns: 2; } }
@media (max-width: 560px) { .s-leistungen-kacheln .kacheln { columns: 1; } }

/* ——— Das Symbol ———
   Strichstärke aus einer Variablen: dünn wirkt teuer, kräftig handfest — das
   ist dieselbe Entscheidung wie bei der Schrift und gehört deshalb zur Stilwelt. */
/* `inline-block` statt `block`: Sebastian, 22.09.2026 — „im Layout schwierig
   mit den Häkchen oben links." Die Kachel zentrierte ihren Text, das Symbol
   stand aber links. Zwei Achsen in einer Kachel sehen immer nach Versehen aus.
   Als inline-block folgt das Symbol der Ausrichtung des Textes. */
.s-icon { width: 30px; height: 30px; display: inline-block; margin-bottom: 14px; color: var(--akzent-tief); transition: scale .35s cubic-bezier(.2,1.4,.4,1), color .3s ease; }
[data-stil="atelier"] .s-icon, [data-stil="klassisch"] .s-icon { --icon-strich: 1.3; }
[data-stil="werkstatt"] .s-icon, [data-stil="meister"] .s-icon { --icon-strich: 2.1; }
.s-leistungen-kacheln article:hover .s-icon, .s-leistungen-kacheln .kachel-link:hover .s-icon { scale: 1.12; }

.mit-bewegung .s-leistungen-kacheln .kacheln > * {
  opacity: 0; translate: 0 20px;
  transition: opacity .55s ease calc(var(--n, 0) * 80ms), translate .65s cubic-bezier(.16,.84,.3,1) calc(var(--n, 0) * 80ms),
              translate .35s ease, border-color .35s ease;
}
.mit-bewegung .s-leistungen-kacheln .kacheln > .ist-sichtbar { opacity: 1; translate: none; }

/* Lange Wörter in der Fakten-Leiste: „Luckenwalde" ragte 54 px über seine
   Spalte hinaus. Der erste Versuch war Silbentrennung — die Zahl sollte groß
   bleiben. Das Ergebnis war „Schwie-lowsee" in 40 px Anzeigeschrift, und das
   liest sich als Fehler (Sebastian, 23.09.2026: „irgendwelcher Text halb
   abgeschnitten"). Jetzt eine Stufe kleiner statt getrennt: Ein Ortsname ist
   ohnehin keine Zahl, er muss nicht 40 px groß sein — er muss lesbar sein.
   Gesetzt wird `data-lang` beim Bauen (tools/sektionen.mjs, ab 10 Zeichen). */
.s-leiste-fakten b, .s-leiste-fakten .zaehler {
  hyphens: manual; overflow-wrap: anywhere; text-wrap: balance;
  max-width: 100%;
}
.s-leiste-fakten b[data-lang] { font-size: clamp(20px, 2.1vw, 28px); }

/* ═══════════════════════════════════════════════════════════════════════════
   ÜBER UNS und ZEITLEISTE (21.09.2026)
   Sebastian: „Völlig unspektakulär — bitte dezent aufwerten."
   Dezent heißt hier: Das Bild bekommt Tiefe statt Effekte, der Text kommt von
   der Seite statt von unten. Beides zusammen ergibt eine Bewegung, die man
   spürt, ohne sie zu bemerken — und beides hält, wenn jemand nicht scrollt.
   ═══════════════════════════════════════════════════════════════════════════ */
.s-ueber-geteilt .raster { align-items: center; }
.s-ueber-geteilt .ug-bild { margin: 0; overflow: clip; border-radius: var(--radius); position: relative; }
.s-ueber-geteilt .ug-bild img { display: block; width: 100%; aspect-ratio: 4/5; object-fit: cover; border-radius: inherit; }
.s-ueber-geteilt .ug-text { position: relative; padding-left: clamp(0px, 1.6vw, 26px); }
/* Ein schmaler Strich am Textanfang — er fasst den Absatz, ohne ihn einzurahmen. */
.s-ueber-geteilt .ug-text::before {
  content: ""; position: absolute; left: 0; top: .35em; bottom: .35em; width: 2px;
  background: linear-gradient(var(--akzent-tief), transparent);
  scale: 1 0; transform-origin: top; transition: scale .9s cubic-bezier(.16,.84,.3,1) .2s;
}
.s-ueber-geteilt .ug-text.ist-sichtbar::before, .ohne-bewegung .s-ueber-geteilt .ug-text::before { scale: 1 1; }
.mit-bewegung .s-ueber-geteilt .ug-text { opacity: 0; translate: 22px 0; transition: opacity .8s ease, translate .9s cubic-bezier(.16,.84,.3,1); }
.mit-bewegung .s-ueber-geteilt .ug-text.ist-sichtbar { opacity: 1; translate: none; }
.s-ueber-geteilt .ug-signatur { margin-top: 22px; font-style: italic; color: var(--leise); }
@supports (animation-timeline: view()) {
  .mit-bewegung .s-ueber-geteilt .ug-bild img {
    animation: ugBild linear both; animation-timeline: view(); animation-range: cover 0% cover 100%;
  }
  @keyframes ugBild { from { transform: scale(1.14) translateY(-3%); } to { transform: scale(1.14) translateY(3%); } }
}
@media (max-width: 820px) { .s-ueber-geteilt .ug-bild img { aspect-ratio: 4/3; } }

/* ——— Zeitleiste: die Linie wächst, die Jahre zählen hoch ——— */
.s-zeitleiste ol { position: relative; border-top: 0; }
.s-zeitleiste ol::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 2px;
  background: linear-gradient(90deg, var(--akzent-tief), color-mix(in oklab, var(--akzent) 20%, transparent));
  scale: 0 1; transform-origin: left; transition: scale 1.3s cubic-bezier(.16,.84,.3,1) .15s;
}
.s-zeitleiste ol.ist-sichtbar::before, .ohne-bewegung .s-zeitleiste ol::before { scale: 1 1; }
.s-zeitleiste li::before { transition: scale .4s cubic-bezier(.2,1.5,.4,1) calc(var(--n, 0) * 140ms + .3s); scale: 0; }
.s-zeitleiste ol.ist-sichtbar li::before, .ohne-bewegung .s-zeitleiste li::before { scale: 1; }
.s-zeitleiste b { display: block; font: var(--kopf-gewicht) clamp(26px, 3vw, 40px)/1 var(--f-kopf); color: var(--akzent-tief); margin-bottom: 8px; }
.mit-bewegung .s-zeitleiste li {
  opacity: 0; translate: 0 16px;
  transition: opacity .6s ease calc(var(--n, 0) * 140ms + .2s), translate .7s cubic-bezier(.16,.84,.3,1) calc(var(--n, 0) * 140ms + .2s);
}
.mit-bewegung .s-zeitleiste li.ist-sichtbar { opacity: 1; translate: none; }

/* Der SEO-Block im Einsatzgebiet: Leistung fett, Ort normal. Die Zeilen sind
   länger als bloße Ortsnamen, deshalb einspaltig ab mittlerer Breite — zwei
   Spalten mit Umbruch mitten im Wortpaar wären schlechter als eine. */
.s-einsatzgebiet--karte .gebiet-text li { min-width: 100%; line-height: 1.5; }
.s-einsatzgebiet--karte .gebiet-text li b { font-weight: 700; }
@media (min-width: 1100px) { .s-einsatzgebiet--karte .gebiet-text li { min-width: 46%; } }

/* ═══════════════════════════════════════════════════════════════════════════
   NEWS-BAND (21.09.2026)
   Sebastian: „Ein Element, das oben am Rand der Webseite immer scrollt und in
   auffälligen, aber passenden Farben als Störer fungiert."
   Zwei Dinge unterscheiden es von einer Laufschrift aus dem Jahr 2003:
     1. Es hält an, sobald man darauf zeigt — sonst kann man es nicht lesen.
     2. Der Inhalt steht zweimal im Markup. Nur so läuft es nahtlos: Die erste
        Hälfte schiebt sich hinaus, während die zweite nachrückt. Sichtbar
        bleibt immer genau eine.
   Bei „Bewegung reduzieren" steht es still und zeigt den ersten Hinweis —
   ein Band, das man nicht lesen kann, ist schlimmer als keins.
   ═══════════════════════════════════════════════════════════════════════════ */
.news-band {
  background: var(--akzent-tief); color: var(--auf-akzent, #fff);
  overflow: clip; position: relative; z-index: 5;
  font: 700 14px/1 var(--f-text); letter-spacing: .03em;
  padding-block: 11px;
}
.nb-lauf { display: flex; width: max-content; }
.nb-satz { display: flex; flex-shrink: 0; }
.nb-punkt { padding-inline: 26px; white-space: nowrap; display: inline-flex; align-items: center; }
.nb-punkt::after {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; opacity: .55; margin-left: 26px;
}
.mit-bewegung .nb-lauf { animation: newsBand calc(var(--nb-tempo, 34) * 1s) linear infinite; }
@keyframes newsBand { to { transform: translateX(-50%); } }
.news-band:hover .nb-lauf, .news-band:focus-within .nb-lauf { animation-play-state: paused; }
/* Ohne Bewegung: kein Lauf, nur der erste Hinweis — lesbar statt leer. */
.ohne-bewegung .nb-satz:last-child { display: none; }
.ohne-bewegung .nb-lauf { width: auto; }
@media (prefers-reduced-motion: reduce) { .mit-bewegung .nb-lauf { animation: none; } }

/* ═══════════════════════════════════════════════════════════════════════════
   LEISTUNGEN MIT BÜHNE (21.09.2026) — früher „Leistungen mit Bildern"
   Sebastian: „Alternierend? Das ist 80er Style. Generell furchtbar — entweder
   du bekommst hier was Modernes hin oder wir deaktivieren diese Sektion."
   Also neu gedacht statt nachgebessert: Das Bild bleibt stehen, der Text zieht
   daran vorbei. Welche Leistung gerade dran ist, entscheidet die
   Scrollposition. Aus einer Zickzack-Liste wird eine Bühne mit einem
   Darsteller — und die Bilder bekommen endlich Größe, statt sich die Zeile mit
   dem Text zu teilen.
   ═══════════════════════════════════════════════════════════════════════════ */
.s-leistungen-wechsel .lw-buehne {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(28px, 5vw, 70px); align-items: start;
  margin-top: clamp(28px, 4vw, 48px);
}
.s-leistungen-wechsel .lw-bilder {
  position: sticky; top: clamp(80px, 14vh, 140px);
  aspect-ratio: 4/5; border-radius: var(--radius); overflow: clip;
  background: var(--grund2);
}
.s-leistungen-wechsel .lw-bild {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; border-radius: inherit;
  opacity: 0; scale: 1.06;
  transition: opacity .7s ease, scale 1.1s cubic-bezier(.16,.84,.3,1);
}
.s-leistungen-wechsel .lw-bild.ist-dran { opacity: 1; scale: 1; }
.s-leistungen-wechsel .lw-bild.platzhalter { background: var(--grund2); }
.s-leistungen-wechsel .lw-liste { list-style: none; margin: 0; padding: 0; }
.s-leistungen-wechsel .lw-liste li {
  padding: clamp(26px, 4vw, 44px) 0;
  border-bottom: 1px solid var(--linie);
  opacity: .42; transition: opacity .5s ease, translate .5s cubic-bezier(.16,.84,.3,1);
}
.s-leistungen-wechsel .lw-liste li:last-child { border-bottom: 0; }
.s-leistungen-wechsel .lw-liste li.ist-dran { opacity: 1; translate: 8px 0; }
.s-leistungen-wechsel .lw-liste h3 { margin: 0 0 8px; font-size: clamp(20px, 2.2vw, 28px); }
.s-leistungen-wechsel .lw-liste p { margin: 0; color: var(--leise); font-size: clamp(16px, 1.5vw, 19px); }
/* Ein Strich links markiert, was gerade gilt — ohne Kasten, ohne Farbe. */
.s-leistungen-wechsel .lw-liste li { position: relative; padding-left: 0; }
.s-leistungen-wechsel .lw-liste li::before {
  content: ""; position: absolute; left: -14px; top: clamp(26px, 4vw, 44px); bottom: 50%;
  width: 2px; background: var(--akzent-tief);
  scale: 1 0; transform-origin: top; transition: scale .55s cubic-bezier(.16,.84,.3,1);
}
.s-leistungen-wechsel .lw-liste li.ist-dran::before { scale: 1 1; }
/* Ohne Skript ist alles gleich sichtbar — lesbar statt halbdurchsichtig. */
.ohne-bewegung .s-leistungen-wechsel .lw-liste li { opacity: 1; }
@media (max-width: 860px) {
  .s-leistungen-wechsel .lw-buehne { grid-template-columns: 1fr; }
  .s-leistungen-wechsel .lw-bilder { position: relative; top: 0; aspect-ratio: 16/10; }
  .s-leistungen-wechsel .lw-liste li { opacity: 1; translate: none; }
  .s-leistungen-wechsel .lw-liste li::before { display: none; }
}

/* Eine Bühne braucht Länge: Ist die Liste kürzer als das Fenster, lässt sich
   der letzte Eintrag nie in die Mitte scrollen, und das Bild bleibt beim
   ersten stehen (gemessen bei zwei Einträgen). Jeder Eintrag bekommt deshalb
   eine Mindesthöhe — bei wenigen Leistungen wird die Sektion dadurch ruhiger,
   nicht länger als nötig. */
.s-leistungen-wechsel .lw-liste li { min-height: min(42vh, 300px); display: flex; flex-direction: column; justify-content: center; }
@media (max-width: 860px) { .s-leistungen-wechsel .lw-liste li { min-height: 0; display: block; } }

/* ═══════════════════════════════════════════════════════════════════════════
   SORTIMENT mit wechselndem Hintergrund (21.09.2026)
   Sebastians Idee, wörtlich umgesetzt: Das Bild der Warengruppe liegt sehr
   dezent über der ganzen Sektion; beim Überfahren der nächsten Gruppe wechselt
   der komplette Hintergrund. Alle Bilder liegen übereinander, nur eines ist
   sichtbar — der Wechsel ist eine Überblendung, kein Schnitt.
   Auf dem Handy gibt es keinen Zeiger; dort bleibt das erste Bild stehen und
   die Sektion sieht aus wie gedacht, nur ohne Wechsel.
   ═══════════════════════════════════════════════════════════════════════════ */
.s-sortiment { position: relative; overflow: clip; }
.so-grund { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.so-grundbild {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; scale: 1.04;
  transition: opacity 1s ease, scale 1.6s cubic-bezier(.16,.84,.3,1);
}
.so-grundbild.ist-dran { opacity: .15; scale: 1; }
.s-sortiment > .rahmen { position: relative; z-index: 1; }
.s-sortiment .regal article { transition: translate .35s cubic-bezier(.16,.84,.3,1), border-color .35s ease, box-shadow .35s ease; }
@media (hover: hover) {
  .s-sortiment .regal article:hover { translate: 0 -6px; border-color: color-mix(in oklab, var(--akzent) 45%, var(--linie)); }
}
.mit-bewegung .s-sortiment .regal article {
  opacity: 0; translate: 0 20px;
  transition: opacity .6s ease calc(var(--n, 0) * 100ms), translate .7s cubic-bezier(.16,.84,.3,1) calc(var(--n, 0) * 100ms),
              border-color .35s ease;
}
.mit-bewegung .s-sortiment .regal article.ist-sichtbar { opacity: 1; translate: none; }

/* ——— Lieferung oder Abholung: zwei Wege, nicht zwei Kästen ———
   Die Sektion beantwortet eine Entweder-oder-Frage. Das soll man sehen: Jede
   Karte trägt ihren eigenen Ton, das Symbol steht groß, und zwischen beiden
   liegt eine Linie statt einer Lücke. */
.s-lieferung-abholung .zwei { position: relative; gap: 0; }
.s-lieferung-abholung article {
  position: relative; overflow: clip;
  padding: clamp(30px, 4vw, 52px);
  border: 1px solid var(--linie);
  transition: translate .4s cubic-bezier(.16,.84,.3,1), box-shadow .4s ease;
}
.s-lieferung-abholung article[data-weg="0"] { border-radius: var(--radius) 0 0 var(--radius); border-right: 0; }
.s-lieferung-abholung article[data-weg="1"] { border-radius: 0 var(--radius) var(--radius) 0; }
.s-lieferung-abholung article::before {
  content: ""; position: absolute; right: -60px; top: -60px; width: 190px; height: 190px;
  border-radius: 50%; background: var(--akzent); opacity: .08;
  transition: scale .6s cubic-bezier(.16,.84,.3,1), opacity .4s ease;
}
.s-lieferung-abholung article[data-weg="1"]::before { background: var(--dunkel); }
.s-lieferung-abholung .symbol { font-size: clamp(34px, 4vw, 48px); line-height: 1; display: block; margin-bottom: 16px; }
.s-lieferung-abholung h3 { font-size: clamp(21px, 2.2vw, 28px); margin: 0 0 10px; }
.s-lieferung-abholung .la-hinweis { margin-top: 14px; font-size: 15px; color: var(--leise); }
.mit-bewegung .s-lieferung-abholung article {
  opacity: 0; translate: 0 22px;
  transition: opacity .65s ease calc(var(--n, 0) * 130ms), translate .75s cubic-bezier(.16,.84,.3,1) calc(var(--n, 0) * 130ms),
              box-shadow .4s ease;
}
.mit-bewegung .s-lieferung-abholung article.ist-sichtbar { opacity: 1; translate: none; }
@media (hover: hover) {
  .s-lieferung-abholung article:hover { translate: 0 -5px; box-shadow: 0 22px 50px color-mix(in oklab, var(--tinte) 14%, transparent); z-index: 1; }
  .s-lieferung-abholung article:hover::before { scale: 1.3; opacity: .14; }
}
@media (max-width: 720px) {
  .s-lieferung-abholung article[data-weg="0"] { border-radius: var(--radius) var(--radius) 0 0; border-right: 1px solid var(--linie); border-bottom: 0; }
  .s-lieferung-abholung article[data-weg="1"] { border-radius: 0 0 var(--radius) var(--radius); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   BEWERTUNGEN — Kopf mit Avatar, drei Layouts (21.09.2026)
   Sebastian: „Gibt es auch Varianten im Layout? Vertikale / quadratische
   Karten? Name oben — Initialen, also Avatar-Kreis etc.?"
   Das echte Bild des Bewerters gibt Google nicht weiter, und wir würden es
   auch nicht nehmen wollen — es ist ein Personenfoto ohne Einwilligung. Die
   Initiale aus dem Namen leistet dasselbe und gehört uns.
   Der Name steht jetzt oben: Wer etwas sagt, entscheidet mit, wie ernst man
   es nimmt. Unten war er eine Fußnote.
   ═══════════════════════════════════════════════════════════════════════════ */
.stimme .st-kopf {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: 12px; margin-bottom: 16px;
}
.stimme .st-avatar {
  width: 42px; height: 42px; border-radius: 50%;
  background: color-mix(in oklab, var(--akzent) 82%, var(--tinte));
  color: #fff; display: grid; place-items: center;
  font: 800 15px/1 var(--f-kopf); letter-spacing: .02em;
}
.stimme .st-wer { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.stimme .st-wer b { font-size: 16px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stimme .st-wer small { color: var(--leise); font-size: 13px; }
.stimme .st-kopf .sterne-reihe { font-size: 15px; letter-spacing: .06em; margin: 0; white-space: nowrap; }
.stimme blockquote { margin: 0; }

/* ——— Layout 2: Raster ———
   Alle Stimmen auf einen Blick, nichts läuft. Für Betriebe mit vielen guten
   Bewertungen die ehrlichere Darstellung: Man sieht die Menge. */
.s-bewertungen-lauf[data-stimmen="raster"] .lauf-bahn {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: clamp(14px, 1.6vw, 22px); overflow: visible; width: auto;
  padding-inline: clamp(16px, 5vw, 64px);
}
.s-bewertungen-lauf[data-stimmen="raster"] .lauf-karte { flex: none; opacity: 1; transform: none; scale: 1; filter: none; }
.s-bewertungen-lauf[data-stimmen="raster"] .lauf-steuer { display: none; }
.s-bewertungen-lauf[data-stimmen="raster"] .stimme-innen { height: 100%; }

/* ——— Layout 3: Band ———
   Quadratische Karten, die ruhig nebeneinander liegen und von Hand geschoben
   werden. Kein Selbstlauf, keine Perspektive — für zurückhaltende Stilwelten. */
.s-bewertungen-lauf[data-stimmen="band"] .bahn-flow { perspective: none; }
.s-bewertungen-lauf[data-stimmen="band"] .lauf-karte {
  flex-basis: min(340px, 78vw); aspect-ratio: 1; transform: none; scale: 1; opacity: 1; filter: none;
}
.s-bewertungen-lauf[data-stimmen="band"] .stimme-innen { height: 100%; display: flex; flex-direction: column; }
.s-bewertungen-lauf[data-stimmen="band"] blockquote { display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden; }
.s-bewertungen-lauf[data-stimmen="band"] .lauf-pause { display: none; }

/* Buchstaben, die dem Zeiger entgegenkommen. Der Übergang ist kurz gehalten:
   Bei 300 ms hinkt die Welle der Hand hinterher und wirkt träge, bei 120 ms
   folgt sie. `display: inline-block` wäre naheliegend, bricht aber die
   Silbentrennung — deshalb bleibt es bei inline. */
.buchstabe { transition: font-variation-settings .12s linear; }
[data-schwere] { font-synthesis-weight: none; }


/* Sicherheitsnetz für die Heldenbilder auf schmalen Schirmen: Dort bleiben
   je nach Stilwelt bis zu elf Pixel Rand, weil die Parallaxe in Prozent
   rechnet und ein Prozent bei 390 px kaum etwas ist. Statt weiter an der
   Vergrößerung zu drehen — ein Versuch damit hat den Rand auf 662 px
   vergrößert — bekommt die Sektion einen dunklen Grund in der Bildfarbe.
   Sichtbar bleibt dann ein Streifen in der Tönung des Fotos, kein heller
   Spalt. Das Problem ist damit nicht gelöst, aber unsichtbar; die Prüfung
   meldet es weiter. */
@media (max-width: 720px) {
  .s-held-vollbild, .s-held-karte, .s-held-notdienst {
    background: color-mix(in oklab, var(--dunkel) 88%, #000);
  }
}

/* Beide Lieferkarten nehmen ihre Schriftfarbe von der Fläche, auf der sie
   liegt — die zweite trägt die dunkle Grundfarbe, die erste den Akzent.
   Vorher erbte die zweite die Schriftfarbe der ersten und stand weiß auf
   hellem Orange: 1,9:1. Zusammengehörende Werte stehen zusammen. */
.s-lieferung-abholung article[data-weg="0"] {
  background: var(--akzent-tief); color: var(--auf-akzent, #fff);
}
.s-lieferung-abholung article[data-weg="1"] {
  background: var(--dunkel); color: var(--dunkel-text);
}
.s-lieferung-abholung article[data-weg="0"] *,
.s-lieferung-abholung article[data-weg="1"] * { color: inherit; }
.s-lieferung-abholung article .la-hinweis { opacity: .75; }

/* ═══════════════════════════════════════════════════════════════════════════
   SCHRIFT AUF BILD — KEIN GESCHMACK, SONDERN PFLICHT (22.09.2026)

   Sebastian: „im ‚klassisch' Modus kann man die Schrift nicht lesen — auch ein
   UX Fehler. Das MUSS 100% sitzen, es sieht sofort wie ein Fehler aus und
   kostet uns einen Kunden."

   Gemessen über alle sechs Stilwelten im Textkasten der Laufkarten:

     klassisch   Etikett + Absatz  #4a4a4a  auf  #2b2b2b   →  1,7:1
     werkstatt   Etikett           #d12a0b  auf  #1a1a1a   →  2,7:1
     freundlich  Etikett           #227260  auf  #000/62%  →  2,4:1
     hofladen    Etikett           #a6432b  auf  #000/62%  →  2,9:1
     meister     Etikett           #b35300  auf Verlauf    →  3,3:1

   Die Ursache ist überall dieselbe: `.lauf-text.auf-bild` setzt `color: #fff`,
   aber Etikett und Absatz haben eigene Farben — `--akzent-tief` und `--leise`.
   Beide sind für Schrift auf HELLEM Grund gerechnet. In einem dunklen Kasten
   über einem Foto gehören sie zur falschen Hälfte der Palette.

   Die Regel lautet ab hier: Was auf einem Bild steht, nimmt die helle Hälfte —
   und das Etikett wird zusätzlich aufgehellt, weil es klein ist.
   ═══════════════════════════════════════════════════════════════════════════ */
/* Der `[data-flaeche]`-Vorsatz ist kein Zierrat: `[data-flaeche="linie"] :is(.s
   article, .s .karte:not(.glas), …) p` wiegt (0,4,1) und hat die Regel ohne
   Vorsatz (0,4,0) geschlagen — in `klassisch` und `atelier` blieb das Etikett
   deshalb auf `--leise`. Gemessen mit dem DevTools-Protokoll, nicht geraten. */
[data-flaeche] .lauf-karte:has(.lauf-bild) .lauf-text,
[data-flaeche] .lauf-karte:has(.lauf-bild) .lauf-text h3,
.lauf-karte:has(.lauf-bild) .lauf-text,
.lauf-karte:has(.lauf-bild) .lauf-text h3 { color: #fff; }
[data-flaeche] .lauf-karte:has(.lauf-bild) .lauf-text p:not(.s-etikett),
.lauf-karte:has(.lauf-bild) .lauf-text p:not(.s-etikett) {
  color: color-mix(in oklab, #fff 90%, transparent);
}
[data-flaeche] .lauf-karte:has(.lauf-bild) .lauf-text .s-etikett,
.lauf-karte:has(.lauf-bild) .lauf-text .s-etikett {
  color: color-mix(in oklab, var(--akzent-hell, #fff) 70%, #fff);
}
/* Der Block-Kasten trägt die Markenfarbe als Fläche — dort gilt die Schrift,
   die für DIESE Fläche gerechnet ist, nicht die helle Hälfte. */
[data-flaeche] [data-textgrund="block"] .lauf-karte:has(.lauf-bild) .lauf-text,
[data-flaeche] [data-textgrund="block"] .lauf-karte:has(.lauf-bild) .lauf-text h3,
[data-flaeche] [data-textgrund="block"] .lauf-karte:has(.lauf-bild) .lauf-text p:not(.s-etikett),
[data-textgrund="block"] .lauf-karte:has(.lauf-bild) .lauf-text,
[data-textgrund="block"] .lauf-karte:has(.lauf-bild) .lauf-text h3,
[data-textgrund="block"] .lauf-karte:has(.lauf-bild) .lauf-text p:not(.s-etikett) {
  color: var(--auf-akzent, #fff);
}
[data-flaeche] [data-textgrund="block"] .lauf-karte:has(.lauf-bild) .lauf-text .s-etikett,
[data-textgrund="block"] .lauf-karte:has(.lauf-bild) .lauf-text .s-etikett {
  color: color-mix(in oklab, var(--auf-akzent, #fff) 82%, transparent);
}

/* ——— Der Textkasten bleibt IN der Karte ———
   Sebastian: „die text intergrund box ist ne katastrophe. steht über den rand".
   `block` stand mit `margin: 0` auf der Kartenkante; bei gerundeten Karten
   schnitt die Rundung die Ecke ab. Jetzt hat jeder Kasten mit Fläche denselben
   Abstand — und damit greift die Radienformel: innen = außen − Abstand. */
[data-textgrund="block"] .lauf-text {
  margin: clamp(16px, 2vw, 30px);
  width: auto; max-width: min(56ch, calc(100% - 2 * clamp(16px, 2vw, 30px)));
}
[data-textgrund="balken"] .lauf-text,
[data-textgrund="glas"]   .lauf-text,
[data-textgrund="block"]  .lauf-text {
  --innen-abstand: clamp(16px, 2vw, 30px);
  border-radius: max(0px, calc(var(--ecke, 18px) - var(--innen-abstand)));
}

/* ——— Die Ortsliste bleibt lesbar, auch unter dem Zeiger ———
   Sebastian, 22.09.2026: „der hover ist bei den Orten immernoch nicht lesbar —
   auch ein FEHLER und kein GESCHMACK."

   Gemessen in `klassisch`: die Schrift sprang beim Überfahren auf #ffffff, der
   Untergrund blieb #f5f3ef. Das sind 1,03:1 — die Zeile verschwindet.

   Ursache: `.s-einsatzgebiet li:hover` setzt Fläche UND Schrift auf die
   Markenfarbe. Die Regel, die aus der Ortsangabe wieder eine Aufzählung macht,
   hat die Fläche zurückgenommen — die weiße Schrift aber stehen lassen. Wer
   eine Fläche entfernt, muss die Schrift mitnehmen, die für sie gedacht war. */
.s-einsatzgebiet--karte .gebiet-text li,
.s-einsatzgebiet--karte .gebiet-text li:hover,
.s-einsatzgebiet--karte .gebiet-text li:hover * { color: inherit; }
/* Wo die Fläche bleibt, bleibt auch die helle Schrift richtig — dort ändert
   sich nichts. Nur der Punkt vor dem Ort wächst, damit das Überfahren trotzdem
   eine Antwort gibt. */
.s-einsatzgebiet--karte .gebiet-text li::before { transition: scale .25s var(--kurve, ease); }
.s-einsatzgebiet--karte .gebiet-text li:hover::before { scale: 1.5; }

/* ——— Der Leitsatz bekommt Zeilen, keine Wortsäule ———
   Sebastian: „Bitte gib diesem Satz mehr Breite und schreib nicht jedes Wort
   untereinander."

   Der Deckel stand als `max-width: 22ch` auf dem `blockquote`. Das `ch` misst
   sich an der Schrift DES ELEMENTS — und das blockquote steht auf 16 px, nicht
   auf den 62 px des Satzes. Gemessen kamen so 220 bis 264 px heraus: rund drei
   Zeichen breit. Der Deckel gehört auf den Absatz, der die große Schrift
   wirklich trägt. */
.s-leitsatz blockquote { max-width: min(1100px, 92%); }
.s-leitsatz blockquote p { max-width: 18ch; margin-inline: auto; text-wrap: balance; }

/* ——— Akkordeon: Polster für die Ziffern, Hover ohne Überlagerung ———
   Sebastian: „Die Boxen haben wieder kein Padding und somit stehen die Zahlen
   direkt am Rand. Und beim Mouse-Over wandert der Text zu weit nach links und
   überlagert die Zahlen."

   Zwei getrennte Fehler:
   1. Die Zeilen hatten seitlich kein Polster — die Ziffer klebte an der Kante
      der eingefärbten Fläche.
   2. `summary:hover { padding-left: 8px }` hat den Abstand von 46 px auf 8 px
      ZURÜCKGESETZT statt ihn zu vergrößern. Der Titel sprang dadurch nach
      links auf die Ziffer. Der Aufrückweg läuft jetzt über eine eigene
      Variable, die zum Grundwert addiert wird. */
/* Die aufgeklappte Zeile trägt eine eingefärbte Fläche. Auf einer Fläche
   braucht Text mehr Luft als auf dem Seitengrund — 20 px sahen bei Bensenair
   immer noch knapp aus. (Sebastian, 22.09.2026: „korrigiere den Textabstand
   in der Box") */
.s-leistungen-akkordeon details { padding-inline: clamp(16px, 1.9vw, 28px); }
.s-leistungen-akkordeon .ak-huelle > p { padding-right: clamp(8px, 1vw, 16px); }
.s-leistungen-akkordeon summary {
  --ak-einzug: 46px; --ak-ruck: 0px;
  padding-left: calc(var(--ak-einzug) + var(--ak-ruck));
  transition: color .2s, padding-left .25s var(--kurve, ease);
}
@media (hover: hover) {
  .s-leistungen-akkordeon summary:hover { --ak-ruck: 8px; padding-left: calc(var(--ak-einzug) + var(--ak-ruck)); }
}
/* Die Ziffer rückt mit — sonst reißt beim Aufrücken eine Lücke auf. */
.s-leistungen-akkordeon summary::before { left: var(--ak-ruck, 0px); transition: color .3s ease, scale .3s ease, left .25s var(--kurve, ease); }

/* ——— Radienformel auch dort, wo das Polster aus einer Karte kommt ———
   Sebastian: „Hier ist der Radius innen nicht korrekt."
   Jede Karte mit eigener Polsterung muss `--innen-abstand` setzen, sonst
   bekommt das Bild darin denselben Radius wie die Karte — und wirkt runder,
   als die Formel erlaubt. */
/* Gemessen: die 22 px Polsterung kommen NICHT aus der Sektion, sondern aus der
   Flächen-Schraube („Wo eine Linie ist, braucht der Text Abstand"). Genau dort
   gehört `--innen-abstand` hin — eine Pauschale von 22 px hätte den Bildern in
   den vier Stilwelten ohne Polsterung einen falschen Radius gegeben. */
[data-flaeche="linie"] .s article, [data-flaeche="linie"] .s .karte:not(.glas),
[data-flaeche="linie"] .s .kasten, [data-flaeche="linie"] .s .kachel,
[data-flaeche="linie"] .s .person { --innen-abstand: clamp(14px, 1.6vw, 22px); }
[data-flaeche="linie"] .s-leistungen-kacheln .kacheln > article { --innen-abstand: clamp(16px, 1.8vw, 24px); }
[data-passepartout="breit"] .s figure { --innen-abstand: 18px; }

/* ——— Die Bühne ist jetzt bedienbar, also muss sie auch so aussehen ———
   Wer klicken kann, muss sehen, dass er klicken kann — und wo er gerade ist. */
.s-leistungen-wechsel .lw-liste li { cursor: pointer; }
.s-leistungen-wechsel .lw-liste li:focus-visible {
  outline: 2px solid var(--akzent-tief); outline-offset: 6px;
  border-radius: max(0px, calc(var(--radius, 0px) - 6px));
}
@media (hover: hover) {
  .s-leistungen-wechsel .lw-liste li:not(.ist-dran):hover { opacity: .8; }
}

/* ——— „Heute" ist die Frage, mit der jemand auf die Zeiten schaut ———
   Sebastian, 22.09.2026: „wenn ich heute auf die Webseite gehe und mich die
   Öffnungszeiten interessieren, möchte ich vielleicht wissen, wie heute
   geöffnet ist."

   Die Zeile bekommt eine Fläche in der Markenfarbe und ein kleines Wort. Kein
   Balken links, kein Pfeil: Die Tafel steht oft auf dunklem Grund, und eine
   Fläche trägt dort besser als eine Linie. Der Zusatz steht in der Zeile, damit
   auch ein Vorleseprogramm ihn ausgibt — eine Farbe allein sagt nichts. */
.zeiten tr.ist-heute, .tafel li.ist-heute {
  background: color-mix(in oklab, var(--akzent) 16%, transparent);
  font-weight: 700;
}
.tafel li.ist-heute {
  border-radius: max(0px, calc(var(--radius, 0px) - var(--innen-abstand, 0px)));
  padding-inline: 10px; margin-inline: -10px;
}
.zeiten tr.ist-heute :is(th, td) { color: inherit; }
/* Die Tafel steht auf dunklem Grund: dort trägt die aufgehellte Markenfarbe. */
.s-oeffnungszeiten-tafel .tafel li.ist-heute,
.s[data-ton="dunkel"] .ist-heute {
  background: color-mix(in oklab, var(--akzent-hell) 22%, transparent);
}
/* Zwei Anläufe, beide von der eigenen Prüfung kassiert:
     1. gefüllte Kapsel in `--akzent` mit `--auf-akzent`   → 4,3:1 (12×)
     2. Umriss in `--akzent-tief` / `--akzent-hell`        → 3,25:1 bis 5,6:1,
        je nach Stilwelt und je nachdem, wie hell die eingefärbte Zeile den
        Untergrund macht.

   Der Fehler steckte beide Male in derselben Annahme: dass eine feste Farbe
   auf einem Grund landet, den ich kenne. Der Grund ist aber die schon
   eingefärbte Zeile, und deren Helligkeit hängt an Stilwelt UND Schraube.

   Also keine eigene Farbe. Die Marke nimmt die Schriftfarbe ihrer Zeile — die
   ist bereits geprüft, per Definition lesbar, und bleibt es auch, wenn sich
   Palette oder Schraube ändern. Zu sehen ist sie trotzdem: durch den Umriss,
   durch die Sperrung und durch die eingefärbte Zeile darunter. */
.heute-marke {
  display: inline-block; margin-left: 8px; vertical-align: baseline;
  font: 700 11px/1 var(--f-knopf, var(--f-text)); text-transform: uppercase; letter-spacing: .12em;
  padding: 3px 8px; border-radius: 99px;
  background: none; color: inherit;
  border: 1px solid color-mix(in oklab, currentColor 42%, transparent);
}

/* Eine geschlossene Zeile ist gedimmt — heute ist sie trotzdem die wichtigste. */
.zeiten tr.zu.ist-heute, .tafel li.zu.ist-heute { opacity: 1; }

/* Dieselbe Spezifitätsfalle wie beim Etikett: `[data-flaeche="linie"] .s article *`
   setzt `color: var(--tinte)` und trifft damit auch das Symbol, das seine Form
   aus `currentColor` zieht. Ein Symbol in Textfarbe ist kein Symbol mehr,
   sondern ein zweites Stück Schrift. */
[data-flaeche] .s .s-icon, .s .s-icon { color: var(--akzent-tief); }
[data-flaeche] .s[data-ton="dunkel"] .s-icon,
.s[data-ton="dunkel"] .s-icon { color: var(--akzent-hell); }

/* ——— Kartenbeschriftung: entweder lesbar oder gar nicht ———
   Die eigene Gesamtprüfung, zwölfmal in Folge: „Beschriftung ‚Feldstraße' nur
   4.6 px groß". Die Karte ist ein SVG mit fester Zeichenfläche; wird sie
   schmaler dargestellt, schrumpft die Schrift mit. Gemessen:

     Handy    390 px  → Maßstab 0,42  → 11 px werden 4,6 px
     Tablet   820 px  → Maßstab 0,88  → 11 px werden  9,7 px
     Desktop 1400 px  → Maßstab 1,50  → 11 px werden 16,5 px

   Eine Beschriftung unter 12 px liest niemand. Sie wegzulassen nimmt der Karte
   nichts, was sie auf dieser Größe leisten könnte: Straßenverlauf, Nadel und
   Umgebung bleiben. */
   Die Gebietskarte hatte dafür schon eine Gegensteuerung (siehe die Regeln zu
   `.gebiet-bild .karte-ort text` weiter oben): CSS überschreibt das
   `font-size`-Attribut des SVG, also lässt sich je Fenstergröße nachlegen. Den
   Straßennamen der Standortkarte fehlte genau das. Er bekommt es hier — und
   unterhalb der Größe, ab der auch Nachlegen nicht mehr hilft, verschwindet er.
   Bei Maßstab 0,42 müsste er auf 29 px im Zeichenraum wachsen; zwölf solcher
   Namen auf einer 500 px breiten Karte wären keine Beschriftung mehr, sondern
   eine zugedeckte Karte. */
.karte-strasse { font-size: 12px; }
@media (max-width: 1100px) { .karte-strasse { font-size: 15px; } }
@media (max-width: 700px)  { .karte-strasse { display: none; } }

/* ——— Kein Marker hinter einem Kasten ———
   Sebastian, 21.09.2026: „Der pulsierende Standort ist immer noch hinter der
   Box." Bei der Standortkarte war die Ursache die volle Kastenbreite ab 860 px
   — die Schwelle steht jetzt bei 620 px, gemessen über sieben Fensterbreiten.

   Beim Kontaktformular liegt es anders: Zwischen 480 und 760 px füllt das
   Formular die Sektion bis auf 25 bis 105 px am Rand. Die Karte ist dort kein
   Bild mehr, sondern Untergrund — und ein pulsierender Punkt, der halb hinter
   Milchglas blinkt, sieht nach Defekt aus. Die Karte verschieben hieße, sie
   vom Betrieb wegzurücken; dann markierte der Punkt ohnehin nichts mehr.
   Also bleibt er dort weg. */
@media (max-width: 760px) {
  .s-kontakt-formular--karte .karte-nadel { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   FUSSZEILE UND ÖFFNUNGSZEITEN (23.09.2026)

   Sebastian: „Der Footer scheint nicht korrekt im Layout — Infos stehen alle
   links und dann Copyright rechts, das sollte eigentlich oben und unten sein."

   Er hat recht, und der Grund ist eine Altlast: `.fuss .rahmen` steht seit der
   ersten Fassung auf `display: flex; justify-content: space-between`. Die
   neuere Fußzeile bringt ihr eigenes Raster mit — `.fuss-raster` als Grid,
   `.fuss-unten` mit Trennlinie darüber. Beide zusammen ergeben: Raster links,
   Schlusszeile rechts daneben statt darunter.

   Gemessen: fuss-raster bei x=64, fuss-unten bei x=692 auf gleicher Höhe.
   ═══════════════════════════════════════════════════════════════════════════ */
.fuss .rahmen { display: block; }
.fuss .rahmen > * + * { margin-top: 0; }

/* ——— Die Zeitentabelle braucht Innenabstand ———
   Sebastian: „Bei den Öffnungszeiten haben wir wieder das Padding-Problem."
   Gemessen in der Kontaktkarte: Tag und Zeit standen bei 0 px von beiden
   Kanten. Die „heute"-Zeile hat eine Fläche — und eine Fläche, deren Text die
   Kante berührt, sieht immer nach Versehen aus. Dieselbe Rechnung wie beim
   Akkordeon: Der Innenabstand gehört an die Zeile, nicht an die Tabelle,
   damit die eingefärbte Fläche ihn mitnimmt. */
.zeiten { border-collapse: separate; border-spacing: 0; }
.zeiten :is(th, td) { padding-block: 9px; }
.zeiten th { padding-left: clamp(10px, 1.2vw, 16px); padding-right: 14px; }
.zeiten td { padding-right: clamp(10px, 1.2vw, 16px); }
.zeiten tr.ist-heute :is(th, td):first-child {
  border-start-start-radius: max(0px, calc(var(--radius, 0px) - 4px));
  border-end-start-radius: max(0px, calc(var(--radius, 0px) - 4px));
}
.zeiten tr.ist-heute :is(th, td):last-child {
  border-start-end-radius: max(0px, calc(var(--radius, 0px) - 4px));
  border-end-end-radius: max(0px, calc(var(--radius, 0px) - 4px));
}
/* Die Fläche liegt jetzt auf den Zellen, nicht auf der Zeile: `tr` nimmt in
   einer Tabelle keinen Radius an. */
.zeiten tr.ist-heute { background: none; }
.zeiten tr.ist-heute :is(th, td) {
  background: color-mix(in oklab, var(--akzent) 16%, transparent);
}
.s[data-ton="dunkel"] .zeiten tr.ist-heute :is(th, td),
.s-oeffnungszeiten-tafel .zeiten tr.ist-heute :is(th, td) {
  background: color-mix(in oklab, var(--akzent-hell) 22%, transparent);
}
