/* --- Werkstatt: zweite Haut fuer die oeffentliche Seite -------------------
   Entscheidung Matteus, 18.09.2026: weg vom glatten, runden Erscheinungsbild,
   hin zu etwas, das nach Anlagenbau aussieht statt nach Software.

   Diese Datei steht NEBEN style.css und ueberschreibt Token, Raster, Rhythmus
   und wenige Bauteile. style.css bleibt unangetastet; die Fassung von
   18.09.2026 frueh liegt zusaetzlich als style-hell-2026-09-18.css daneben.

   Geladen wird sie von jeder oeffentlichen Seite, nach style.css. Der Rueckweg
   ist eine entfernte Zeile im <head> -- keine Rekonstruktion. */

:root {
  /* Warme Graustufen statt kuehlem Weiss: Papier, nicht Bildschirm. */
  --bg:          #f5f3f0;
  --bg-elevated: #ffffff;
  --bg-sunken:   #eceae5;
  --fg:          #1c1a17;
  --fg-muted:    #6a635b;
  --fg-faint:    #8a8279;
  --line:        rgba(28, 26, 23, .14);
  --line-strong: rgba(28, 26, 23, .26);

  /* Das Blau der Wortmarke, eine Spur tiefer, damit es auf Papier traegt. */
  --accent:      #1d5fd0;
  --accent-hover:#1750b5;
  --accent-fg:   #ffffff;
  --ok:          #1c7a46;

  --nav-bg:      rgba(245, 243, 240, .88);

  /* Kanten statt Rundungen. Nicht ganz scharf -- zwei Pixel sind der
     Unterschied zwischen "gebaut" und "unfertig". */
  --radius-sm: 2px;
  --radius:    3px;
  --radius-lg: 4px;
  --radius-bild: 14px;   /* Fotos bleiben rund eingefasst, Flaechen nicht */

  /* Schatten fast weg: gedruckte Dinge werfen keine. */
  --shadow-sm: 0 1px 0 rgba(28, 26, 23, .06);
  --shadow-md: 0 1px 0 rgba(28, 26, 23, .10);

  /* --- Skala --------------------------------------------------------------
     Ein Raster fuer Abstaende, Groessen und Zeilenlaengen. Kanten fluchten,
     weil jede Seite dieselben Masse benutzt statt eigener style="…".

     Vertikaler Rhythmus (Verhaeltnis, nicht Dekoration):
       eyebrow → Ueberschrift   0.75rem
       Ueberschrift → Vorspann  1.25rem
       Vorspann → Inhalt        2rem
       Abschnitt                clamp(3.25rem, 7vw, 5.5rem) oben und unten
     Das ist 3 : 5 : 8 gegenueber der Abschnittsluft. */

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-7: 2rem;
  --space-8: 2.5rem;
  --space-9: 3.5rem;
  --section: clamp(3.25rem, 7vw, 5.5rem);

  --gutter:  clamp(1.25rem, 4.5vw, 1.5rem);
  --page:    min(67.5rem, calc(100% - 2 * var(--gutter)));
  --measure: 40rem;
  --prose:   40rem;

  /* Eine Kurve, eine Dauer. Staffelabstand kurz genug, dass nichts wartet. */
  --ease:     cubic-bezier(.22, .61, .36, 1);
  --duration: .7s;
  --stagger:  .07s;

  /* Schaltflaechen: nie unter der Daumenbreite. */
  --tap: 2.75rem;

  /* Abstand unter der klebenden Leiste. Am Telefon zwei Zeilen. */
  --nav-offset: 4.75rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:          #0c0b09;
    --bg-elevated: #141210;
    --bg-sunken:   #0a0908;
    --fg:          #f4f1ea;
    --fg-muted:    #b7aea2;
    --fg-faint:    #8e8579;
    --line:        rgba(244, 241, 234, .16);
    --line-strong: rgba(244, 241, 234, .32);
    --accent:      #7eb4ff;
    --accent-hover:#9ec8ff;
    --ok:          #3ee07a;
    --nav-bg:      rgba(12, 11, 9, .88);
    --shadow-sm:   0 1px 0 rgba(0, 0, 0, .55);
    --shadow-md:   0 1px 0 rgba(0, 0, 0, .7);
  }
  .jetzt-haupt .gross,
  .zaehlwerk-zahlen dd,
  .wert dd {
    color: var(--accent);
  }
  .card[data-tone="solar"]  { --tone: #ffc45a; }
  .card[data-tone="energy"] { --tone: #3eecc8; }
  .card[data-tone="home"]   { --tone: #9ea2ff; }
  .card[data-tone="care"]   { --tone: #7eb4ff; }
  .card[data-tone="signal"] { --tone: #ff7ec4; }
}

/* ---------- Typografie --------------------------------------------------- */

.eyebrow {
  font-size: .6875rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--fg-muted);
  display: flex;
  align-items: center;
  gap: .7rem;
  margin: 0 0 var(--space-3);
}
.eyebrow::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}
.band .eyebrow { color: #9fc4ff; }
.band .eyebrow::after { background: rgba(255, 255, 255, .22); }

h1, h2, h3 { letter-spacing: -.015em; font-weight: 650; text-wrap: balance; overflow-wrap: break-word; }
h1 {
  font-size: clamp(2.25rem, 7vw, 4rem);
  line-height: 1.06;
  letter-spacing: -.03em;
  margin: 0 0 var(--space-5);
}
h2 {
  font-size: clamp(1.7rem, 4.2vw, 2.7rem);
  line-height: 1.1;
  letter-spacing: -.025em;
  margin: 0 0 var(--space-5);
}
h3 {
  font-size: clamp(1.1rem, 2.2vw, 1.35rem);
  letter-spacing: -.01em;
  margin: 0 0 var(--space-3);
}
.lead {
  font-size: clamp(1.05rem, 2.1vw, 1.22rem);
  line-height: 1.62;
  max-width: var(--measure);
  margin: 0 0 var(--space-7);
}
p { line-height: 1.68; margin: 0 0 var(--space-4); text-wrap: pretty; }

.wert dd, .vergleich dd, .zaehlwerk-zahlen dd, .ecke b, .jetzt-haupt .gross {
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}

/* ---------- Raster ------------------------------------------------------- */

.page { width: var(--page); margin-inline: auto; }
.prose { max-width: var(--prose); }

/* Abschnitte tragen die vertikale Luft, .page nur die Breite. Sonst wuerde
   dieselbe Klasse Fusszeile, Band und Inhalt unterschiedlich aufblasen. */
section { padding-block: 0; }
section.page { padding-block: var(--section); }
.hero {
  text-align: left;
  overflow: visible;
}
.hero.page {
  /* Kurzer Weg: der Kopf fuellt den Schirm nicht. Die grosse Schrift
     ist Transform, nicht extra Luft. */
  padding-block: clamp(1.5rem, 3.5vw, 2.5rem) var(--space-7);
}
.hero .lead { margin-inline: 0; }
.hero-actions { justify-content: flex-start; }

/* Quiet chapter head for every inner page. Start and plant keep the
   fly-through; these pages must not. Same house (eyebrow, paper, left
   edge) without the billboard type, the drifting glow, or a sticky
   track. The hairline is the threshold -- not empty space -- so the
   first content stays in the first screen. */
.kopf {
  text-align: left;
  background: var(--bg-sunken);
  border-bottom: 1px solid var(--line);
  padding-block: clamp(1.75rem, 4vw, 3.25rem);
  overflow: visible;
}
/* Inner pages keep class "hero" so removing werkstatt.css still
   leaves style.css's head. The drifting glow belongs to the start
   page; it is the opposite of quiet. */
.kopf::before {
  content: none;
  display: none;
}
.kopf h1 {
  font-size: clamp(1.7rem, 4.4vw, 2.6rem);
  line-height: 1.12;
  letter-spacing: -.022em;
  margin: 0 0 var(--space-5);
}
.kopf .lead {
  margin-inline: 0;
  margin-bottom: var(--space-7);
}
.kopf .lead:last-child,
.kopf .hero-actions {
  margin-bottom: 0;
}
.kopf + section.page,
.kopf + .legal {
  padding-top: var(--space-8);
}

/* Scrollgekoppelte Ueberschrift: Layout in der Startgroesse, Schrumpfen
   nur ueber transform. --hero-scale/--hero-spread setzt motion.js aus
   scrollY, linear und umkehrbar. */
[data-hero] {
  --hero-scale: 1;
  --hero-spread: 1;
  --hero-p: 0;
}
.hero-heading {
  font-size: clamp(2.7rem, 10vw, 5.15rem);
  line-height: 1.05;
  margin: 0 0 var(--space-5);
}
/* Die Verschiebung der Zeilen ist ein transform -- sie nimmt sich Platz, ohne
   welchen zu belegen. Ohne diesen mitwandernden Abstand schiebt die untere
   Zeile im Ausgangszustand in den Vorspann hinein. Er schrumpft mit
   --hero-spread, also genau im Mass, in dem die Zeilen zusammenruecken.
   [data-hero] davor, weil style.css `.hero h1 { margin-bottom: 1.1rem }`
   setzt -- eine Klasse plus ein Element schlaegt eine Klasse allein, und
   genau daran ist die Reservierung im ersten Anlauf wirkungslos verpufft. */
[data-hero] .hero-heading {
  margin-bottom: calc(var(--space-5) + var(--hero-spread) * 1.05em);
}

/* ---------- Der Zoom auf der Startseite ---------------------------------- */
/*
   Gewuenscht nach dem Vorbild von apple.com: die Schrift waechst beim
   Scrollen, man faehrt hindurch, dahinter liegt die Seite.
   Damit man das ueberhaupt sehen kann, muss der Kopf stehen bleiben, waehrend
   gescrollt wird -- sonst waere er weg, bevor etwas passiert ist. Also eine
   Laufstrecke von zwei Bildschirmhoehen, in der die Halteschicht klebt.
   Alles laeuft ueber transform und opacity, eine Rechnung je Bild.
   Der Text wird ausgeblendet, bevor er gross genug waere, um unscharf zu
   wirken -- Chrome zeichnet stark skalierte Schrift weich, deshalb nutzt
   Apple dort SVG. Wir brauchen das nicht, weil bei uns nichts stehen bleibt,
   was unscharf werden koennte.
*/
.js [data-zoom] {
  --hero-zoom: 1;
  --hero-op: 1;
  --hero-ein: 0;
  min-height: 220svh;
  padding-block: 0;
  display: block;
}
.js [data-zoom] .zoom-halt {
  position: sticky;
  top: 3.25rem;
  min-height: calc(100svh - 3.25rem);
  /* Beide Schichten im selben Feld: die Schrift und der Text stehen
     uebereinander, nicht untereinander. Sonst schoebe das Einblenden des
     einen das andere weg -- und genau dazwischen soll man hindurchfahren. */
  display: grid;
  align-content: center;
  padding-block: var(--space-6);
  /* Die Schrift waechst auf das Zwoelfache. Ohne diesen Schnitt wird daraus
     eine horizontale Scrollleiste -- gesehen bei 1280 px, Zoom 5. Sticky
     bleibt intakt: overflow liegt auf der klebenden Schicht, nicht auf der
     Strecke. */
  overflow: hidden;
}
.js [data-zoom] .zoom-schrift,
.js [data-zoom] .zoom-rest {
  grid-area: 1 / 1;
  width: 100%;
}
.js [data-zoom] .zoom-schrift {
  transform: scale(var(--hero-zoom));
  transform-origin: 50% 50%;
  opacity: var(--hero-op);
}
/* Beim Oeffnen steht die Schrift allein und fuellt den Schirm. */
.js [data-zoom] .hero-heading {
  font-size: clamp(2.6rem, 12.5vw, 7rem);
  line-height: 1.02;
  margin-bottom: 0;
  /* Sonst bricht "und jemand, der hinsieht." in Einzelwoerter auf und die
     Zeilen werden unterschiedlich lang -- bei dieser Groesse faellt das
     sofort auf. */
  text-wrap: balance;
}
.js [data-zoom] .hero-cluster { transform: none; }
.js [data-zoom] .hero-line { transform: none; }
/* Der Text kommt erst, wenn man durch die Schrift hindurch ist. */
.js [data-zoom] .zoom-rest {
  opacity: var(--hero-ein);
  transform: translate3d(0, calc((1 - var(--hero-ein)) * 2rem), 0);
}
/* Solange er nicht da ist, ist er auch nicht anfassbar -- eine unsichtbare
   Schaltflaeche, die Klicks schluckt, ist schlimmer als keine. */
[data-zoom][data-phase="schrift"] .zoom-rest { pointer-events: none; }
[data-zoom][data-phase="text"] .zoom-schrift { pointer-events: none; }

/* ---------- Dasselbe im Referenzband ------------------------------------- */
/*
   Gleicher Ablauf wie im Kopf, nur mit dem Film dahinter: erst die
   Ueberschrift allein, man faehrt hindurch, dabei kommt das Video zum
   Vorschein, danach die Zahlen und die beiden Schaltflaechen.
   Die Haltestrecke gehoert dem Abschnitt, das Klebende ist die innere
   Schicht -- der Film sitzt darin, sonst wuerde er ueber zwei
   Bildschirmhoehen gezogen.
*/
.js .band.band-zoom {
  min-height: 200svh;
  display: block;
  overflow: visible;
  background: none;
}
.js .band-zoom .zoom-halt {
  position: sticky;
  top: 0;
  min-height: 100svh;
  overflow: hidden;
  isolation: isolate;
  display: grid;
  align-items: center;
  background: #0b0d10;
  border-radius: 0;
}
.js .band-zoom .zoom-halt > .page {
  display: grid;
  align-content: center;
}
.js .band-zoom .zoom-schrift,
.js .band-zoom .zoom-rest { grid-area: 1 / 1; }

/* Die haltende Schicht ist genau einen Schirm hoch und schneidet ab, was
   darueber hinausgeht -- sonst stuende die wachsende Schrift ueber dem
   halben Dokument. Der Preis: was nicht hineinpasst, ist nicht nur unten
   abgeschnitten, sondern unerreichbar, weil die Schicht klebt. Genau das ist
   den beiden Schaltflaechen passiert (gemeldet 19.09.2026). Auf dem Telefon
   ruecken deshalb Vorspann, Kennzahlen und Knoepfe enger zusammen, bis alles
   in 844 Punkte Hoehe passt -- weglassen waere die schlechtere Antwort. */
@media (max-width: 40rem) {
  /* Ohne .js, damit dieselbe Enge auch bei prefers-reduced-motion gilt:
     dort gibt es keine klebende Schicht, aber der Film ist trotzdem nur
     einen Schirm hoch, und die Knoepfe muessen hinein. */
  .band-zoom .zoom-rest .lead {
    font-size: .9375rem;
    line-height: 1.5;
  }
  .band-zoom .zoom-rest .kennzahlen {
    margin-top: var(--space-3);
    gap: var(--space-2) var(--space-5);
  }
  .band-zoom .zoom-rest .kennzahlen dd { font-size: 1.15rem; }
  .band-zoom .zoom-rest .kennzahlen dt { margin-bottom: 0; }
  .band-zoom .zoom-rest .knopf-paar { margin-top: var(--space-4); }
  .band-zoom .zoom-halt > .page { padding-block: var(--space-4); }
}
.js .band-zoom .zoom-schrift h2 {
  font-size: clamp(1.9rem, 7.4vw, 4.2rem);
  line-height: 1.05;
  text-wrap: balance;
  /* "Blockheizkraftwerk" ist laenger als eine Telefonspalte breit ist. Ohne
     Trennung schiebt das Wort ueber den Rand hinaus -- und ein Band, aus dem
     Text herauslaeuft, sieht nach Fehler aus, nicht nach Gestaltung. */
  hyphens: auto;
  overflow-wrap: break-word;
}
/* Film und Verlauf haengen in style.css an `.band > video` und `.band::after`
   -- beide sind jetzt eine Ebene tiefer, sonst wuerden sie ueber die ganze
   Haltestrecke von zwei Bildschirmhoehen gezogen. */
.js .band-zoom > .zoom-halt > video,
.js .band-zoom > .zoom-halt > img.standbild {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 42%;
}
.js .band-zoom::after { content: none; }
.js .band-zoom .zoom-halt::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(180deg, rgba(4,6,9,.62) 0%, rgba(4,6,9,.46) 45%, rgba(4,6,9,.74) 100%);
  /* Der Film wird beim Hindurchfahren freier: der Verlauf traegt die
     Lesbarkeit des Textes, und wenn der Text weg ist, darf das Bild
     durchschimmern. Ganz verschwindet er nicht -- die Ecke mit den
     Livewerten steht weiter darauf. */
  opacity: calc(.45 + var(--hero-op, 1) * .55);
}
.hero-cluster {
  display: block;
  transform: scale(var(--hero-scale));
  transform-origin: top left;
  will-change: transform;
}
.hero-line {
  display: block;
  transform: translate3d(0, calc(var(--hero-spread) * var(--line-shift, 0) * 1em), 0);
  will-change: transform;
}
/* Der Abstand, der sich schliesst. Vorher -0,1 zu 0,42 em: gemessen ein
   Uebergang, gesehen nichts. Ein halbes Zeilenmass ist der Unterschied
   zwischen "da bewegt sich etwas" und "da ist nichts passiert". */
.hero-line:nth-child(1) { --line-shift: -0.34; }
.hero-line:nth-child(2) { --line-shift: 0.92; }
.band.bildkopf .hero-heading {
  font-size: clamp(2.35rem, 8vw, 4.4rem);
  color: #fff;
}

.band { padding-block: 0; border-top: 0; }
.band + section,
section + .band { border-top: 0; }
.band > .page {
  width: 100%;
  padding-block: var(--space-8);
}
.band, section[id], .hero, .kopf, h2 {
  scroll-margin-top: var(--nav-offset);
}
.band h1 { font-size: clamp(1.9rem, 4.5vw, 2.9rem); }
.band .lead { max-width: var(--measure); color: rgba(255, 255, 255, .86); }
.band-schmal h3 {
  font-size: clamp(1.2rem, 2.6vw, 1.6rem);
  margin: 0;
}

.legal {
  padding-block: var(--space-8);
}
.legal > header { margin-bottom: var(--space-8); }
.legal > section {
  padding-block: var(--space-9) 0;
  border: 0;
}

/* Inhalt nach einer Ueberschrift ohne Vorspann: derselbe Abstand wie nach
   einem Vorspann, damit Rasterkanten nicht springen. */
h2 + .grid,
h2 + .werte,
h2 + .steps,
h2 + .prose,
h3 + .grid { margin-top: var(--space-3); }
.lead + .grid,
.lead + .werte,
.lead + .hero-actions,
.lead + .umschalter { margin-top: 0; }
.kennzahlen { margin-top: var(--space-6); }
.kennzahlen + .knopf-paar { margin-top: var(--space-7); }
.steps + p { margin-top: var(--space-7); }
.grid + .note,
.grid + .galerie { margin-top: var(--space-7); }
.werte + .prose { margin-top: var(--space-8); }
.prose .grid { margin-block: var(--space-6); }

.grid { gap: var(--space-5); }
.grid-2, .grid-3 { grid-template-columns: 1fr; }
@media (min-width: 40rem) {
  .grid-2 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 64rem) {
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
}
.grid-align { align-items: center; }

.card, .wert, .vergleich, .zaehlwerk, .soc, .jetzt-haupt {
  border-radius: var(--radius);
  box-shadow: none;
  background: var(--bg-elevated);
}
.card {
  border: 1px solid var(--line);
  padding: var(--space-6);
}
.card-lg { padding: var(--space-7); border-radius: var(--radius-lg); box-shadow: none; }
.card > :last-child,
.soc > :last-child { margin-bottom: 0; }
.card .ico { border-radius: var(--radius); }
.card-center { margin-inline: auto; }
.cta { text-align: center; }
.cta h2 { margin-bottom: var(--space-4); }
.cta .lead { margin-inline: auto; max-width: 32rem; margin-bottom: var(--space-6); }
kbd { border-radius: var(--radius-sm); }

.wert:hover, .vergleich:hover, .card:hover {
  transform: none;
  box-shadow: none;
}
.wert:hover, .vergleich:hover { border-color: var(--accent); }

/* Bilder behalten ihre runde Einfassung -- ausdruecklich gewuenscht
   (18.09.2026). Die Werkstatt-Kante gilt fuer Flaechen, die Text tragen;
   ein Foto ist keine solche Flaeche. Bildkoepfe, Standbilder und die
   Lupe tragen dieselbe Einfassung. */
.galerie { gap: var(--space-5); margin-top: var(--space-7); }
.galerie img { border-radius: var(--radius-bild); }

.band {
  border-radius: var(--radius-bild);
  width: var(--page);
  margin-inline: auto;
  margin-block: var(--space-5);
}
.band > video,
.band > img.standbild {
  border-radius: inherit;
}

/* Bildkopf der Anlagenseite: eine Bildschirmhoehe unter der Leiste.
   Die Ecke sitzt unten im Band; eine Scrollbewegung fuehrt in die Seite. */
.band.bildkopf {
  width: min(calc(100% - 2 * var(--gutter)), 80rem);
  min-height: calc(100vh - var(--nav-offset) - var(--space-5));
  min-height: calc(100svh - var(--nav-offset) - var(--space-5));
  height: calc(100vh - var(--nav-offset) - var(--space-5));
  height: calc(100svh - var(--nav-offset) - var(--space-5));
  margin-block: 0 var(--space-5);
  display: grid;
  align-items: stretch;
}
.band.bildkopf .zoom-halt > .page,
.band.bildkopf > .page {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: min(100%, var(--page));
  margin-inline: auto;
  padding-block: var(--space-6) 7.5rem;
  padding-inline: var(--gutter);
  min-height: 0;
  box-sizing: border-box;
}

/* Am Schreibtisch duerfen sie unterschiedlich gross sein: drei Spalten, aber
   nicht drei gleiche Kaesten. Die Hochkant-Aufnahme setzt tiefer an, die
   uebrigen wechseln ihr Format. Am Telefon bleibt alles einspaltig und
   gleich hoch -- dort ist Ruhe wichtiger als Abwechslung. */
@media (min-width: 64rem) {
  .galerie {
    grid-template-columns: repeat(3, 1fr);
    align-items: start;
  }
  .galerie figure:not(.hoch):nth-child(3n+2) img { aspect-ratio: 1 / 1; }
  .galerie figure:not(.hoch):nth-child(3n)   img { aspect-ratio: 5 / 4; }
  .galerie figure.hoch { margin-top: var(--space-6); }

  /* Das Zoom-Band ist ausgenommen: diese Regel gab ihm ab 64 rem wieder eine
     feste, niedrige Hoehe -- damit war seine Haltestrecke weg, lauf = 0, und
     bahn() blieb bei q = 0. Die Bewegung fand nicht statt, ohne dass irgendwo
     ein Fehler stand. Auf dem Telefon lief sie, auf dem iPad nicht, weil
     Safari dort in der Voreinstellung die breite Darstellung meldet (gemeldet
     19.09.2026). Die drei :not() wiegen zusammen mehr als `.js .band-zoom`,
     deshalb half auch die spaetere Regel nicht. */
  .band:not(.band-schmal):not(.bildkopf):not(.band-zoom) {
    width: min(64rem, calc(100% - 3rem));
    min-height: clamp(22rem, 48vh, 32rem);
  }
  /* Randlos, und das ist der Punkt: der Zoom lebt davon, dass die Schrift
     ueber die Kanten hinauswaechst. In einem eingerueckten Kasten waere
     dasselbe nur ein Ausschnitt -- die Schrift stiesse an eine innere Kante,
     und statt hindurchzufahren schaute man durch ein Fenster zu. Deshalb hier
     bewusst anders als die uebrigen Baender. */
  .js .band.band-zoom {
    width: auto;
    min-height: 200svh;
  }
  .band-schmal {
    width: min(52rem, calc(100% - 8rem));
    min-height: clamp(13rem, 26vh, 18rem);
  }
}

/* ---------- Schaltflaechen und Typenschild-Teile ------------------------- */

.btn, .knopf-live {
  border-radius: var(--radius-sm);
  font-weight: 600;
  letter-spacing: .01em;
  min-height: var(--tap);
  padding-block: .7rem;
}
.btn-primary { background: var(--accent); }
.btn-primary:hover { background: var(--accent-hover); box-shadow: none; }
.knopf-live { box-shadow: none; min-height: var(--tap); }
.knopf-live:hover { transform: none; background: rgba(10, 12, 16, .82); }

.copy {
  border-radius: var(--radius-sm);
  margin-block: var(--space-4) var(--space-3);
}
.copy button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  padding: .5rem 1rem;
  border-radius: var(--radius-sm);
}
.umschalter {
  border-radius: var(--radius);
  margin-top: 0;
}
.umschalter button {
  min-height: var(--tap);
  border-radius: var(--radius-sm);
  padding: .5rem 1rem;
}
.lupe { border-radius: var(--radius-bild); box-shadow: none; }
.lupe-zu {
  width: var(--tap);
  height: var(--tap);
  border-radius: var(--radius-sm);
}

.zaehlwerk {
  border-left: 3px solid var(--accent);
  background: var(--bg-elevated);
  margin-block: var(--space-6);
}
.zaehlwerk-kopf { letter-spacing: .14em; }

.mark { border-radius: var(--radius); }
.mark::before, .mark::after { border-radius: 0; }

.steps li::before { border-radius: var(--radius-sm); }
.soc-balken, .mix-balken { border-radius: var(--radius-sm); }

.nav { border-bottom: 1px solid var(--line); }

/* Weggeschoben statt ausgeblendet: eine Leiste, die verblasst, laesst den
   Text darunter durchscheinen; eine, die hochfaehrt, ist einfach weg. Nur
   transform, damit nichts neu umbricht. Ohne Skript (und bei reduzierter
   Bewegung) bleibt sie stehen -- die Klasse wird dann nie gesetzt. */
.nav { transition: transform .32s var(--ease, ease); will-change: transform; }
.nav.ist-weg { transform: translate3d(0, -100%, 0); }
@media (prefers-reduced-motion: reduce) {
  .nav { transition: none; }
  .nav.ist-weg { transform: none; }
}
.nav-inner {
  width: var(--page);
  min-height: 3.25rem;
  height: auto;
  gap: var(--space-6);
}
.nav-links {
  display: flex;
  align-items: center;
  gap: var(--space-5);
}
.nav-links a,
.nav-anmelden {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  white-space: nowrap;
}
.nav a:not(.brand)::after { bottom: .7rem; }

.footer { padding-block: var(--space-7); }
.footer .page { padding-block: 0; }
.footer a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
}

dl.facts.facts-compact div {
  grid-template-columns: 9.5rem 1fr;
  padding-block: var(--space-3);
}
.gruppe > .small { max-width: var(--measure); }
.jahr + p,
.balken-beschriftung + p { margin-top: var(--space-6); }
.reihe h3 {
  font-size: 1rem;
  margin-bottom: var(--space-4);
}

.jetzt-haupt { margin-top: 0; padding: var(--space-6); }
.gruppe { margin-top: var(--space-8); }
.jahr { margin-top: var(--space-7); }
.stand { margin-top: var(--space-5); }
.vorlauf-hinweis { margin-top: var(--space-5); max-width: var(--measure); }
.erzeugung .lead + .werte,
.bhkw .lead + .werte { margin-top: 0; }

/* ---------- Bewegung: eine Kurve, gestaffelt, ohne Sprung ---------------- */

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* Video und Ecke nicht mit den Abschnittskindern verstecken: das Band
   wuerde sonst beim Einblenden springen. */
.js main > section > video,
.js main > section > .ecke,
.js main > section > .page,
.js main > header > *,
.js .kopf,
.js .kopf > *,
.js [data-hero] .hero-heading {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}
.js main > section .reveal,
.js main > header .reveal {
  opacity: 0;
  transform: translate3d(0, .5rem, 0);
  transition:
    opacity var(--duration) var(--ease),
    transform var(--duration) var(--ease);
  transition-delay: calc(var(--stagger) * var(--delay, 0));
}
.js .reveal.is-visible { opacity: 1; transform: none; }
.js [data-delay="1"],
.js [data-delay="2"],
.js [data-delay="3"],
.js [data-delay="4"],
.js [data-delay="5"] {
  transition-delay: calc(var(--stagger) * var(--delay, 0));
}

.card,
.vergleich,
.btn,
.knopf-live,
.copy,
.copy button,
.nav a:not(.brand)::after,
.nav .brand .mark,
.btn-primary::before,
.steps li::before,
.link-arrow::after,
.proj-chevron,
.nav {
  transition-timing-function: var(--ease);
}
.card { transition: border-color .25s var(--ease); }
.card:hover .ico { transform: none; }
.btn-primary::before { display: none; }
.hero::before {
  inset: -20% 0 auto;
  background:
    radial-gradient(46% 54% at 12% 28%, color-mix(in oklab, var(--accent) 16%, transparent), transparent 72%);
  opacity: .42;
  animation: drift 28s var(--ease) infinite alternate;
  filter: blur(28px);
}
.hero.kopf::before {
  content: none;
  display: none;
  animation: none;
}
.ecke { transition: opacity .6s var(--ease), transform .6s var(--ease); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js .reveal,
  .js main > section > *,
  .js main > header > *,
  .js main > section > .grid > *,
  .js main .steps > li {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .hero::before { animation: none; }
  [data-hero] {
    --hero-scale: 1;
    --hero-spread: 0;
  }
  [data-zoom] {
    min-height: 0;
    padding-block: var(--section) 0;
  }
  [data-zoom] .zoom-halt {
    position: static;
    min-height: 0;
    padding-block: 0;
    display: block;
    overflow: visible;
  }
  /* Ohne html.js greifen die Regeln, die den Film in der Halteschicht
     festhalten, nicht. Der Film steht dann im Fluss: am Schreibtisch eine
     schmale Spalte links und rechts daneben Schwarz, der Text erst weit
     unter dem Bild. Hier wird das Band wieder ein gewoehnliches Band --
     eine Hoehe, Film deckt, Schrift und Text liegen darauf, beides sichtbar. */
  .band.band-zoom {
    min-height: 0;
  }
  .band-zoom .zoom-halt {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    min-height: clamp(22rem, 48vh, 32rem);
    display: grid;
    align-items: center;
    background: #0b0d10;
  }
  .band-zoom .zoom-halt > video,
  .band-zoom .zoom-halt > img.standbild {
    position: absolute;
    inset: 0;
    z-index: -2;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 42%;
  }
  .band-zoom::after { content: none; }
  .band-zoom .zoom-halt::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background:
      linear-gradient(180deg, rgba(4,6,9,.62) 0%, rgba(4,6,9,.46) 45%, rgba(4,6,9,.74) 100%);
  }
  .band-zoom .zoom-schrift h2 {
    hyphens: auto;
    overflow-wrap: break-word;
  }
  /* Die Ecke sitzt absolut am Boden. Schrift und Text stehen im ruhigen
     Zustand untereinander, nicht uebereinander -- ohne diesen Abstand
     laeuft der zweite Knopf in die Livedaten. */
  .band-zoom .zoom-halt:has(.ecke) > .page {
    padding-bottom: 6rem;
  }
  [data-zoom] .zoom-schrift,
  [data-zoom] .zoom-rest {
    transform: none;
    opacity: 1;
    pointer-events: auto;
  }
  [data-zoom] .zoom-rest { margin-top: var(--space-5); }
  [data-zoom] .hero-cluster,
  [data-zoom] .eyebrow,
  [data-zoom] .lead,
  [data-zoom] .hero-actions {
    transform: none;
    opacity: 1;
  }
  [data-hero] .hero-heading {
    font-size: clamp(2.25rem, 7vw, 4rem);
  }
  .hero-cluster,
  .hero-line {
    transform: none;
    will-change: auto;
  }
}

/* ---------- Handy zuerst ------------------------------------------------- */

@media (max-width: 40rem) {
  .hero-actions,
  .knopf-paar {
    flex-direction: column;
    align-items: stretch;
  }
  .hero-actions .btn,
  .knopf-paar .btn,
  .knopf-paar .knopf-live,
  .cta .btn {
    justify-content: center;
    width: 100%;
  }
  .copy {
    flex-direction: column;
    align-items: stretch;
  }
  .copy code {
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .copy button { width: 100%; }
  .umschalter { width: 100%; }
  .umschalter button { flex: 1; }
  h1 { line-height: 1.1; }
  h1, h2 {
    hyphens: auto;
    overflow-wrap: break-word;
  }
  dl.facts div,
  dl.facts.facts-compact div { grid-template-columns: 1fr; }
  .band:has(.ecke) > .page {
    padding-bottom: 7rem;
  }
  /* Vollformat unter der Leiste, ohne seitlichen Rahmen: das Video
     soll den Schirm fuellen. Andere Baender behalten die Einfassung. */
  .band.bildkopf {
    width: 100%;
    border-radius: 0;
    margin: 0;
    min-height: calc(100vh - var(--nav-offset));
    min-height: calc(100svh - var(--nav-offset));
    height: calc(100vh - var(--nav-offset));
    height: calc(100svh - var(--nav-offset));
  }
  .band.bildkopf .zoom-halt > .page,
  .band.bildkopf > .page {
    padding-bottom: 7.5rem;
  }
}

.nav-links { flex-wrap: nowrap; }

@media (max-width: 56rem) {
  :root { --nav-offset: 7rem; }
  .nav-inner {
    flex-wrap: wrap;
    gap: 0;
    padding-block: var(--space-1) 0;
    height: auto;
  }
  /* The way into the portal shares the first row with the wordmark. It used
     to sit at the end of the scrolling link row, where the phone cut it off:
     the one link a customer actually comes for was the one behind the fade. */
  .nav .brand {
    width: auto;
    margin-right: auto;
    min-height: var(--tap);
    order: 1;
  }
  .nav-anmelden {
    order: 2;
    color: var(--fg);
    padding-left: var(--space-2);
  }
  .nav-links { order: 3; }
  .nav-links {
    width: 100%;
    min-width: 0;
    max-width: 100%;
    /* space-2 + a 20 px fade cut "Dokumentation" to "Dokumentatio" at
       390 px (360 px scroll in a 350 px row). The row is sticky: what
       the fade hid was not just clipped, it was behind a hold layer. */
    gap: var(--space-1);
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .nav-links::-webkit-scrollbar { display: none; }
  .nav-links a { flex: none; padding-inline: .15rem; }
  .band, section[id], .hero, .kopf, h2 { scroll-margin-top: var(--nav-offset); }
}

/* ---------- Zoom on the plant page --------------------------------------- */
/*
   Decision: the plant page gets the same fly-through as the start page.
   This is the film of this plant, and the short title is the thing you
   enter through. Direct visits never saw the start-page zoom.

   The live corner must not grow. It sits in .zoom-halt as a sibling of
   the type, never inside .zoom-schrift (that wrapper is the one that
   scale()s). Transform is not inherited; a rule that sets transform on
   .ecke would also kill its own wechsel animation.

   Film and overlay live on .zoom-halt, not on the section: otherwise
   they stretch over the two-screen track. These cover rules are not
   gated on .js, so prefers-reduced-motion (no html.js) and a missing
   script still show a covering film with type and text on top.
*/
.band.bildkopf[data-zoom] {
  display: block;
  height: auto;
  min-height: calc(100vh - var(--nav-offset) - var(--space-5));
  min-height: calc(100svh - var(--nav-offset) - var(--space-5));
}
.band.bildkopf[data-zoom] .zoom-halt {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: calc(100vh - var(--nav-offset) - var(--space-5));
  min-height: calc(100svh - var(--nav-offset) - var(--space-5));
  display: grid;
  align-items: center;
  background: #0b0d10;
  border-radius: inherit;
}
.band.bildkopf[data-zoom] .zoom-halt > video,
.band.bildkopf[data-zoom] .zoom-halt > img.standbild {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 42%;
}
.band.bildkopf[data-zoom]::after { content: none; }
.band.bildkopf[data-zoom] .zoom-halt::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(180deg, rgba(4,6,9,.62) 0%, rgba(4,6,9,.46) 45%, rgba(4,6,9,.74) 100%);
}

.js .band.bildkopf[data-zoom] {
  min-height: 200svh;
  overflow: visible;
  background: none;
}
.js .band.bildkopf[data-zoom] .zoom-halt {
  position: sticky;
  /* Match the bar, not --nav-offset (4.75rem vs 3.25rem): a cream strip
     between bar and film during the hold looks like a hole. */
  top: 3.25rem;
  min-height: calc(100svh - 3.25rem - var(--space-5));
  /* Growing type is clipped here, not on the track -- sticky would die. */
  overflow: hidden;
}
.js .band.bildkopf[data-zoom] .zoom-halt > .page {
  display: grid;
  align-content: center;
}
.js .band.bildkopf[data-zoom] .zoom-schrift,
.js .band.bildkopf[data-zoom] .zoom-rest {
  grid-area: 1 / 1;
  width: 100%;
}
.js .band.bildkopf[data-zoom] .hero-heading {
  font-size: clamp(2.6rem, 12.5vw, 7rem);
  line-height: 1.02;
  margin-bottom: 0;
  text-wrap: balance;
  color: #fff;
}
.js .band.bildkopf[data-zoom] .zoom-halt::after {
  /* Same as the start-page band: the grade lets go as the type flies
     through, but never fully -- the live corner stays on it. */
  opacity: calc(.45 + var(--hero-op, 1) * .55);
}

@media (max-width: 40rem) {
  .band.bildkopf[data-zoom],
  .band.bildkopf[data-zoom] .zoom-halt {
    /* Two tap-rows plus the wrap padding, not --nav-offset (7rem):
       7rem is scroll-margin. Using it as height leaves a cream strip
       under the bar and another at the bottom of the film. */
    min-height: calc(100vh - 2 * var(--tap) - var(--space-1));
    min-height: calc(100svh - 2 * var(--tap) - var(--space-1));
    border-radius: 0;
  }
  .js .band.bildkopf[data-zoom] {
    min-height: 200svh;
  }
  /* Lead + button + corner must fit the sticky layer at 390x844.
     Leaving something out would be the worse answer. */
  .band.bildkopf[data-zoom] .zoom-rest .lead {
    font-size: .9375rem;
    line-height: 1.5;
  }
  .band.bildkopf[data-zoom] .zoom-rest .knopf-zeile {
    margin-top: var(--space-4);
  }
  .js .band.bildkopf[data-zoom] .zoom-halt > .page {
    padding-block: var(--space-4) 7.5rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* No hold, no fly-through. Halt is one remaining viewport; type and
     text stack; the corner sits on the film at 1:1. */
  .band.bildkopf[data-zoom] {
    min-height: 0;
    padding-block: 0;
  }
  .band.bildkopf[data-zoom] .zoom-halt {
    position: relative;
    min-height: calc(100vh - var(--nav-offset) - var(--space-5));
    min-height: calc(100svh - var(--nav-offset) - var(--space-5));
    display: grid;
    align-items: center;
    overflow: hidden;
  }
  .band.bildkopf[data-zoom] .zoom-halt:has(.ecke) > .page {
    padding-bottom: 7.5rem;
  }
}

@media (prefers-reduced-motion: reduce) and (max-width: 40rem) {
  .band.bildkopf[data-zoom] .zoom-halt {
    min-height: calc(100vh - 2 * var(--tap) - var(--space-1));
    min-height: calc(100svh - 2 * var(--tap) - var(--space-1));
  }
}

@media (max-width: 56rem) {
  .js .band.bildkopf[data-zoom] .zoom-halt {
    top: calc(2 * var(--tap) + var(--space-1));
    min-height: calc(100svh - 2 * var(--tap) - var(--space-1));
  }
}
