/* ============================================================================
   Gemeinsames Aussehen aller Kunden-Vorlagen.

   Bewusst OHNE Canvas-Effekte: die gehoeren zur Portfolioseite und waeren fuer
   eine Arztpraxis fehl am Platz. Hier zaehlt Ruhe, Lesbarkeit und dass der
   Besucher schnell findet, was er sucht.

   Farben kommen aus CSS-Variablen. Das Adminpanel setzt --accent ueber
   site.config.json -> design.akzent; alles andere folgt daraus.
   ========================================================================= */

:root{
  --bg:#EFF2ED;
  --bg-warm:#E7EBE1;
  --surface:#FBFAF7;
  --ink:#1F3B33;
  --sub:#5A6E66;
  --accent:#C98F65;
  --line:rgba(31,59,51,0.14);
  --gutter:32px;
  --ecken:0px;

  /* Zweite Zierfarbe - fuer Verlaeufe, Schriftzuege und alles, was aus einer
     Farbe in eine andere laeuft. OHNE eigene Angabe ist sie die Zierfarbe
     selbst; ein Verlauf von Rot nach Rot ist einfach eine rote Flaeche.
     Deshalb muss kein Bauteil zwei Faelle kennen: es rechnet immer mit
     --accent-2 und bekommt ohne Zutun das Richtige. */
  --accent-2:var(--akzent-zwei, var(--accent));

  /* --- Farbe des Nebels ---
     Zwei Toene, beide einstellbar (design.nebelTon, design.nebelKernTon).
     Ohne Angabe folgt der Nebel der Zierfarbe - eine Seite, deren Rauch eine
     andere Farbe hat als ihr Licht, sieht nach Versehen aus.

     Der KERN ist die hellere Mitte einer Schwade. Er ist der Grund, warum
     Rauch nach beleuchtetem Rauch aussieht und nicht nach eingefaerbter
     Watte - aber er ist auch die Stelle, an der es schnell milchig wird.
     Deshalb nur 18 % Weiss in der Vorgabe und ein eigener Regler daneben:
     wer es rauchiger will, dreht ihn zur Zierfarbe hin.

     Die Deckkraft steckt hier drin und nicht in der Farbe selbst: der
     Farbwaehler im Panel liefert nur einen Farbwert ohne Durchsichtigkeit. */
  --nebel-farbe:color-mix(in srgb, var(--nebel-ton, var(--accent)) 60%, transparent);
  --nebel-kern:color-mix(in srgb,
    var(--nebel-kern-ton, color-mix(in srgb, var(--nebel-ton, var(--accent)) 82%, #fff))
    45%, transparent);

  /* Wie stark alles leuchtet, als FAKTOR (0 = gar nicht, 1 = wie entworfen).
     Gesetzt vom Loader aus design.leuchtkraft. Jede Schein-Regel multipliziert
     ihre eigene Deckkraft damit - so bleibt das Verhaeltnis der Bauteile
     zueinander erhalten, egal wie hell es insgesamt gedreht wird. */
  --leuchtkraft:1;

  /* Schriften. Der Loader ueberschreibt diese Werte, wenn im Adminpanel eine
     Schrift aus shared/fonts/ gewaehlt wurde - sonst gilt genau das, was hier
     steht. Die Ersatzangaben dahinter greifen, solange die Schriftdatei noch
     laedt oder fehlt; die Seite ist damit nie ohne Schrift. */
  --schrift-text:'Public Sans', system-ui, sans-serif;
  --schrift-ueberschrift:'Fraunces', Georgia, serif;
  --schrift-mono:'IBM Plex Mono', ui-monospace, monospace;

  /* Leuchtender Rand. Im Hellen ein normaler Schatten, im Dunklen der Schein
     um eine Kante herum. Steht hier und nicht in site.css, weil Karten,
     Knoepfe und Bilder ihn gemeinsam benutzen sollen - eine Website, in der
     jedes Bauteil anders leuchtet, sieht nicht nach einer Website aus. */
  --leuchten:0 6px 20px rgba(31,59,51,.08);
  --fehler:#B4472F;
}

/* ---------------------------------------------------------------------------
   Dunkle Fassung.

   Gesetzt wird sie als Attribut am <html> durch erscheinung() im loader.js,
   Quelle ist site.config.json -> design.helligkeit.

   WARUM EIN ZWEITER TOKENSATZ UND NICHT EINE DUNKLE ZIERFARBE:
   Eine helle Seite mit dunkler Zierfarbe ist keine dunkle Seite. Umgekehrt
   muesste jede dunkle Vorlage sonst ein Dutzend Variablen einzeln neu setzen -
   und die naechste wieder, mit leicht anderen Werten. Dann leuchtet jede Seite
   anders und keine sieht gewollt aus.

   Es sind dieselben Variablennamen wie oben. Kein einziges Bauteil weiter
   unten in dieser Datei muss davon wissen; wer hier neue Regeln schreibt,
   nimmt einfach var(--bg) und bekommt beides geschenkt.

   Die Zierfarbe (--accent) steht bewusst NICHT hier: sie kommt aus dem
   Adminpanel und ist die eine Farbe, die der Betreiber selbst waehlt.
   --------------------------------------------------------------------------- */
:root[data-helligkeit="dunkel"]{
  /* Der Grundton ist einstellbar (design.grund) - nicht jede dunkle Seite ist
     schwarz, manche ist tiefblau oder braun. Ohne Angabe bleibt es beim
     bisherigen Fast-Schwarz. */
  --bg:var(--grund, #0B0B0E);
  /* Nur eine Spur heller als --bg. Zwei deutlich verschiedene Dunkeltoene
     lesen sich als Fehler, nicht als Gliederung.
     AUS --bg gerechnet, nicht danebengeschrieben: sonst bliebe die Seite
     grau, sobald jemand den Grundton auf Blau stellt. */
  --bg-warm:color-mix(in srgb, var(--bg) 96%, #fff);
  --surface:color-mix(in srgb, var(--bg) 93%, #fff);
  --ink:#F2F0EF;
  --sub:#A8A4A6;
  --line:rgba(255,255,255,0.13);
  --leuchten:0 0 26px rgba(0,0,0,.55);
  --fehler:#FF8A6E;
}

/* Bilder und Videos wirken auf schwarzem Grund heller als sie sind - das
   Auge hat keinen hellen Bezugspunkt mehr. Eine Spur zurueckgenommen sitzen
   sie ruhiger in der Seite. */
:root[data-helligkeit="dunkel"] img,
:root[data-helligkeit="dunkel"] video{filter:brightness(.94);}

*{box-sizing:border-box; margin:0; padding:0;}
html{
  scroll-behavior:smooth;
  /* BEIM SPRINGEN OBEN PLATZ LASSEN FUER DIE MITLAUFENDE KOPFZEILE.
     Ohne das schiebt der Browser die Oberkante des Ziels an die Oberkante des
     Fensters, und dort steht die Kopfzeile: Beschriftung und Ueberschrift des
     Abschnitts liegen dahinter. Die 14 Pixel obendrauf sind Luft, damit das
     Ziel nicht auf Kante klebt.

     Die Hoehe misst ui.js (kopfPlatz) und schreibt sie nach --kopfhoehe. Sie
     steht auf 0, sobald der Kopf nicht mehr klebt - dann verdeckt er nichts,
     und ein freigehaltener Streifen waere eine Luecke. Der Ausweichwert gilt
     nur fuer die Zeitspanne vor der ersten Messung. */
  scroll-padding-top:calc(var(--kopfhoehe, 76px) + 14px);
}
/* ---------- Der Ladeschirm ----------

   Zwischen "HTML ist da" und "loader.js hat die Abschnitte gefuellt" steht in
   der Seite nur das Geruest: Ueberschriften ohne Inhalt, leere Kaesten,
   Platzhalter. Beim Neuladen war das einen Wimpernschlag lang zu sehen.

   Ein Versuch, nur "main" zu verbergen, reichte nicht: Kopf, Fuss und die
   leeren Baender blieben sichtbar, und man sah weiterhin eine halbfertige
   Seite. Jetzt deckt ein Schirm ALLES ab, und darauf steht das Zeichen der
   Marke - dieselbe Ansicht, mit der die Seite gleich anfaengt, statt eines
   Zwischenzustands.

   Der Schirm steht fest im HTML und nicht in JavaScript: er soll genau in
   der Zeitspanne da sein, in der JavaScript noch nicht gelaufen ist.

   DIE SELBSTBEFREIUNG IST DER WICHTIGE TEIL: die Animation blendet ihn nach
   1,8 Sekunden auch dann weg, wenn "bereit" nie kommt - bei einem Fehler im
   Ladeweg, abgeschaltetem JavaScript oder einer content.json, die nicht
   antwortet. Ein Schirm, der in diesen Faellen liegenbliebe, waere eine
   Seite, die es gar nicht mehr gibt. */
.ladeschirm{
  position:fixed; inset:0; z-index:9999;
  display:grid; place-items:center;
  background:var(--bg);
  animation:ladeschirmWeg .45s ease 1.8s both;
}
.ladeschirm img{
  width:clamp(84px, 12vw, 150px); height:auto;
  /* Ein ruhiges Atmen. Kein Kreisel: das Zeichen IST die Marke, und ein
     rotierendes Logo sieht aus wie ein Fehler, der behoben wird. */
  animation:ladeschirmAtem 1.6s ease-in-out infinite;
}
/* Fertig - der Schirm geht weg.
   NICHT ueber dieselbe Animation: eine laufende Animation wird nicht neu
   gestartet, nur weil sich Dauer oder Verzoegerung aendern - der Schirm blieb
   dadurch stehen, obwohl "bereit" gesetzt war. Und ein Ausblenden, das an
   einer Animation haengt, bleibt haengen, sobald der Browser Animationen
   anhaelt (Hintergrundtab, Sparmodus).

   Deshalb hier ein schlichter Endzustand mit Ueberblendung. Faellt auch die
   aus, ist der Schirm eben sofort weg - das ist der harmlose Fall.
   visibility wird verzoegert geschaltet, damit die Ueberblendung noch zu
   sehen ist, bevor das Element aus dem Weg geht. */
:root.bereit .ladeschirm{
  animation:none;
  opacity:0; visibility:hidden;
  transition:opacity .3s ease, visibility 0s linear .3s;
}
@keyframes ladeschirmWeg{
  to{ opacity:0; visibility:hidden; }
}
@keyframes ladeschirmAtem{
  0%,100%{ opacity:.55; transform:scale(.97); }
  50%    { opacity:1;   transform:scale(1);   }
}
@media(prefers-reduced-motion: reduce){
  .ladeschirm img{ animation:none; }
  .ladeschirm{ animation-duration:.01s; }
}

body{
  background:var(--bg); color:var(--ink);
  font-family:var(--schrift-text);
  line-height:1.65; -webkit-font-smoothing:antialiased;
}
h1,h2,h3{font-family:var(--schrift-ueberschrift); font-weight:500; letter-spacing:-0.01em;}
a{color:inherit;}
img,video{max-width:100%;}

@media (prefers-reduced-motion: reduce){
  *{animation-duration:.001ms !important; transition-duration:.001ms !important;}
}
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible{
  outline:3px solid var(--accent); outline-offset:3px;
}

/* Icons aus sections.js. Die Groesse haengt an der Schriftgroesse ihrer
   Umgebung, nicht an einer festen Pixelzahl: ein Icon neben einer Ueberschrift
   soll mitwachsen, eines in der Fusszeile klein bleiben.
   vertical-align statt flex, damit es auch mitten im Fliesstext sitzen kann. */
.icon{width:1.35em; height:1.35em; vertical-align:-.28em; flex:none;}

.wrap{max-width:1120px; margin:0 auto; padding:0 var(--gutter);}
.mono{
  font-family:var(--schrift-mono); font-size:.78rem;
  letter-spacing:.06em; text-transform:uppercase; color:var(--accent);
  display:block; margin-bottom:14px;
}

/* Sanftes Einblenden beim Scrollen - dieselbe Klasse wie im Portfolio,
   damit loader.js nur einen Mechanismus kennt. */
.dg{opacity:0; transform:translateY(12px);
    transition:opacity .5s ease, transform .6s cubic-bezier(.2,.7,.3,1);}
.dg.in{opacity:1; transform:none;}
.dg-1{transition-delay:.06s;} .dg-2{transition-delay:.13s;}
.dg-3{transition-delay:.2s;}  .dg-4{transition-delay:.27s;}

/* ---------- Kopfzeile ---------- */
header{
  position:sticky; top:0; z-index:50;
  background:color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter:blur(10px); border-bottom:1px solid var(--line);
}
/* Verhalten der Kopfzeile - gesetzt vom Loader aus site.config.json.
   Vorgabe ist "mitlaufend", also genau das bisherige Verhalten. */
:root[data-kopf="normal"] header{position:relative; z-index:50;}
/* relative statt static: ohne Versatz sieht es genauso aus, verschafft
   dem Kopf aber eine eigene Ebene ueber den Zeichenflaechen. Mit static
   greift z-index nicht, und der Kopf verschwaende hinter dem Nebel. */
:root[data-kopf="versteckend"] header{transition:transform .28s ease;}
:root[data-kopf="versteckend"] header.weg{transform:translateY(-100%);}
@media (prefers-reduced-motion: reduce){
  :root[data-kopf="versteckend"] header{transition:none;}
}
/* "fest"       immer sichtbar, die Seite endet DARUEBER - es wird nichts
                dahinter gerendert. Die Hoehe misst ui.js als --fusshoehe.
   "mitlaufend" klebt am unteren Rand, der Inhalt scrollt dahinter durch. */
:root[data-fuss="mitlaufend"] footer{position:sticky; bottom:0; z-index:45;}
:root[data-fuss="fest"] footer{
  position:fixed; left:0; right:0; bottom:0; z-index:45;
  background:color-mix(in srgb, var(--bg) 94%, transparent);
  backdrop-filter:blur(12px);
  border-top:1px solid var(--line);
}
body{padding-bottom:var(--fusshoehe, 0px);}

.nav{display:flex; align-items:center; justify-content:space-between; gap:20px; padding:16px 0;}
.marke{font-family:var(--schrift-ueberschrift); font-size:1.08rem; font-weight:600;}

/* Dachmarke oben, eigener Name klein darunter (loader.js, logo()).
   Der kleine Name traegt die Zierfarbe der Seite - das ist auf einen Blick
   der Unterschied zwischen den acht Unterseiten, deren Kopf sonst identisch
   waere. Enge Zeilen, damit die beiden ein Block bleiben und nicht wie zwei
   getrennte Angaben aussehen. */
/* Die Spalte ist nur so breit wie ihr breitestes Kind - der Schriftzug.
   align-items:flex-end schiebt den kleinen Namen dann an dessen RECHTE
   Kante. Ohne "width:max-content" waere die Spalte so breit wie der ganze
   Kopf, und "rechtsbuendig" hiesse "am Fensterrand". */
.marke-namen{
  display:flex; flex-direction:column; align-items:flex-end;
  width:max-content; max-width:100%; line-height:1.05; min-width:0;
}
.marke-namen .marke{font-size:1.02rem;}
/* Der Schriftzug als Bild. Die Hoehe richtet sich nach der Schriftgroesse,
   die er ersetzt - so bleibt der Kopf gleich hoch, egal ob dort Schrift oder
   Zeichnung steht. */
.marke-bild{display:block; height:1.15em; width:auto;}
.marke-unter{
  font-family:var(--schrift-mono); font-size:.6rem; letter-spacing:.2em;
  text-transform:uppercase; color:var(--accent); margin-top:4px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
@media(max-width:560px){ .marke-unter{display:none;} }

/* --- Der Markenname im Kopf mit wanderndem Verlauf (design.markeVerlauf) ---

   Die Farben sind NICHT erfunden: es sind die fuenf Stufen aus dem
   Schriftzug-SVG der Dachmarke (nachtundtag_Nmae_color_gradient_v4.svg),
   Violett ueber Magenta nach Orange. Damit steht im Kopf derselbe Verlauf wie
   auf dem Zeichen daneben - haette ich ihn nachempfunden, waeren es zwei
   aehnliche Verlaeufe, und der Unterschied faellt genau dann auf, wenn beide
   nebeneinanderstehen.

   Der Verlauf ist doppelt so breit wie die Schrift und wandert; sichtbar ist
   immer nur ein Ausschnitt. Deshalb wirkt es wie Licht, das ueber den Namen
   laeuft, und nicht wie ein Farbwechsel.

   background-clip:text faerbt die Buchstabenform selbst. Die Schriftfarbe muss
   dafuer durchsichtig sein - sonst liegt sie deckend darueber.

   Als EIGENE Klasse und nicht an ".marke": die vier Kundenvorlagen haben einen
   ruhigen Namen im Kopf, und ein wanderndes Leuchten waere dort deplatziert. */
.marke-verlauf{
  background-image:linear-gradient(100deg,
    #8e2dff 0%, #c930ff 15%, #ff2aa8 25%, #ff3a43 35%, #ff5a1f 50%,
    #ff3a43 65%, #ff2aa8 75%, #c930ff 85%, #8e2dff 100%);
  background-size:200% 100%;
  -webkit-background-clip:text; background-clip:text;
  color:transparent; -webkit-text-fill-color:transparent;
  animation:markeVerlauf 9s linear infinite;
}
@keyframes markeVerlauf{
  from{ background-position:0% 50%; }
  to  { background-position:200% 50%; }
}
/* Wer "Bewegung reduzieren" eingestellt hat, bekommt den Verlauf - aber
   stehend. Die Farbe ist die Marke, die Bewegung nur Zierde. */
@media(prefers-reduced-motion: reduce){
  .marke-verlauf{ animation:none; background-position:25% 50%; }
}
.nav-links{display:flex; gap:24px; list-style:none; font-size:.88rem;}
.nav-links a{text-decoration:none; opacity:.75; position:relative; padding-bottom:5px;}
.nav-links a:hover{opacity:1; color:var(--accent);}
/* Der Abschnitt, in dem der Besucher gerade steht. Gesetzt beim Scrollen von
   mitlesen() im loader.js.
   Als eigener Strich unter dem Wort und nicht als text-decoration: der laesst
   sich anfahren (er waechst aus der Mitte) und liegt immer auf derselben
   Hoehe, egal ob das Wort Unterlaengen hat. */
.nav-links a.aktiv{opacity:1; color:var(--accent);}
.nav-links a::after{
  content:''; position:absolute; left:0; right:0; bottom:0; height:2px;
  background:currentColor; transform:scaleX(0); transform-origin:center;
  transition:transform .25s ease;
}
.nav-links a.aktiv::after{transform:scaleX(1);}
#mobileMenu a.aktiv{color:var(--accent);}
.nav-cta{
  text-decoration:none; font-size:.85rem; font-weight:600; white-space:nowrap;
  background:var(--ink); color:var(--bg); padding:10px 18px; border-radius:var(--ecken);
}
.nav-cta:hover{background:var(--accent);}
@media(max-width:820px){ .nav-links{display:none;} }

/* ---------- Startbereich ---------- */
.hero{padding:96px 0 72px; background:var(--bg-warm); border-bottom:1px solid var(--line);}
.hero h1{font-size:clamp(2rem,4.6vw,3.2rem); line-height:1.12; max-width:20ch; margin-bottom:20px;}
.hero h1 em{font-style:italic; color:var(--accent);}

/* Namenszug als Bild statt als Schrift (content/schriftzug/).
   Die Breite ist gedeckelt, nicht die Hoehe: ein Schriftzug ist ein breites,
   flaches Bild, und was er an Hoehe braucht, weiss nur er selbst. */
.hero-schriftzug{margin-bottom:20px;}
/* Jedes Bild sitzt in einem eigenen Kasten. Der Kasten bestimmt die Groesse,
   das Bild fuellt ihn aus - und der Kasten kann tragen, was ein <img> nicht
   tragen kann: ein ::after fuer den wandernden Verlauf (siehe unten). */
.hero-zeichen-bild{
  display:block; position:relative; line-height:0;
  width:100%; max-width:min(560px, 100%);
}
.hero-schriftzug img{display:block; width:100%; height:auto;}
.hero-sub{font-size:1.08rem; color:var(--sub); max-width:56ch; margin-bottom:30px;}
.hero-ctas{display:flex; gap:12px; flex-wrap:wrap;}

/* Zeilenumbrueche aus der Textdatei bleiben stehen.
   Wer im Adminpanel im Textfeld die Eingabetaste drueckt, meint einen
   Umbruch - HTML wirft ihn sonst weg und macht aus vier gesetzten Zeilen
   einen Fliesstext, der irgendwo umbricht. Mit pre-line entscheidet der
   Betreiber, wo die Zeile endet, ohne HTML zu kennen.

   pre-LINE und nicht pre: mehrfache Leerzeichen und Einzuege bleiben
   zusammengefasst, sonst zoege eine versehentlich eingerueckte Zeile die
   Einrueckung mit auf die Seite. */
.hero-sub{white-space:pre-line;}

/* --- Vollbildfoto hinter dem Startbereich ---
   Wird nur gebaut, wenn ein Bild da ist (sections.js). Der Startbereich
   behaelt seine Flaechenfarbe als Unterlage: laedt das Foto langsam oder gar
   nicht, steht der Text trotzdem nicht auf Weiss.

   Das Foto liegt VOLL BREIT, nicht im .wrap - deshalb ein eigener Kasten und
   nicht ein background-image am Startbereich: nur so lassen sich Verdunkelung
   und Nebel als eigene Schichten daruebersetzen, und nur so kann der Nebel
   sich bewegen, ohne das Foto mitzunehmen. */
.hero-mit-grund{position:relative; overflow:hidden;}
.hero-mit-grund .wrap{position:relative; z-index:2;}
/* Die ganze Hintergrundschicht - Foto, Verdunkelung und Nebel zusammen -
   loest sich nach unten auf.

   Vorher endete sie mit einer geraden Kante quer durch die Seite: der
   Startbereich hoerte auf, und darunter war schlagartig Schwarz. Die
   Verdunkelung allein reichte dagegen nicht, weil der Nebel VOR ihr liegt und
   sich davon nichts sagen laesst. Eine Maske ueber der ganzen Schicht wirkt
   dagegen auf alles darin, egal in welcher Reihenfolge es gezeichnet wird. */
.hero-grund{
  position:absolute; inset:0; z-index:0; pointer-events:none;
  -webkit-mask-image:linear-gradient(180deg, #000 0 62%, transparent 100%);
  mask-image:linear-gradient(180deg, #000 0 62%, transparent 100%);
}
.hero-foto{
  width:100%; height:100%; object-fit:cover; display:block;
  /* Eine Spur unscharf und weiter weg: das Foto ist Atmosphaere, nicht
     Inhalt. Scharf im Hintergrund konkurriert es mit dem Portrait davor. */
  filter:blur(2px) saturate(1.05); transform:scale(1.06);
}
/* Verdunkelung. Zwei Verlaeufe uebereinander:
   nach UNTEN, damit das Foto in die Seitenfarbe uebergeht statt an einer
   Kante abzureissen - und flaechig, damit die Schrift ueberall lesbar
   bleibt. --hero-dunkel kommt aus design.heroVerdunkeln. */
.hero-schleier{
  position:absolute; inset:0;
  background:
    /* Oben etwas dunkler, damit die Kopfzeile Halt hat. Nach UNTEN hin
       bewusst NICHTS mehr: das Ausklingen macht die Maske an .hero-grund.
       Stand hier zusaetzlich ein dunkler Verlauf, ergab das einen grauen
       Streifen kurz vor dem Ende - zwei Auflösungen uebereinander. */
    linear-gradient(180deg,
      color-mix(in srgb, var(--bg) 55%, transparent) 0%,
      transparent 26%),
    color-mix(in srgb, var(--bg) calc(var(--hero-dunkel, .55) * 100%), transparent);
}

/* --- Nebel ---
   Drei weiche Schwaden, jede eine einzige radiale Flaeche. Sie wandern
   langsam gegeneinander; wuerde nur EINE wandern, saehe man den Weg.
   Die Farbe kommt aus --nebel-farbe (site.css) - hier steht nur, wie gross
   die Schwaden sind und wohin sie ziehen. */
/* Das Feld, in dem die Schwaden liegen. Hier passieren die zwei Dinge, die
   aus weichen Flecken Rauch machen:

   1. RAUSCHMASKE. Ein Stueck SVG mit feTurbulence, direkt als Datenadresse
      eingebettet - keine Datei, kein Nachladen. Es loechert die Schwaden
      unregelmaessig, und weil die Maske langsam wandert, zieht das Muster
      durch den Rauch statt mit ihm mitzufahren. Genau das laesst es leben.

   2. KANTENSCHAERFUNG. blur() macht die Raender weich, contrast() zieht sie
      danach wieder zusammen. Aus zwei sich beruehrenden Flecken wird dabei
      EINE Form mit einer geschwungenen Taille - der Uebergang, den man von
      Flammen und Rauchzungen kennt. Ohne den zweiten Schritt bleiben es
      Kreise, die einander ueberlappen.

   Beides sitzt am FELD und nicht an den einzelnen Schwaden: sonst bekommt
   jede ihr eigenes Muster, und man sieht fuenf Scheiben statt einer Wand. */
.hero-nebel-lagen{position:absolute; inset:0; opacity:var(--nebel-staerke, .4);}

.hero-nebel-feld{
  position:absolute; inset:-10%;
  /* NUR Weichzeichnen. Hier stand zusaetzlich contrast(5.5), mit der
     Begruendung, es ziehe die Raender wieder zusammen - das war falsch.
     Der CSS-Filter contrast() rechnet ausschliesslich auf Rot, Gruen und
     Blau und ruehrt die Deckkraft NICHT an. Er konnte also nie Kanten
     formen; er hat nur die helleren Stellen des Rauchs ins gesaettigte Rot
     gedrueckt - und damit genau das Leuchten entfernt, an dem man Rauch
     ueberhaupt erkennt. Auf schwarzem Grund blieb fast nichts uebrig.
     Die Kanten macht jetzt die Maske, dort wo die Deckkraft wohnt. */
  filter:blur(8px);

  /* Nur die Rauschmaske. Das Ausklingen nach unten macht die Maske an
     .hero-grund - sie liegt ueber der ganzen Schicht und wirkt damit auch
     auf den Nebel. Hier stand kurz eine zweite Maskenebene dafuer; sie tat
     dasselbe ein zweites Mal, und der Nebel loeste sich dadurch doppelt so
     schnell auf wie das Foto darunter. */
  -webkit-mask-image:var(--rauschen);
  mask-image:var(--rauschen);
  -webkit-mask-size:var(--masche) var(--masche);
  mask-size:var(--masche) var(--masche);
  -webkit-mask-repeat:repeat;
  mask-repeat:repeat;
}

/* Die Rauschbilder. Jedes ist ein Stueck SVG als Datenadresse - zusammen
   keine 700 Zeichen, also weniger als eine einzige Zeile eines Fotos. Eine
   Bilddatei waere hier nicht nur groesser, sondern auch schlechter: eine
   PNG-Kachel kachelt sichtbar, sobald man sie zweimal nebeneinander legt.

   stitchTiles='stitch' ist der entscheidende Zusatz. Ohne ihn rechnet
   feTurbulence jede Kachel fuer sich, und an jeder Kante trifft Rauschen auf
   fremdes Rauschen - man sieht ein Gitter. Mit "stitch" wird das Rauschfeld
   ueber die Kachelgrenze hinweg fortgesetzt, und die Kachel ist nahtlos.
   Genau dieses Gitter war im Nebel zu sehen.

   baseFrequency klein = grobe Wolken, gross = feiner Grus. Die drei Lagen
   sind absichtlich weit auseinander: grobe Ballen, mittlere Schwaden, feiner
   Flug. Uebereinander ergibt das die Struktur, die eine einzelne Lage nicht
   haben kann. */
/* Der zweite Schritt in jedem Rauschbild ist die feColorMatrix. Sie rechnet
   auf der DECKKRAFT (letzte Zeile: neu = 4*alt - 1.4) und ist damit das, was
   contrast() im CSS-Filter nicht konnte:

     Rauschwert unter 0.35  ->  ganz durchsichtig
     Rauschwert ueber 0.60  ->  ganz deckend
     dazwischen             ->  ein schmaler Verlauf

   Aus dem gleichmaessigen Grauschleier, den feTurbulence liefert, werden so
   ausgefranste Zungen mit klaren Raendern - Rauch statt Dunst. Die drei Lagen
   sind verschieden hart: grob und weich oben, fein und hart unten. */
.hero-nebel-feld[data-lage="1"]{
  --rauschen:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='512' height='512'><filter id='a'><feTurbulence type='fractalNoise' baseFrequency='0.006' numOctaves='4' seed='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 -1.05'/></filter><rect width='512' height='512' filter='url(%23a)'/></svg>");
  --masche:900px;
  animation:nebelZug1 71s linear infinite;
}
.hero-nebel-feld[data-lage="2"]{
  --rauschen:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='512' height='512'><filter id='b'><feTurbulence type='fractalNoise' baseFrequency='0.014' numOctaves='3' seed='11' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 -1.4'/></filter><rect width='512' height='512' filter='url(%23b)'/></svg>");
  --masche:540px;
  animation:nebelZug2 47s linear infinite;
}
.hero-nebel-feld[data-lage="3"]{
  --rauschen:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='512' height='512'><filter id='c'><feTurbulence type='fractalNoise' baseFrequency='0.03' numOctaves='2' seed='23' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 -1.9'/></filter><rect width='512' height='512' filter='url(%23c)'/></svg>");
  --masche:300px;
  opacity:.7;
  animation:nebelZug3 33s linear infinite;
}

/* Die Masken ziehen in verschiedene Richtungen und mit verschiedenem Tempo.
   Der Weg ist jeweils ein GANZZAHLIGES Vielfaches der Maschenweite - nur dann
   sitzt das Muster am Ende wieder genau auf dem Anfang und der Durchlauf
   springt nicht sichtbar zurueck.

   HIER STANDEN FESTE PIXELWERTE, UND GENAU DAS WAR DER SPRUNG.
   900, 540 und 300 px passten zu den Maschenweiten der eingebauten
   Rauschbilder. Die mitgelieferten Texturen aus shared/nebel/ haben aber
   1100, 640 und 360 px - und eine Site mit eigenen Texturen setzt wieder
   andere. Der Weg war damit KEIN Vielfaches der Masche mehr: am Ende jedes
   Durchlaufs sass das Muster ein Stueck daneben und sprang zurueck. Auf der
   groben Lage einmal alle 71 Sekunden, gut sichtbar.

   Jetzt rechnet der Weg mit var(--masche) - egal, welche Textur darunter
   liegt. Der Nebel laeuft damit wirklich endlos; eine Grenze gibt es nicht,
   die Animation wiederholt nur eine Strecke, die exakt aufgeht. */
@keyframes nebelZug1{
  from{-webkit-mask-position:0 0;
       mask-position:0 0;}
  to  {-webkit-mask-position:var(--masche) calc(-1 * var(--masche));
       mask-position:var(--masche) calc(-1 * var(--masche));}
}
@keyframes nebelZug2{
  from{-webkit-mask-position:0 0;
       mask-position:0 0;}
  to  {-webkit-mask-position:calc(-1 * var(--masche)) calc(-2 * var(--masche));
       mask-position:calc(-1 * var(--masche)) calc(-2 * var(--masche));}
}
@keyframes nebelZug3{
  from{-webkit-mask-position:0 0;
       mask-position:0 0;}
  to  {-webkit-mask-position:var(--masche) calc(-2 * var(--masche));
       mask-position:var(--masche) calc(-2 * var(--masche));}
}

.hero-nebel{
  position:absolute; border-radius:50%;
  /* Eine Plateaustufe vor dem Auslaufen: erst danach hat contrast() etwas
     zu fassen. Ein glatter Verlauf von voll nach nichts wuerde dabei nur
     heller, nicht kantiger. */
  background:radial-gradient(closest-side,
    var(--nebel-kern, transparent) 0%,
    var(--nebel-farbe, color-mix(in srgb, var(--ink) 14%, transparent)) 34%,
    transparent 72%);
  filter:blur(18px); will-change:transform;
}
.hero-nebel.n1{left:-16%; bottom:-18%; width:62%; height:72%; animation:nebel1 31s ease-in-out infinite;}
.hero-nebel.n2{right:-14%; bottom:-22%; width:70%; height:80%; animation:nebel2 43s ease-in-out infinite;}
.hero-nebel.n3{left:26%;  bottom:-28%; width:56%; height:66%; animation:nebel3 37s ease-in-out infinite;}
.hero-nebel.n4{left:6%;   bottom:-12%; width:44%; height:52%; animation:nebel4 25s ease-in-out infinite;}
.hero-nebel.n5{right:12%; bottom:-16%; width:50%; height:58%; animation:nebel5 29s ease-in-out infinite;}
.hero-nebel.n6{left:38%;  bottom:-20%; width:46%; height:60%; animation:nebel2 35s ease-in-out infinite;}

/* Nur verschieben, drehen und skalieren - alles drei rechnet die Grafikkarte,
   ohne die Seite neu zu setzen. Ein wandernder "left"-Wert wuerde bei jedem
   Bild das Layout neu berechnen und auf schwachen Geraeten ruckeln.
   Die Drehung ist der Unterschied zu vorher: eine Schwade, die nur wandert,
   behaelt ihre Form - eine, die sich dabei dreht, quillt. */
@keyframes nebel1{
  0%,100%{transform:translate3d(0,0,0) rotate(0deg) scale(1);}
  50%    {transform:translate3d(22%,-14%,0) rotate(26deg) scale(1.3);}
}
@keyframes nebel2{
  0%,100%{transform:translate3d(0,0,0) rotate(0deg) scale(1.12);}
  50%    {transform:translate3d(-26%,-18%,0) rotate(-22deg) scale(.9);}
}
@keyframes nebel3{
  0%,100%{transform:translate3d(-10%,4%,0) rotate(8deg) scale(1);}
  50%    {transform:translate3d(16%,-20%,0) rotate(-18deg) scale(1.35);}
}
@keyframes nebel4{
  0%,100%{transform:translate3d(6%,0,0) rotate(-12deg) scale(1.15);}
  50%    {transform:translate3d(-18%,-24%,0) rotate(20deg) scale(.85);}
}
@keyframes nebel5{
  0%,100%{transform:translate3d(0,6%,0) rotate(16deg) scale(.95);}
  50%    {transform:translate3d(12%,-26%,0) rotate(-10deg) scale(1.25);}
}
/* "Bewegung reduzieren" schaltet oben schon jede Animation auf .001ms - die
   Schwaden bleiben dann einfach stehen und sind trotzdem zu sehen. Genau so
   ist es gemeint: es geht Stimmung verloren, kein Inhalt. */

/* --- Startbereich mit Bildkarte ---
   Die Karte steht LINKS im Markup, aber der Text ist der Hauptinhalt: auf
   schmalen Schirmen bricht die Karte deshalb unter den Text, nicht darueber.
   Sonst muesste jeder erst an einem Foto vorbeiscrollen, um zu erfahren,
   wessen Foto es ist. */
.hero-mit-bild .wrap{display:flex; align-items:center; gap:clamp(24px,5vw,64px);}
.hero-mit-bild .hero-text{flex:1 1 380px; min-width:0;}
.hero-karte{
  flex:0 0 clamp(240px,28vw,340px); order:-1;
  border:1px solid var(--line); border-radius:var(--ecken);
  background:var(--surface); box-shadow:var(--leuchten); overflow:hidden;
}
.hero-karte-bild{aspect-ratio:3/4; background:var(--bg-warm);
                 display:flex; align-items:center; justify-content:center;}
/* Ein Foto, das SCHON eine fertige Karte ist ("beschriftung: im-bild").
   Es wird nicht in ein Seitenverhaeltnis gezwungen und nicht beschnitten:
   an einer gestalteten Karte ist jeder Rand Absicht. Der Kasten nimmt
   stattdessen die Form des Bildes an. */
.hero-karte[data-beschriftung="im-bild"] .hero-karte-bild{
  aspect-ratio:auto; display:block;
}
.hero-karte[data-beschriftung="im-bild"] .hero-karte-bild img{
  height:auto; object-fit:contain;
}

/* --bild-stelle kommt aus "ausschnitt:" in der meta.txt des Portraits
   (siehe hero() in sections.js) - dasselbe Wort wie bei den Personenkarten.
   Ohne Angabe bleibt es bei der Mitte. */
.hero-karte-bild img, .hero-karte-bild video{
  width:100%; height:100%; object-fit:cover;
  object-position:var(--bild-stelle, center);
}

/* --- Freigestelltes Portrait auf Glas ---
   "freisteller: ja" in der meta.txt des Bildordners. Das Bild ist dann eine
   PNG-Datei ohne Hintergrund.

   Die Karte wird zur Scheibe: backdrop-filter nimmt, was HINTER ihr gemalt
   ist - also das Hintergrundfoto des Startbereichs - und zeichnet es
   unscharf. Deshalb funktioniert der Glaseffekt nur ueber einem Bild; auf
   einfarbigem Grund bleibt eine leicht getoente Flaeche uebrig, was auch
   nicht falsch aussieht. */
/* --- Die Scheibe hinter dem Portrait ---
   Art und Staerke kommen aus site.config.json (karteArt, karteStaerke) und
   stehen als Attribut bzw. als Variable an der Karte.

   EINE Rechnung fuer beide Glasarten: sie unterscheiden sich nur darin, ob
   zusaetzlich unscharf gezeichnet wird. Bei Staerke 0 bleibt von beiden
   nichts uebrig - "voll durchsichtig" braucht deshalb keinen eigenen Modus.

   backdrop-filter nimmt, was HINTER der Karte gemalt ist - also das
   Hintergrundfoto des Startbereichs. Ueber einfarbigem Grund bleibt nur die
   Toenung uebrig, was ebenfalls nicht falsch aussieht. */
.hero-karte[data-scheibe="milchglas"],
.hero-karte[data-scheibe="klarglas"]{
  background:color-mix(in srgb, var(--ink) calc(var(--scheibe-staerke, .55) * 22%), transparent);
}
.hero-karte[data-scheibe="milchglas"]{
  backdrop-filter:blur(calc(var(--scheibe-staerke, .55) * 26px)) saturate(1.15);
  -webkit-backdrop-filter:blur(calc(var(--scheibe-staerke, .55) * 26px)) saturate(1.15);
}
.hero-karte[data-scheibe="flaeche"]{background:var(--surface);}

/* DER Fehler, der die Durchsichtigkeit unbrauchbar machte:
   Der Bildkasten IN der Karte trug seine eigene Flaechenfarbe (--bg-warm) -
   eine undurchsichtige. Die Karte war also brav durchscheinend, und darin
   stand ein grauer Kasten, der alles verdeckte. Von aussen sah es aus, als
   bewirke der Regler nichts.

   Dasselbe gilt fuer die Namensplatte unten: sie darf nur so viel Deckung
   bekommen, wie zum Lesen noetig ist - und die kommt hier, nicht aus der
   Freisteller-Regel weiter unten. */
.hero-karte[data-scheibe="milchglas"] .hero-karte-bild,
.hero-karte[data-scheibe="klarglas"] .hero-karte-bild{background:none;}

/* Die Namensplatte hat einen EIGENEN Regler (--platte-staerke) und folgt
   nicht der Scheibe darueber.
   Der Grund ist inhaltlich: die Scheibe soll den Raum zeigen, die Platte soll
   einen Namen lesbar machen. Das sind zwei verschiedene Aufgaben, und wer die
   Scheibe ganz aufmacht, will deshalb noch lange keinen Namen, der im Nebel
   verschwindet. Vorgabe ist 100 - also deckend.
   Der Schatten bleibt trotzdem: er kostet nichts und traegt den Text auch
   dann, wenn jemand die Platte doch durchsichtig stellt. */
/* Die Farbe der Platte ist einstellbar (design.platteTon). Ohne Angabe ist es
   der GRUNDTON der Seite, nicht die Flaechenfarbe: --surface ist im Dunklen
   absichtlich eine Spur heller als der Grund - richtig fuer eine Karte, die
   auf der Seite liegt, falsch fuer eine Platte, die im Entwurf schwarz ist.
   Sie sah dadurch grau aus. */
.hero-karte[data-scheibe="milchglas"] .hero-karte-fuss,
.hero-karte[data-scheibe="klarglas"] .hero-karte-fuss{
  background:color-mix(in srgb, var(--platte-ton, var(--bg))
    calc(var(--platte-staerke, 1) * 100%), transparent);
  border-top:1px solid var(--line);
  text-shadow:0 1px 10px var(--bg), 0 0 3px var(--bg);
}

/* WICHTIG ZUM VERSTAENDNIS: durchscheinen kann nur, wo KEIN Bild ist.
   Ein normales Foto fuellt den Bildkasten vollstaendig aus - dann bleibt von
   der Scheibe nur der Rand und die Namensplatte zu sehen. Erst ein
   freigestelltes PNG gibt die Flaeche rund um die Person frei, und dann
   steht der Raum des Startbereichs dahinter. */
.hero-karte-frei .hero-karte-bild{
  background:none;
  /* Etwas hoeher als 3/4: die Person soll stehen, nicht in einem Kasten
     sitzen. object-position unten, damit sie auf der Fusszeile aufsetzt und
     nicht in der Mitte schwebt. */
  aspect-ratio:4/5;
  align-items:flex-end;
}
.hero-karte-frei .hero-karte-bild img{
  object-fit:contain; object-position:bottom;
  /* Ein Schatten unter der Person - ohne ihn klebt der Freisteller wie ein
     Aufkleber auf der Scheibe. */
  filter:drop-shadow(0 12px 26px rgba(0,0,0,.55));
  transition:filter .35s ease;
}
.hero-karte-frei:hover .hero-karte-bild img{
  filter:drop-shadow(0 12px 26px rgba(0,0,0,.55))
         drop-shadow(0 0 22px color-mix(in srgb, var(--accent) 45%, transparent));
}
/* Die Namensplatte bleibt IMMER etwas gedeckt, auch wenn die Scheibe
   darueber auf 0 steht: sie traegt Text, und Text auf einem bewegten Foto
   ist nicht mehr zu lesen. Sie folgt der Staerke, aber erst ab einem
   Grundwert. */
/* Beim Freisteller bleibt die Unschaerfe unter der Platte - dort steht Text
   direkt vor dem Foto. Die Deckung kommt aus der Regel oben, damit es nur
   EINE Stelle gibt, an der die Staerke wirkt. */
/* Beim Freisteller bleibt die Unschaerfe unter der Platte - dort steht Text
   direkt vor dem Foto. Sie richtet sich nach der PLATTE, nicht nach der
   Scheibe: eine halb durchsichtige Platte ohne Unschaerfe waere ein Fenster
   auf ein scharfes Foto, und darauf liest sich kein Name. */
.hero-karte-frei[data-scheibe="milchglas"] .hero-karte-fuss{
  backdrop-filter:blur(calc((1 - var(--platte-staerke, 1)) * 16px + 4px));
  -webkit-backdrop-filter:blur(calc((1 - var(--platte-staerke, 1)) * 16px + 4px));
}

/* Anklickbares Portrait (Kurzbiografie im Flyover). Ein <button>, damit es
   mit der Tastatur erreichbar ist - ein <div> mit Klickereignis waere fuer
   jeden, der nicht mit der Maus arbeitet, unsichtbar. */
.hero-karte-knopf{
  display:block; width:100%; padding:0; border:0; background:none;
  cursor:pointer; font:inherit; color:inherit; position:relative;
}
.hero-karte-mehr{
  position:absolute; left:0; right:0; bottom:0; padding:26px 12px 12px;
  font-family:var(--schrift-mono); font-size:.68rem;
  letter-spacing:.14em; text-transform:uppercase; color:var(--ink);
  background:linear-gradient(180deg, transparent, color-mix(in srgb, var(--bg) 80%, transparent));
  opacity:0; transition:opacity .28s ease;
}
.hero-karte-knopf:hover .hero-karte-mehr,
.hero-karte-knopf:focus-visible .hero-karte-mehr{opacity:1;}
.hero-karte-fuss{padding:16px 18px; text-align:center; display:grid; gap:4px;}
.hero-karte-fuss strong{
  font-family:var(--schrift-ueberschrift); font-size:1.35rem; line-height:1.1;
}
.hero-karte-fuss span{
  font-family:var(--schrift-mono); font-size:.72rem;
  letter-spacing:.14em; text-transform:uppercase; color:var(--accent);
}
.hero-karte-fuss em{font-style:normal; font-size:.76rem; color:var(--sub);
                    padding-top:8px; border-top:1px solid var(--line);}
.hero-karte-fuss em em{color:var(--accent);}
@media(max-width:820px){
  .hero-mit-bild .wrap{flex-direction:column; align-items:stretch;}
  /* Jetzt DOCH oben: steht die Karte auf einem Handy unter dem Text, sieht
     man beim Aufrufen der Seite gar kein Bild mehr - der Text allein fuellt
     dort schon den ganzen Schirm. */
  .hero-karte{order:-1; align-self:center; flex-basis:auto; max-width:280px;}
}

/* ---------- Zierelemente ----------
   Die Wellenform aus sections.js (ZIER). Sie traegt currentColor, steht also
   immer in der Farbe der Stelle, an der sie sitzt.

   preserveAspectRatio="none" im SVG heisst: die Kurve wird auf die Breite
   gezogen, die sie bekommt. Deshalb steht hier nur eine HOEHE - die Breite
   bestimmt der Ort, nicht das Zierelement. */
.zier{display:block; width:100%; height:44px; color:var(--accent); overflow:visible;}
.zier-linie{opacity:.55;}
/* Der wandernde Lichtpunkt: derselbe Kurvenzug, aber nur ein kurzes Stueck
   davon sichtbar (dasharray). Der Rest der Strichlaenge ist die Luecke -
   sie muss laenger sein als die Kurve, sonst laufen mehrere Punkte
   gleichzeitig. */
.zier-lauf{
  stroke-width:2.2;
  filter:drop-shadow(0 0 6px currentColor);
  stroke-dasharray:70 3000;
  animation:zierLauf 4.5s linear infinite;
}
@keyframes zierLauf{ from{stroke-dashoffset:3070;} to{stroke-dashoffset:0;} }

/* Unter dem Startbereich: schmal und zurueckgenommen, es ist ein Uebergang. */
.hero-zier{position:relative; z-index:2; margin-top:clamp(24px,5vw,54px);}
.hero-zier .zier{height:clamp(30px,5vw,56px); opacity:.9;}
/* Im Aufruf-Band steht es ZWISCHEN Text und Knoepfen und darf schrumpfen,
   wenn der Platz knapp wird - der Aufruf selbst darf es nie. */
.aufruf .zier{height:34px; min-width:80px;}
.zier-band{flex:1 1 90px; min-width:0;}
@media(max-width:820px){ .aufruf .zier-band{display:none;} }

.hero-chips{display:flex; flex-wrap:wrap; gap:10px; margin-top:26px;}
.hero-chip{
  display:inline-flex; align-items:center; gap:8px;
  font-family:var(--schrift-mono); font-size:.72rem;
  letter-spacing:.1em; text-transform:uppercase;
  padding:8px 15px; border:1px solid var(--line); border-radius:999px;
  color:var(--sub);
}
/* Das erste Schlagwort ist das wichtigste - Rolle, Zugehoerigkeit, Fachgebiet.
   Es traegt deshalb die Zierfarbe, alle weiteren bleiben ruhig. Ohne diese
   Abstufung ist eine Reihe aus sechs gleichen Pillen eine Wand. */
.hero-chip:first-child{color:var(--accent); border-color:var(--accent);}

/* --- Textblock im Startbereich mittig (design.heroText) ---
   Der geteilte Startbereich ist ausgenommen: dort steht der Text absichtlich
   links neben dem Zeichen, das ist seine ganze Idee. Die Breitenbegrenzungen
   (max-width) bleiben stehen und werden nur ueber "margin:auto" auf die
   Mittelachse geholt - ohne das waere ein zentrierter Satz ueber 90 Zeichen
   breit und damit schlechter lesbar als der linksbuendige davor. */
:root[data-herotext="mitte"] .hero:not(.hero-geteilt) .hero-text{
  text-align:center; display:flex; flex-direction:column; align-items:center;
}
:root[data-herotext="mitte"] .hero:not(.hero-geteilt) .hero-text h1,
:root[data-herotext="mitte"] .hero:not(.hero-geteilt) .hero-sub{
  margin-left:auto; margin-right:auto;
}
:root[data-herotext="mitte"] .hero:not(.hero-geteilt) .hero-ctas,
:root[data-herotext="mitte"] .hero:not(.hero-geteilt) .hero-chips{
  justify-content:center;
}
/* Steht daneben ein Foto, bleibt die zweispaltige Anordnung.

   Hier stand zwischenzeitlich das Gegenteil: Portrait oben, Text mittig
   darunter. Das war eine Fehldeutung von "Ueberschriften mittig" - gemeint
   waren die ABSCHNITTSueberschriften, nicht der Startbereich. Im Designsheet
   (NuT/_PLANUNG/NuT_WebsiteReferenz/01_Project_Context/references/
   Artist_Page_concept_Luzifa_1.png)
   steht das Portrait links, der Text rechts und linksbuendig; genau so ist es
   auch gebaut.

   Die Regel bleibt als ausdrueckliche Ausnahme stehen, damit die zentrierte
   Fassung (die Kollektivseiten nutzen sie) nicht versehentlich auf eine Seite
   mit Portrait durchschlaegt. */
:root[data-herotext="mitte"] .hero-mit-bild .hero-text{
  text-align:left; align-items:flex-start;
}

/* Name und Untertitel eine Spur groesser als in den Kundenvorlagen.
   Auf einer Kuenstlerseite ist der Name das Plakat und nicht die Ueberschrift
   eines Textes - er darf die Seite tragen. Die Vorlagen bleiben unberuehrt,
   weil die Regel an der Einstellung haengt und nicht an ".hero h1". */
:root[data-herotext="mitte"] .hero h1,
:root[data-herotext="mitte"] .hero-schriftzug{
  font-size:clamp(2.6rem,6vw,4.4rem); max-width:none;
}
:root[data-herotext="mitte"] .hero-sub{
  font-size:clamp(1.12rem,1.7vw,1.32rem); max-width:52ch;
}
.btn{
  text-decoration:none; font-size:.9rem; font-weight:600; padding:14px 24px;
  border:1px solid var(--ink); border-radius:var(--ecken); display:inline-block;
  transition:background-color .2s, color .2s, border-color .2s;
}
.btn-solid{background:var(--ink); color:var(--bg);}
.btn-solid:hover{background:var(--accent); border-color:var(--accent);}
.btn-line:hover{background:var(--ink); color:var(--bg);}

/* ---------- Abschnitte ---------- */
.band{padding:84px 0; border-bottom:1px solid var(--line);}
.band:nth-of-type(even){background:var(--surface);}

/* --- GLASFLAECHEN STATT GRAUER BAENDER (design.flaechen) -----------------

   "--surface" ist der Grundton um 7 % aufgehellt. Auf einer hellen Seite ist
   das ein warmes Weiss, auf einer schwarzen ein GRAU - und Grau ist auf einer
   Clubseite die einzige Farbe, die nirgends vorkommt.

   Es faerbt zwei Dinge zugleich: jedes zweite Band und saemtliche Karten.
   Deshalb hier zwei Schalter statt einer Farbe:

     .band:nth-of-type(even)  bekommt gar keine Flaeche mehr
     --surface                wird zum Glaston der Karten

   Der Glaston ist ein Hauch der Zierfarbe auf Durchsichtigem - dieselbe
   Bauart wie auf den Trance4matioN-Seiten (psy.css), nur ohne deren
   UV-Pigmente. Damit sieht man den Seitengrund durch die Karte, und die
   Karte hat trotzdem eine Kante.

   Ueber design.karteTon laesst sich der Ton frei setzen; ohne Angabe sind es
   5 % der Zierfarbe. --surface umzudefinieren statt zwanzig Regeln
   anzufassen ist Absicht: jede Stelle, die heute eine Flaeche hat, bekommt
   automatisch dieselbe neue - auch die, die erst naechste Woche dazukommt. */
:root[data-flaechen="glas"]{
  --surface:var(--karte-ton, color-mix(in srgb, var(--accent) 5%, transparent));
  --karte-kante:color-mix(in srgb, var(--accent) 42%, transparent);
  --karte-schein:0 0 22px color-mix(in srgb, var(--accent)
                   calc(30% * var(--leuchtkraft)), transparent);
}
:root[data-flaechen="glas"] .band:nth-of-type(even){background:none;}

/* DIE KARTEN.
   Dasselbe Aussehen, das Luzifas eigene site.css schon hatte - hier einmal
   fuer alle, statt es in jede Kollektivdatei zu kopieren: eine Kontur in der
   Zierfarbe, ein Saum darum, ein Hauch Verlauf von oben.

   DAZU ECHTES GLAS (backdrop-filter).

   Ohne das war die Karte bei 3 % Deckkraft praktisch durchsichtig - ein
   Laserstrahl DAHINTER war genauso deutlich zu sehen wie einer davor, und von
   aussen sah es aus, als laege er oben drauf. Die Ebene stimmte die ganze
   Zeit (Band auf z-index 1, Zeichenflaeche auf 0); was fehlte, war der
   sichtbare Unterschied.

   Ein Weichzeichner auf dem Untergrund macht daraus eine Scheibe: was
   dahinter liegt, bleibt sichtbar, wird aber unscharf - und genau daran
   erkennt das Auge, was vorn ist. Der Nebenzweck ist der wichtigere: Text
   auf einer Scheibe ist lesbar, Text auf einem wandernden Laserstrahl nicht.

   saturate hebt die Farbe hinter der Scheibe leicht an; ein reiner Blur
   macht den Untergrund flau. */
:root[data-flaechen="glas"] .fakten,
:root[data-flaechen="glas"] .termin,
:root[data-flaechen="glas"] .aufruf,
:root[data-flaechen="glas"] .partner:not(.partner-bald),
:root[data-flaechen="glas"] .skill-karten .skill-row,
:root[data-flaechen="glas"] .offer,
:root[data-flaechen="glas"] .fly-allg-box{
  border-color:var(--karte-kante);
  box-shadow:var(--karte-schein);
  background:var(--karte-ton, linear-gradient(180deg,
    color-mix(in srgb, var(--ink) 4%, transparent), transparent));
  -webkit-backdrop-filter:blur(7px) saturate(1.15);
          backdrop-filter:blur(7px) saturate(1.15);
}
.band h2{font-size:clamp(1.5rem,2.8vw,2.1rem); margin-bottom:12px;}
/* Ueberschrift links, Verweis rechts. Die Grundlinie wird geteilt (baseline),
   damit die kleine Zeile nicht mittig neben einer grossen Ueberschrift
   schwebt - sie soll auf derselben Linie sitzen wie deren Unterkante. */
.band-kopf{display:flex; align-items:baseline; justify-content:space-between; gap:20px;}
.band-kopf h2{margin-bottom:12px;}
/* Luft zwischen Ueberschrift und dem, was sie ueberschreibt.
   Vorher trug nur das h2 einen Abstand von 12px - und in den beiden
   Zierfassungen wird der auf 0 gesetzt (siehe unten), wodurch die Ueberschrift
   auf der ersten Kartenreihe klebte. Der Abstand gehoert an den KOPF, nicht an
   die Schrift darin: er trennt zwei Bloecke und nicht zwei Zeilen.

   Nur fuer "linie" und "mitte": in der Vorgabe "links" stehen die vier
   fertigen Kundenvorlagen, und deren Abstaende hat niemand bemaengelt. Eine
   Regel ohne Auswahl haette sie alle mitverschoben. */
:root[data-kopfstil="linie"] .band-kopf,
:root[data-kopfstil="mitte"] .band-kopf{margin-bottom:clamp(26px,3.4vw,44px);}
/* Steht eine Vorzeile darunter, hat sie ihren eigenen Abstand - dann waere
   der des Kopfes doppelt. */
:root[data-kopfstil="linie"] .band-kopf:has(+ .lede),
:root[data-kopfstil="mitte"] .band-kopf:has(+ .lede){margin-bottom:14px;}

/* --- Zierlinie im Abschnittskopf (design.abschnittskopf) ---
   Vorgabe ist "links": beide Striche sind da, aber breitenlos - die vier
   aelteren Kundenvorlagen sehen unveraendert aus. */
.band-linie{display:none;}
:root[data-kopfstil="linie"] .band-kopf,
:root[data-kopfstil="mitte"] .band-kopf{align-items:center;}
:root[data-kopfstil="linie"] .band-kopf h2,
:root[data-kopfstil="mitte"] .band-kopf h2{margin-bottom:0;}
/* Der Strich sitzt auf der Schriftmitte, nicht auf der Grundlinie - deshalb
   oben align-items:center statt baseline. Auf der Grundlinie saehe er aus
   wie eine Unterstreichung, die zu kurz geraten ist. */
:root[data-kopfstil="linie"] .band-linie-rechts,
:root[data-kopfstil="mitte"] .band-linie{
  display:block; flex:1 1 30px; min-width:20px; height:1px;
  background:linear-gradient(90deg, var(--accent), transparent);
  opacity:.5;
}
/* Zur Ueberschrift hin heller, nach aussen auslaufend - auf beiden Seiten.
   Ein durchgehender Strich quer durch die Seite wirkt wie ein Trenner
   zwischen zwei Themen, nicht wie eine Zierde an einer Ueberschrift. */
:root[data-kopfstil="mitte"] .band-linie-links{
  background:linear-gradient(90deg, transparent, var(--accent));
}
:root[data-kopfstil="mitte"] .band-kopf{justify-content:center; text-align:center;}
/* Die Vorzeile folgt der Ueberschrift: eine zentrierte Ueberschrift ueber
   einem linksbuendigen Absatz haette zwei Achsen. */
:root[data-kopfstil="mitte"] .lede{margin-left:auto; margin-right:auto; text-align:center;}
/* Der Aktionslink bricht in der Mitte-Fassung in eine eigene Zeile: neben
   einer zentrierten Ueberschrift zoege er sie aus der Mitte. */
:root[data-kopfstil="mitte"] .band-kopf{flex-wrap:wrap;}
:root[data-kopfstil="mitte"] .band-aktion{flex-basis:100%; text-align:center;}
@media(max-width:560px){
  :root[data-kopfstil="linie"] .band-linie-rechts{display:none;}
}
.band-aktion{
  flex:none; font:inherit; font-size:.84rem; font-weight:600; cursor:pointer;
  background:none; border:0; padding:4px 0; color:var(--accent);
  border-bottom:1px solid transparent;
}
.band-aktion:hover{border-bottom-color:var(--accent);}
@media(max-width:560px){
  /* Auf schmalen Schirmen unter die Ueberschrift statt daneben - nebeneinander
     bleiben von beiden nur Wortfetzen uebrig. */
  .band-kopf{flex-direction:column; align-items:flex-start; gap:2px;}
  .band-kopf h2{margin-bottom:6px;}
}
.lede{color:var(--sub); max-width:60ch; margin-bottom:40px;}

/* ---------- Leistungen ---------- */
.offer-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:20px;}
.offer{
  background:var(--bg); border:1px solid var(--line); border-radius:var(--ecken);
  padding:26px 24px; display:flex; flex-direction:column;
}
.band:nth-of-type(even) .offer{background:var(--surface);}
.offer .oid{font-family:var(--schrift-mono); font-size:.72rem; letter-spacing:.08em;
            color:var(--accent); margin-bottom:12px; text-transform:uppercase;}
.offer h3{font-size:1.12rem; margin-bottom:10px;}
.offer .oclaim{font-size:.82rem; color:var(--sub); padding-bottom:12px;
               margin-bottom:12px; border-bottom:1px dashed var(--line);}
.offer p{color:var(--sub); font-size:.92rem; margin-bottom:14px;}
.offer ul{list-style:none; margin-bottom:16px;}
.offer li{font-size:.9rem; color:var(--sub); padding-left:16px; position:relative; margin-bottom:6px;}
.offer li::before{content:'—'; position:absolute; left:0; color:var(--accent);}
.offer .ofoot{margin-top:auto; display:flex; gap:14px; align-items:center; flex-wrap:wrap;}
.offer .ofoot a, .offer .obtn{
  font-size:.84rem; text-decoration:none; color:var(--accent);
  border:none; background:none; padding:0; cursor:pointer;
  border-bottom:1px solid var(--accent);
}
.offer .oprice{font-family:var(--schrift-mono); font-size:.8rem; opacity:.8;}
.offer-note{
  margin-top:22px; background:var(--bg-warm); border:1px solid var(--line);
  border-radius:var(--ecken); padding:22px 24px;
  display:grid; grid-template-columns:auto 1fr auto; gap:18px; align-items:center;
}
.offer-note .nid{font-family:var(--schrift-mono); font-size:.72rem; color:var(--accent);}
.offer-note p{color:var(--sub); font-size:.92rem;}
.offer-note a{text-decoration:none; border:1px solid var(--ink); padding:10px 18px;
              border-radius:var(--ecken); font-size:.84rem; white-space:nowrap;}
@media(max-width:700px){ .offer-note{grid-template-columns:1fr;} }

/* ---------- Team ---------- */
.team-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:24px;}
.person{background:var(--bg); border:1px solid var(--line); border-radius:var(--ecken); overflow:hidden;}
.band:nth-of-type(even) .person{background:var(--surface);}
.person-bild{aspect-ratio:4/5; background:var(--bg-warm); display:flex;
             align-items:center; justify-content:center; overflow:hidden;
             font-size:.8rem; color:var(--sub); text-align:center; padding:12px;}
/* --bild-stelle kommt aus "ausschnitt:" in der meta.txt des Eintrags
   (siehe team() in sections.js). Ohne Angabe bleibt es bei der Mitte. */
.person-bild img, .person-bild video{
  width:100%; height:100%; object-fit:cover;
  object-position:var(--bild-stelle, center);
}

/* Form der Personenfotos - waehlbar im Adminpanel unter Darstellung.
   Der Zuschnitt liegt auf dem RAHMEN, nicht auf dem Bild: so bleibt die
   Datei unangetastet und ein Formwechsel kostet kein neues Hochladen.
   "rund" und "diamant" brauchen ein quadratisches Feld, sonst entstuende
   ein Ei statt eines Kreises. */
.team-grid.form-rund    .person-bild{aspect-ratio:1; border-radius:50%; margin:20px 20px 0;}
.team-grid.form-weich   .person-bild{border-radius:14px; margin:14px 14px 0;}
.team-grid.form-eckig   .person-bild{border-radius:0;}
.team-grid.form-diamant .person-bild{
  aspect-ratio:1; margin:20px 20px 0;
  /* clip-path statt Drehung: eine gedrehte Kachel wuerde das Bild mitdrehen
     und man muesste es gegendrehen - hier bleibt es aufrecht. */
  clip-path:polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}
/* Ohne Foto steht dort ein Hinweistext - der soll nicht beschnitten werden. */
.team-grid.form-diamant .person-bild:not(:has(img)):not(:has(video)){clip-path:none;}
.person-text{padding:20px;}
.person-text h3{font-size:1.08rem; margin-bottom:4px;}
/* Die dritte Zeile - DJ, DJane, Live Act. Leiser als das Genre darueber:
   sie ordnet ein, sie ist nicht die Aussage. */
.person-typ{
  /* Kleiner als das Genre darueber (.76rem) und kleiner als die Abzeichen:
     die Taetigkeit ordnet ein, sie ist die leiseste der drei Zeilen. Die
     Sperrung faellt mit der Groesse ebenfalls - bei .2em faellt eine so
     kleine Schrift auseinander. */
  font-family:var(--schrift-mono); font-size:.5rem; letter-spacing:.14em;
  text-transform:uppercase; color:var(--sub); margin-top:1px; opacity:.85;
}
.person-rolle{font-family:var(--schrift-mono); font-size:.76rem;
              color:var(--accent); margin-bottom:10px;}
.person-text p{color:var(--sub); font-size:.92rem;}

/* --- Eine Reihe statt eines Rasters ---
   layouts.teamReihe = "scroll" (sections.js, RENDER.team; Verhalten in ui.js,
   karussell()).

   EINE Zeile Karten mit einem Knopf links und rechts, endlos herumreichend.
   Frueher trat die Reihe hier bewusst aus der Spalte heraus bis an den
   Fensterrand, damit man ihr ansieht, dass es weitergeht. Das ist nicht mehr
   noetig: die beiden Pfeile sagen es deutlicher, und sie brauchen den Platz
   an genau dieser Stelle. Ein Kasten, der unter seinen eigenen Knopf laeuft,
   verdeckt die Karte, auf die der Knopf zeigt.

   overflow-y:hidden waere falsch (es schneidet den Schein der Karten ab),
   overflow-y:visible ist bei einem scrollenden Kasten nicht erlaubt und wird
   vom Browser still zu auto - deshalb Innenabstand oben und unten, der dem
   Schein Platz laesst.

   KEIN scroll-snap: das Rondell setzt die Scrollposition beim Herumreichen um
   eine ganze Satzbreite zurueck, und ein Einrasten wuerde genau dann noch
   einmal nachziehen. Aus einem unsichtbaren Sprung wird so ein sichtbarer. */
/* Das Feld: Knopf, Reihe, Knopf. Ein Raster und keine absolute Lage, damit
   die Knoepfe die Reihe wirklich schmaler machen statt sich darueberzulegen -
   sonst verdeckt der Pfeil die Karte, auf die er zeigt. */
/* ".karten-reihe" und nicht ".team-reihe": dieselbe Reihe traegt inzwischen
   auch die Bereiche und den Rueckblick. Was darin liegt, entscheidet der
   Abschnitt; wie es laeuft, steht hier und nur hier. */
.karten-reihe{
  position:relative;
  display:grid; grid-template-columns:auto minmax(0,1fr) auto;
  align-items:stretch; gap:clamp(8px,1.6vw,20px);
}
/* Passt alles ohnehin nebeneinander, verschwinden die Knoepfe (ui.js setzt
   das Merkmal). Ein Pfeil, der nichts bewegt, ist eine Falle. */
.karten-reihe[data-ruhig] .reihe-knopf{display:none;}
.karten-reihe[data-ruhig]{grid-template-columns:minmax(0,1fr);}
/* Und dann stehen die Karten MITTIG.
   Die Spur richtet ihren Inhalt sonst linksbuendig aus - richtig, solange
   seitlich weitergeht, falsch, sobald alles hineinpasst: drei Kacheln klebten
   dadurch am linken Rand einer breiten Flaeche. Zentriert wird nur in diesem
   Zustand; eine scrollende Reihe muss vorne anfangen, sonst beginnt sie in
   der Mitte ihres eigenen Inhalts. */
.karten-reihe[data-ruhig] > .reihe-spur{justify-content:center;}
/* Und die Kopien sind weg.
   ui.js legt sie inzwischen IMMER an, damit aus einem Raster eine Reihe
   werden kann, sobald jemand das Fenster schmaler zieht. Solange es ein
   Raster ist, haben sie dort nichts zu suchen: man saehe dieselben Karten
   dreimal. */
.karten-reihe[data-ruhig] .reihe-klon{display:none;}

/* Die Pfeile sind ein HINWEIS, kein Bedienelement mit Gewicht.
   Deshalb ohne Kasten, blass und mit einem langsamen Pulsieren: es soll
   auffallen, dass es seitlich weitergeht, ohne den Blick vom Inhalt
   wegzuziehen. Ein umrandeter Knopf neben einer Karte sieht aus wie eine
   zweite Karte. */
.reihe-knopf{
  display:flex; align-items:center; justify-content:center;
  width:clamp(32px, 3.4vw, 54px); padding:0;
  background:none; cursor:pointer; color:var(--accent);
  border:0; opacity:.5;
  transition:opacity .25s;
  animation:reihePuls 3s ease-in-out infinite;
}
/* Ein duenner Umriss auf fast schwarzem Grund verschwindet. Der Saum macht
   ihn sichtbar, ohne ihn dick zu machen - dasselbe Mittel wie beim Neonrand
   am Markenzeichen, nur viel leiser. */
.reihe-knopf svg{
  filter:drop-shadow(0 0 6px color-mix(in srgb, var(--accent)
           calc(70% * var(--leuchtkraft)), transparent));
}
/* Die beiden Seiten schlagen versetzt - gleichzeitig saehe es aus wie ein
   Blinken der ganzen Seite, versetzt wie ein Hin und Her. */
.reihe-knopf-rechts{animation-delay:1.5s;}
/* Die Spanne war zu leise: bei 24 % war der Pfeil auf schwarzem Grund
   schlicht nicht da. Jetzt schwingt er zwischen deutlich und hell - immer
   noch zurueckhaltend gegenueber den Karten, aber auffindbar. */
@keyframes reihePuls{
  0%, 100%{ opacity:.42; }
  50%     { opacity:.9; }
}
@media(prefers-reduced-motion: reduce){
  .reihe-knopf{animation:none; opacity:.7;}
}
/* Ein UMRISS, keine gefuellte Flaeche - dasselbe Zeichen wie im Entwurf.
   Die Hoehe ist gedeckelt: der Knopf ist so hoch wie die Karten daneben,
   und ein Dreieck ueber die volle Kartenhoehe waere ein Wegweiser, kein
   Bedienelement. */
.reihe-knopf svg{width:58%; height:auto; max-height:78px;
                 transition:transform .18s ease;}
.reihe-knopf:hover{ opacity:1; animation:none; }
.reihe-knopf:hover svg{transform:scale(1.08);}
.reihe-knopf:active svg{transform:scale(.94);}
@media(max-width:560px){
  /* AUF DEM TELEFON GENAU EINE KARTE.
     Zwei halbe Karten nebeneinander sind auf 375px keine zwei Angebote,
     sondern zwei unleserliche Spalten. Die Karte nimmt deshalb die volle
     Breite, und die Spur rastet je Karte ein.

     Die Pfeile BLEIBEN - anders als frueher, wo sie hier verschwanden. Sie
     werden nicht zum Klicken gebraucht (der Finger wischt), sondern als
     Hinweis, dass es seitlich weitergeht. Genau das sieht man einer
     stehenden Karte sonst nicht an. Deshalb schmal und blass. */
  /* DIE PFEILE MUESSEN SICH TREFFEN LASSEN.
     22px sah richtig aus und war als Ziel fuer einen Daumen zu klein -
     empfohlen sind 44. Der Knopf bekommt deshalb Innenabstand und gibt ihn
     als Aussenabstand wieder her: die Trefferflaeche ist 44px breit, der
     Platz, den er der Karte wegnimmt, bleibt bei 24.

     Erster Versuch war ein unsichtbares ::after, das seitlich hinausragt.
     Das traegt zwar optisch, aber getroffen wurde es nicht - im Test lag an
     der Stelle weiterhin die Spur. Innenabstand am Knopf selbst ist der
     kuerzere Weg und geht nicht daneben.

     touch-action:manipulation nimmt die 300-ms-Pause, die der Browser sonst
     abwartet, ob noch ein zweites Tippen kommt. */
  .reihe-knopf{
    width:24px; padding-inline:10px; margin-inline:-10px;
    box-sizing:content-box; touch-action:manipulation; opacity:.62;
  }
  /* KEIN scroll-snap. Es stand hier einen Tag lang und war genau der Fehler,
     vor dem der Kommentar weiter oben warnt: das Rondell setzt die
     Scrollposition beim Herumreichen um eine ganze Satzbreite zurueck, und
     das Einrasten zieht danach noch einmal nach. Aus einem unsichtbaren
     Sprung wird dadurch ein sichtbarer - und zwar bei jedem Durchlauf
     zwischen letzter und erster Karte.

     Eine Karte je Ansicht braucht es auch nicht: die Karte ist so breit wie
     die Spur, sie steht also ohnehin allein. */
  .karten-reihe > .reihe-spur{gap:14px;}
  /* Die Kartenbreite fuer das Telefon steht NICHT hier, sondern ganz am Ende
     der Datei - siehe dort. Grund: die einzelnen Kartensorten bekommen ihre
     Breite weiter unten, und bei gleicher Spezifitaet gewinnt die spaetere
     Regel. Hier stehend hatte sie keine Wirkung. */
}

/* Die laufende Spur.

   Sie traegt ZUSAETZLICH die Rasterklasse ihres Abschnitts (team-grid,
   bereich-grid, rueck-grid) - daran haengt das Aussehen der Karten. Deshalb
   ist der Selektor hier zweistufig: "display:flex" muss das "display:grid"
   der Rasterklasse schlagen, egal in welcher Reihenfolge die beiden im
   Stylesheet stehen. */
/* WEICHE KANTEN STATT ABGESCHNITTENER KARTEN.

   Am Rand wurde eine Karte hart durchgeschnitten - das sah nach Fehler aus
   und nicht nach "hier geht es weiter". Eine Maske laesst sie stattdessen
   ausblenden.

   Beide Seiten blenden IMMER aus: die Reihe laeuft endlos (ui.js legt Kopien
   der Karten vor und hinter die echten), es gibt also keinen Anfang und kein
   Ende, an dem die Maske eine Karte grundlos halbieren wuerde.

   Der Verlauf ist etwa eine halbe Karte breit - laenger, und schon die
   vorletzte waere blass; kuerzer, und es bliebe eine sichtbare Kante. */
.karten-reihe > .reihe-spur{
  /* Der Verlauf beginnt HINTER dem Innenabstand: davor liegt nur Luft fuer
     den Schein, dort gibt es nichts auszublenden. */
  --rand:clamp(80px, 7vw, 170px);
  -webkit-mask-image:linear-gradient(90deg, transparent 0, #000 var(--rand),
    #000 calc(100% - var(--rand)), transparent 100%);
          mask-image:linear-gradient(90deg, transparent 0, #000 var(--rand),
    #000 calc(100% - var(--rand)), transparent 100%);
}
.karten-reihe > .reihe-spur{
  display:flex; gap:24px;
  grid-template-columns:none;
  overflow-x:auto;
  /* DER SCHEIN BRAUCHT PLATZ IM KASTEN.
     Ein Kasten mit overflow schneidet alles ab, was ueber ihn hinausragt -
     auch den Saum um eine Karte. overflow-x:auto laesst sich dabei nicht auf
     eine Achse beschraenken: sobald eine Achse scrollt, wird die andere vom
     Browser ebenfalls auf "auto" gesetzt. Es wird also auch oben und unten
     geschnitten.

     WIE VIEL PLATZ ES BRAUCHT, steht nicht fest, sondern haengt am Regler:
     eine Bereichskachel hat beim Zeigen 60px Schein MAL --leuchtkraft, bei
     1.55 also 93px. Mit festen 40px war der Saum gekappt, sobald die Maus
     darauf stand - genau der Fall, in dem er auffaellt. Deshalb rechnet das
     Polster jetzt mit demselben Regler und geht nie aus.

     SENKRECHT ist das gefahrlos: der negative Aussenabstand holt die Hoehe
     zurueck, und quer passiert nichts.

     WAAGERECHT wird EXAKT der Innenabstand der Reihe gespiegelt. Ein
     groesserer Wert zoege die Spur ueber den Rand der Reihe hinaus, und auf
     einem schmalen Schirm bekaeme die ganze Seite dadurch eine waagerechte
     Bildlaufleiste. Was hier fehlt, faengt die Maske ab: sie blendet die
     Raender ohnehin aus. */
  --schein-luft:calc(64px * var(--leuchtkraft));
  --luft-x:clamp(12px, 4vw, 64px);
  padding:var(--schein-luft) var(--luft-x);
  margin:calc(-1 * var(--schein-luft)) calc(-1 * var(--luft-x));
  /* KEIN Balken. Bei einer Reihe, die endlos herumreicht, misst er nichts:
     er zeigt die Position innerhalb von drei Saetzen Kopien, springt beim
     Umlegen zurueck und behauptet ein Ende, das es nicht gibt. Gescrollt
     wird trotzdem - mit Rad, Finger, Pfeilen und Tastatur. */
  scrollbar-width:none;
  /* Auf dem Telefon soll die Reihe mit dem Finger laufen, ohne dass der
     Browser den senkrechten Scroll abfaengt. */
  -webkit-overflow-scrolling:touch;
  overscroll-behavior-x:contain;
}
.karten-reihe > .reihe-spur::-webkit-scrollbar{display:none;}
/* Feste Kartenbreite - im Raster teilen sich die Karten den Platz, in einer
   Reihe gibt es keinen zu teilenden Platz. Ohne feste Breite schrumpfen die
   Karten, je mehr es werden, bis dreissig DJs als Streifen dastehen.

   Je Kartensorte eine eigene Breite: eine Personenkarte ist hochkant, eine
   Bereichskachel breit. Eine gemeinsame Zahl waere fuer die eine zu schmal
   und fuer die andere zu breit. Die letzte Regel faengt alles ab, was
   spaeter dazukommt. */
/* WIE VIELE KARTEN NEBENEINANDER?
   So viele, wie hinpassen - gedeckelt ist die Breite der Karte, nicht ihre
   Anzahl. Auf einem breiten Schirm stehen damit von selbst mehr da. Die
   Untergrenze ist die Lesbarkeit: unter 230px wird aus der Beschreibung
   eine Wortspalte. */
.karten-reihe > .reihe-spur > *{flex:0 0 clamp(240px, 20vw, 300px);}
.karten-reihe > .reihe-spur > .person{flex:0 0 clamp(230px, 17vw, 264px);}
.karten-reihe > .reihe-spur > .bereich{flex:0 0 clamp(280px, 26vw, 360px);}

/* DIE REIHE DARF UEBER DEN SATZSPIEGEL HINAUS.

   ".wrap" ist auf 1120px begrenzt - richtig fuer Text, falsch fuer eine
   Reihe, die seitlich laeuft: auf einem 3440er Schirm standen viereinhalb
   Karten in der Mitte, und links und rechts war Platz fuer sechs weitere.

   Der Selektor greift ueber ".band" und nicht ueber ".wrap >": zwischen
   Kasten und Reihe liegt noch der Behaelter des Abschnitts (data-section),
   den loader.js fuellt. Ein direktes Kind war die Reihe nie.

   Die Breite ist "100vw minus ein Rest": ein exaktes 100vw rechnet die
   senkrechte Bildlaufleiste mit und erzeugt genau dadurch eine zweite,
   waagerechte. Ueber 2100px wird gedeckelt - sonst stehen auf einem sehr
   breiten Schirm zwoelf Karten in einer Reihe, und aus dem Rondell wird
   ein Regal. */
.band .karten-reihe{
  --reihe-breit:min(calc(100vw - 14px), 2100px);
  width:var(--reihe-breit);
  margin-left:calc((100% - var(--reihe-breit)) / 2);
  padding-inline:clamp(12px, 4vw, 64px);
}
/* Die erste Bereichskachel ist im Raster die breite. In einer Reihe gibt es
   kein "breit" - dort stehen alle nebeneinander und muessen gleich aussehen. */
.karten-reihe > .reihe-spur > .bereich:first-child{grid-column:auto;}
.karten-reihe > .reihe-spur:focus-visible{outline:3px solid var(--accent); outline-offset:4px;}


/* ---------- Terminbuchung ---------- */
.buchung-rahmen{
  border:1px solid var(--line); border-radius:var(--ecken); overflow:hidden;
  background:var(--surface); min-height:620px;
}
.buchung-rahmen iframe{width:100%; height:660px; border:0; display:block;}
.buchung-hinweis{margin-top:14px; color:var(--sub); font-size:.9rem;}
.buchung-platzhalter{
  border:1.5px dashed var(--line); border-radius:var(--ecken);
  padding:32px; color:var(--sub); background:var(--surface);
}
.buchung-platzhalter p{margin-bottom:8px;}
.buchung-platzhalter code{background:var(--bg-warm); padding:2px 6px; font-size:.9em;}

/* ---------- Preise ---------- */
.price-toggle{
  width:100%; text-align:left; background:var(--surface); border:1px solid var(--line);
  border-radius:var(--ecken); padding:18px 22px; cursor:pointer;
  font:inherit; font-size:.9rem; color:var(--ink);
  display:flex; justify-content:space-between; align-items:center;
}
.price-toggle .chev{color:var(--accent); transition:transform .3s ease;}
.price-toggle[aria-expanded="true"] .chev{transform:rotate(90deg);}
.price-body{max-height:0; overflow:hidden; transition:max-height .45s ease;}
.price-inner{border:1px solid var(--line); border-top:none; background:var(--surface);}
.price-group{border-bottom:1px solid var(--line);}
.price-group:last-child{border-bottom:none;}
.price-group h4{font-family:var(--schrift-mono); font-size:.74rem; letter-spacing:.08em;
                text-transform:uppercase; color:var(--accent); padding:16px 22px 6px; font-weight:500;}
.price-row{display:grid; grid-template-columns:1fr auto; gap:20px; align-items:baseline;
           padding:11px 22px; border-top:1px dashed var(--line);}
.price-row .pname small{display:block; color:var(--sub); font-size:.82rem;}
.price-row .pval{font-family:var(--schrift-mono); font-size:.85rem; white-space:nowrap;}
.price-row .pval.soft{color:var(--sub);}
.price-foot{padding:16px 22px; color:var(--sub); font-size:.86rem; border-top:1px solid var(--line);}

/* ---------- Know-how / Merkmale ---------- */
/* Zwei Formen desselben Abschnitts, umschaltbar ueber layouts.skills:
   Reihen untereinander (Vorgabe) oder Karten nebeneinander. */
.skill-row{padding:18px 0; border-top:1px solid var(--line);}
.skill-row .num{
  font-family:var(--schrift-mono); font-size:.72rem; letter-spacing:.1em;
  color:var(--accent); display:block; margin-bottom:6px;
}
.skill-icon{color:var(--accent); font-size:1.5rem; line-height:0;
            display:block; margin-bottom:10px;}
.skill-row h3{font-size:1.06rem; margin-bottom:6px;}
.skill-row p{color:var(--sub); font-size:.92rem; max-width:70ch;}

.skill-karten{display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:18px;}
.skill-karten .skill-row{
  border-top:0; padding:24px;
  border:1px solid var(--line); border-radius:var(--ecken);
  background:var(--surface); box-shadow:var(--leuchten);
}

/* ---------- Kennzahlen-Leiste ---------- */
/* Eine Reihe, die bei Platzmangel umbricht statt zu schrumpfen: gestauchte
   Zahlen liest niemand, umgebrochene schon. Die Trennstriche sitzen ZWISCHEN
   den Zellen (::before ab der zweiten), nicht als Rahmen an jeder - sonst
   stehen an den Umbruchstellen doppelte Linien. */
.fakten{
  display:flex; flex-wrap:wrap;
  border:1px solid var(--line); border-radius:var(--ecken);
  background:var(--surface); box-shadow:var(--leuchten);
}
.fakt{
  flex:1 1 200px; display:flex; align-items:center; gap:14px;
  padding:20px 24px; position:relative;
}
.fakt + .fakt::before{
  content:''; position:absolute; left:0; top:18%; bottom:18%;
  border-left:1px solid var(--line);
}
.fakt-icon{color:var(--accent); font-size:1.35rem; line-height:0;}
.fakt-text{display:flex; flex-direction:column; min-width:0;}
.fakt-name{
  font-family:var(--schrift-mono); font-size:.7rem; letter-spacing:.1em;
  text-transform:uppercase; color:var(--accent);
}
/* Der WERT in einer Zelle der Faktenleiste - "140-155 BPM", "Hard Techno".
   Auf jeder Seite dasselbe Bauteil, aber es sieht ueberall anders aus: auf
   BOESEBAESSE weiss, auf Trance4matioN limonefarben, auf einer Praxisseite
   im Fliesstextton. Bisher war das nirgends einstellbar, sondern stand an
   drei Stellen fest verteilt - deshalb hier zwei Variablen.

   Ohne Angabe aendert sich nichts: die Farbe erbt wie bisher vom Text
   darum, die Schrift kommt aus der Vorlage. */
.fakt-wert{
  font-size:.98rem; font-weight:600;
  color:var(--fakt-farbe, inherit);
  font-family:var(--fakt-schrift, inherit);
}
@media(max-width:640px){
  .fakt{flex:1 1 100%; padding:14px 18px;}
  /* Bei einer Zelle je Zeile trennt die Linie nicht mehr links, sondern oben */
  .fakt + .fakt::before{left:18px; right:18px; top:0; bottom:auto;
                        border-left:0; border-top:1px solid var(--line);}
}

/* ---------- Termine ---------- */
.termin-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:20px;}
.termin{
  display:flex; flex-direction:column; overflow:hidden;
  border:1px solid var(--line); border-radius:var(--ecken);
  background:var(--surface); box-shadow:var(--leuchten);
}
.termin-bild{position:relative; aspect-ratio:16/10; background:var(--bg-warm);
             display:flex; align-items:center; justify-content:center; overflow:hidden;}
.termin-bild img, .termin-bild video, .termin-bild iframe{
  width:100%; height:100%; object-fit:cover; border:0;
}
/* Die Datumsplakette liegt AUF dem Bild und bringt ihren eigenen dunklen
   Grund mit - ein helles Foto und ein weisses Datum darauf sind sonst nicht
   auseinanderzuhalten. */
.termin-datum{
  position:absolute; left:12px; top:12px; z-index:2;
  display:flex; flex-direction:column; align-items:center; line-height:1;
  padding:8px 12px; border-radius:var(--ecken);
  background:rgba(0,0,0,.62); color:#fff; backdrop-filter:blur(3px);
}
.termin-datum b{font-size:1.5rem; font-weight:700;}
.termin-datum i{font-style:normal; font-family:var(--schrift-mono);
                font-size:.66rem; letter-spacing:.12em; margin-top:3px; color:var(--accent);}
.termin-datum u{text-decoration:none; font-size:.6rem; opacity:.7; margin-top:2px;}
.termin-text{padding:18px; display:flex; flex-direction:column; gap:8px; flex:1;}
.termin-text h3{font-size:1.1rem;}
.termin-ort{display:flex; align-items:center; gap:7px; font-size:.86rem; color:var(--accent);}
.termin-info{font-size:.9rem; color:var(--sub);}
.termin-knopf{
  margin-top:auto; align-self:flex-start; display:inline-flex; align-items:center; gap:7px;
  text-decoration:none; font-size:.86rem; font-weight:600;
  padding:9px 16px; border:1px solid var(--line); border-radius:var(--ecken);
}
.termin-knopf:hover{border-color:var(--accent); color:var(--accent);}
/* Archiv: sichtbar, aber erkennbar zweitrangig. Nicht ausgegraut bis zur
   Unlesbarkeit - wer im Archiv liest, will es ja lesen. */
.termin-vorbei{opacity:.62;}
.termin-vorbei:hover{opacity:1;}
.termine-leer{color:var(--sub); font-size:.96rem; padding:18px 0;}

/* ---------- Aufruf ---------- */
.aufruf{
  display:flex; align-items:center; gap:22px; flex-wrap:wrap;
  padding:26px 28px; border:1px solid var(--line); border-radius:var(--ecken);
  background:var(--surface); box-shadow:var(--leuchten);
}
.aufruf-icon{color:var(--accent); font-size:1.8rem; line-height:0; flex:none;}
.aufruf-text{flex:1 1 260px; min-width:0;}
.aufruf-text h3{font-size:1.24rem;}
/* Das hervorgehobene Wort - "*LUZIFA*" in der meta.txt - traegt die
   Zierfarbe. Dieselbe Schreibweise wie in den Ueberschriften der Startseite. */
.aufruf-text h3 em{font-style:normal; color:var(--accent);}
.aufruf-text p{color:var(--sub); font-size:.92rem; margin-top:5px;}
.aufruf-knoepfe{display:flex; gap:12px; flex-wrap:wrap;}
.aufruf-knopf{
  display:inline-flex; align-items:center; gap:8px; text-decoration:none;
  font-size:.88rem; font-weight:600; padding:12px 22px;
  border:1px solid var(--ink); border-radius:var(--ecken); white-space:nowrap;
}
/* Auf dem Handy ueber die volle Breite und mit Umbruch.
   white-space:nowrap haelt eine lange Beschriftung ("Folgen & auf dem
   Laufenden bleiben") sonst in EINER Zeile - die dann breiter ist als der
   Schirm, und die ganze Seite laesst sich seitlich schieben. Ein Knopf, der
   umbricht, ist besser als eine Seite, die wackelt. */
@media(max-width:560px){
  .aufruf-knoepfe{width:100%;}
  .aufruf-knopf{
    flex:1 1 100%; white-space:normal;
    justify-content:center; text-align:center;
  }
}
.aufruf-knopf.voll{background:var(--ink); color:var(--bg); border-color:var(--ink);}
.aufruf-knopf.voll:hover{background:var(--accent); border-color:var(--accent);}
.aufruf-knopf.linie:hover{background:var(--ink); color:var(--bg);}

/* Eingebettete Rahmen fuellen immer den Kasten, in dem sie stehen. Ohne diese
   Zeile bekaeme jeder iframe die Vorgabe des Browsers (300 x 150 px) und
   stuende als kleiner Kasten in einer grossen Kachel - img und video sind
   weiter oben geregelt, iframe war es nie.

   Sie steht VOR den Hoerproben, nicht danach: .hoerprobe-spieler setzt eine
   feste Hoehe, und bei gleicher Spezifitaet gewinnt die spaetere Regel. */
.einbett{display:block; width:100%; height:100%; border:0;}

/* ---------- Formular in der Ebene ----------
   Ein Kasten, der fest in der index.html steht und den ui.js beim Oeffnen in
   die Flyover-Ebene schiebt (siehe elementOeffnen()). Warum geschoben und
   nicht nachgebaut, steht in der index.html.

   Solange er an seinem Platz im Dokument liegt, traegt er das Merkmal hidden -
   die Regel hier braucht ihn also nicht zu verstecken. */
.fly-formular{max-width:560px;}
.fly-formular-lede{
  color:var(--sub); font-size:.92rem; margin-bottom:18px;
}
.fly-formular-lede strong{color:var(--ink); font-weight:600;}

/* ---------- Hoerproben ----------
   Eingebettete Spieler von SoundCloud, Spotify oder YouTube (sections.js,
   RENDER.hoerproben; Reiter in ui.js, hoerprobenReiter).

   EIN Kasten mit zwei Reitern und einer Liste, die IN SICH scrollt.

   Warum die Liste scrollt und nicht einfach laenger wird: ein Kuenstler mit
   zehn Stuecken haette sonst zehn Spieler untereinander, und der Abschnitt
   waere hoeher als alles andere auf der Seite zusammen. Der Kasten bleibt
   jetzt gleich hoch, egal ob drei oder dreissig Stuecke darin liegen -
   dieselbe Ueberlegung wie bei der Kartenreihe der DJs.

   Die Hoehen der Spieler stehen fest und nicht als Seitenverhaeltnis: ein
   Spieler ist kein Bild. Er braucht so viel Platz, wie seine Bedienelemente
   hoch sind - bei einem breiteren Fenster wird er breiter, nicht hoeher. */
.hoerpanel{
  border:1px solid var(--line); border-radius:var(--ecken);
  background:var(--surface); box-shadow:var(--leuchten);
  overflow:hidden;
}

/* --- Die Reiter --- */
.hoer-reiter{display:flex; gap:2px; border-bottom:1px solid var(--line);}
.hoer-reiter-knopf{
  display:inline-flex; align-items:center; gap:8px;
  padding:14px 22px; border:0; background:none; cursor:pointer;
  font-family:var(--schrift-mono); font-size:.78rem;
  letter-spacing:.1em; text-transform:uppercase;
  color:var(--sub); position:relative;
  transition:color .2s;
}
.hoer-reiter-knopf:hover{color:var(--ink);}
/* Der Strich unter dem gewaehlten Reiter. Als eigenes Element und nicht als
   border-bottom: ein Rahmen wuerde den Text um einen Pixel verschieben,
   sobald man umschaltet. */
.hoer-reiter-knopf::after{
  content:''; position:absolute; left:14px; right:14px; bottom:-1px; height:2px;
  background:var(--accent); transform:scaleX(0); transform-origin:center;
  transition:transform .2s ease;
}
.hoer-reiter-knopf[aria-selected="true"]{color:var(--accent);}
.hoer-reiter-knopf[aria-selected="true"]::after{transform:scaleX(1);}
.hoer-zahl{
  font-size:.68rem; padding:1px 7px; border-radius:99px;
  background:color-mix(in srgb, var(--ink) 10%, transparent);
}
.hoer-reiter-knopf[aria-selected="true"] .hoer-zahl{
  background:color-mix(in srgb, var(--accent) 18%, transparent);
}

/* --- Die scrollende Liste --- */
.hoer-liste{
  max-height:clamp(300px, 46vh, 520px);
  overflow-y:auto;
  padding:6px 18px 18px;
  scrollbar-width:thin;
  scrollbar-color:var(--accent) transparent;
  overscroll-behavior-y:contain;
}
.hoer-liste::-webkit-scrollbar{width:8px;}
.hoer-liste::-webkit-scrollbar-thumb{
  background:color-mix(in srgb, var(--accent) 55%, transparent); border-radius:99px;
}
.hoer-liste::-webkit-scrollbar-track{background:transparent;}

.hoerprobe{padding:14px 0; display:grid; gap:10px; align-content:start;}
.hoerprobe + .hoerprobe{border-top:1px solid var(--line);}
.hoerprobe-kopf{display:flex; align-items:baseline; justify-content:space-between; gap:12px;}
.hoerprobe-kopf h3{font-size:1rem;}
.hoerprobe-kopf .mono{margin-bottom:0; white-space:nowrap;}
.hoerprobe-spieler{height:166px;}
/* Spotify baut seinen Spieler hoch: Deckel, Titel und Regler stehen
   untereinander. Bei 166 px waere davon die Haelfte abgeschnitten. */
.hoerprobe-hoch{height:232px;}
/* Ein Album bringt seine Titelliste mit - genau deshalb wird sie hier nicht
   nachgebaut. Sie braucht aber Platz. */
.hoerprobe-album{height:440px;}
.hoerprobe-albumhoch{height:380px;}
.hoerprobe-text{font-size:.9rem; color:var(--sub);}
.hoerprobe-text em{font-style:normal; color:var(--accent);}
.hoerprobe-aus{justify-self:start;}

/* Apple Music baut seinen Spieler flacher als SoundCloud, sein Album dafuer
   hoeher - die Titelliste steht bei ihm mit Deckel darueber. Mixcloud kommt
   mit einem schmalen Streifen aus, weil das Bild abgeschaltet ist
   (hide_cover=1 in der Einbett-Adresse). */
.hoerprobe-apple{height:175px;}
.hoerprobe-applealbum{height:450px;}
.hoerprobe-mix{height:120px;}
/* Ein Video ist keine Tonspur: es braucht ein Seitenverhaeltnis, keine
   feste Hoehe - sonst stehen bei jedem Fenster andere schwarze Balken. */
.hoerprobe-video{height:auto; aspect-ratio:16/9;}

/* --- Anbieterknoepfe ueber dem Spieler ---
   Dasselbe Stueck liegt bei mehreren Diensten; hier waehlt der Besucher.
   Die Reihenfolge kommt aus sections.js (DIENSTE) - vorne die, bei denen vom
   Hoeren am meisten beim Kuenstler ankommt. */
.hoerprobe-dienste{display:flex; flex-wrap:wrap; gap:6px;}
.hoer-dienst{
  font-family:var(--schrift-mono); font-size:.66rem; letter-spacing:.1em;
  text-transform:uppercase; cursor:pointer;
  padding:5px 11px; border-radius:999px;
  border:1px solid var(--line); background:none; color:var(--sub);
  transition:color .2s, border-color .2s, background .2s;
}
.hoer-dienst:hover{color:var(--ink); border-color:var(--accent);}
.hoer-dienst[aria-pressed="true"]{
  color:var(--accent);
  border-color:color-mix(in srgb, var(--accent) 55%, transparent);
  background:color-mix(in srgb, var(--accent) 12%, transparent);
}
/* Ein Punkt vor dem Namen bei den Diensten, die den Kuenstler am besten
   bezahlen. Nur ein leiser Hinweis - der Satz oben sagt, was er bedeutet. */
.hoer-dienst-fair::before{
  content:''; display:inline-block; width:5px; height:5px; margin-right:7px;
  border-radius:50%; background:var(--accent); vertical-align:middle;
}

/* --- Der Zufallsknopf und der Hinweis darunter --- */
.hoer-start{
  display:flex; align-items:center; gap:16px; flex-wrap:wrap;
  padding:16px 18px; border-bottom:1px solid var(--line);
}
.hoer-zufall{
  display:inline-flex; align-items:center; gap:12px; cursor:pointer;
  padding:10px 20px 10px 12px; border-radius:999px;
  border:1px solid color-mix(in srgb, var(--accent) 55%, transparent);
  background:color-mix(in srgb, var(--accent) 12%, transparent);
  color:var(--accent);
  font-family:var(--schrift-mono); font-size:.74rem;
  letter-spacing:.12em; text-transform:uppercase;
  transition:background .2s, box-shadow .2s;
}
.hoer-zufall:hover{
  background:color-mix(in srgb, var(--accent) 22%, transparent);
  box-shadow:var(--leuchten);
}
/* Das Dreieck ist aus Rahmen gebaut, nicht aus einem Zeichen: ein ▶ aus der
   Schrift sitzt je nach Schriftart anders auf der Grundlinie. */
.hoer-zufall-zeichen{
  width:0; height:0; margin-left:6px;
  border-left:11px solid currentColor;
  border-top:7px solid transparent; border-bottom:7px solid transparent;
}
/* Die Profilknoepfe: "hier gibt es mich auch". Sie sehen aus wie die
   Anbieterknoepfe an einem Stueck, fuehren aber hinaus statt umzuschalten -
   deshalb der Pfeil und kein aria-pressed. */
.hoer-profile{display:flex; flex-wrap:wrap; gap:6px;}
.hoer-profil{
  font-family:var(--schrift-mono); font-size:.66rem; letter-spacing:.1em;
  text-transform:uppercase; text-decoration:none;
  padding:5px 11px; border-radius:999px;
  border:1px solid var(--line); color:var(--sub);
  transition:color .2s, border-color .2s, background .2s;
}
.hoer-profil:hover{
  color:var(--accent); border-color:var(--accent);
  background:color-mix(in srgb, var(--accent) 10%, transparent);
}
.hoer-fair{
  flex:1 1 100%; min-width:220px; margin:0;
  font-size:.82rem; color:var(--sub); line-height:1.5;
}
.hoer-fair em{font-style:normal; color:var(--accent);}

/* Das Stueck, das der Zufallsknopf gewaehlt hat. Ein Strich links, kein
   Farbklecks: der Kasten soll ruhig bleiben, waehrend Musik laeuft. */
.hoerprobe.laeuft{
  border-left:2px solid var(--accent);
  padding-left:12px; margin-left:-14px;
}

/* ---------- Partner / Kollektive ---------- */
/* Die erste Karte ist die grosse: ein Kollektiv, dem man angehoert, steht
   nicht gleichberechtigt neben zwei Platzhaltern. */
.partner-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:18px;}
.partner-grid > .partner:first-child{grid-column:span 2;}
@media(max-width:720px){ .partner-grid > .partner:first-child{grid-column:auto;} }
.partner{
  display:flex; gap:22px; align-items:center; padding:24px;
  border:1px solid var(--line); border-radius:var(--ecken);
  background:var(--surface); box-shadow:var(--leuchten);
  /* Nebeneinander nur, wenn wirklich Platz dafuer ist.
     Vorher stand die Marke neben dem Text ab der ersten Zeile - und weil die
     schmalen Karten nur gut 250px breit sind, blieben dem Text rund 50px. Das
     ergab eine Spalte aus einzelnen Woertern und bei der dritten Karte gar
     nichts mehr. Jetzt darf die Zeile umbrechen: der Text fordert mindestens
     200px, und wo die nicht danebenpassen, rutscht er unter die Marke.

     Warum keine Container-Abfrage (der naheliegende Weg, den ".bereich" geht):
     ein Element kann sich nicht selbst abfragen. "container-type" auf .partner
     und "@container" fuer .partner waeren zwei verschiedene Kaesten - die
     Regel haette nie gegriffen. */
  flex-wrap:wrap; justify-content:center;
}
.partner-logo{
  flex:1 1 40%; min-width:140px;
  display:flex; align-items:center; justify-content:center;
}
.partner-logo img{max-height:96px; width:auto; object-fit:contain;}
/* Der Name steht seit dem 20.08.2026 IMMER im Markup, damit eine Seite beide
   zeigen kann (Zeichen und Name nebeneinander, siehe portfolio2). Wo ein Logo
   liegt, trug es den Namen bisher schon in sich - dort bleibt er verborgen,
   sonst stuende er auf allen bestehenden Seiten ploetzlich doppelt da. */
.partner-logo img ~ .partner-name{display:none;}
.partner-name{
  font-family:var(--schrift-ueberschrift); font-weight:700; font-size:1.6rem;
  letter-spacing:-.02em; text-align:center; line-height:1.05;
}
/* 200px ist die Schwelle, unter der ein Satz zur Wortspalte wird. Sie steht
   hier als flex-basis und nicht als min-width: so darf der Text auf breiten
   Karten schrumpfen, springt aber unter die Marke, statt sich einzuschnueren. */
.partner-text{flex:1 1 200px; min-width:0;}
.partner-text p{font-size:.9rem; color:var(--sub); margin-bottom:14px;}
.partner-text p em{font-style:normal; color:var(--accent);}
.partner-knopf{
  display:inline-flex; align-items:center; gap:7px; text-decoration:none;
  font-size:.84rem; font-weight:600; padding:10px 18px;
  border:1px solid var(--line); border-radius:var(--ecken);
}
.partner-knopf:hover{border-color:var(--accent); color:var(--accent);}
/* Platzhalter: gestrichelt, damit auf den ersten Blick klar ist, dass hier
   nichts fehlt, sondern noch etwas kommt. */
.partner-bald{
  flex-direction:column; justify-content:center; gap:12px; text-align:center;
  border-style:dashed; background:none; box-shadow:none; color:var(--sub);
  min-height:150px;
}
.partner-schloss{font-size:1.4rem; line-height:0; opacity:.7;}
.partner-baldtext{
  font-family:var(--schrift-mono); font-size:.72rem;
  letter-spacing:.1em; text-transform:uppercase;
}

/* ---------- Häufige Fragen ---------- */
.faq-item{border-top:1px solid var(--line); padding:16px 0;}
.faq-item:last-of-type{border-bottom:1px solid var(--line);}
.faq-item summary{cursor:pointer; font-weight:600; font-size:1rem;}
.faq-item summary::marker{color:var(--accent);}
.faq-item p{color:var(--sub); font-size:.94rem; margin-top:10px; max-width:70ch;}

/* ---------- Arbeitsweise / Ablauf ---------- */
.proc{border:1px solid var(--line); border-radius:var(--ecken); background:var(--surface);
      font-family:var(--schrift-mono); font-size:.88rem;}
.proc .bar{padding:11px 18px; border-bottom:1px solid var(--line);
           color:var(--sub); font-size:.72rem; letter-spacing:.08em;}
.proc .body{padding:20px 22px; color:var(--sub);}
.proc .body div{margin-bottom:8px;}
.proc .body .p{color:var(--accent);}
.proc .cursor{display:inline-block; width:7px; height:1em; background:var(--accent);
              vertical-align:middle; animation:blink 1.05s step-end infinite;}
@keyframes blink{50%{opacity:0;}}

/* ---------- Galerie / Projekte (falls die Site sie nutzt) ---------- */
.gal{display:grid; grid-template-columns:repeat(4,1fr); gap:12px;}
.gal div{aspect-ratio:1; border:1px solid var(--line); background:var(--surface);
         overflow:hidden; display:flex; align-items:center; justify-content:center;
         font-size:.7rem; color:var(--sub); text-align:center;}
.gal img, .gal video{width:100%; height:100%; object-fit:cover;}
.gal-bento{grid-auto-rows:170px;}
.gal-bento div{aspect-ratio:auto;}
.gal-bento .gal-2x2{grid-column:span 2; grid-row:span 2;}
.gal-bento .gal-2x1{grid-column:span 2;}
.gal-bento .gal-4x1{grid-column:span 4;}
@media(max-width:760px){
  .gal{grid-template-columns:repeat(2,1fr);}
  .gal-bento{grid-auto-rows:140px;}
  .gal-bento .gal-2x1, .gal-bento .gal-4x1{grid-column:span 2;}
}

/* ---- Bento als Ziehharmonika ----
   Zeilen statt Raster: nur so kann beim Zeigen auf eine Kachel Platz
   UMVERTEILT werden (die Zeile unter ihren Kacheln, die Spalte unter ihren
   Zeilen). Ein Grid kann das nicht - es weiss nicht, in welcher Spalte die
   Maus steht.
   --reihen, --h und --w kommen aus sections.js; das Muster gehoert dorthin,
   nicht ins Stylesheet. */
.gal-akkordeon{
  display:flex; flex-direction:column; gap:12px;
  height:calc(var(--reihen, 2) * 270px);
}
/* Die Zeile ist ein Behaelter, keine Kachel. Die Sammelregel ".gal div"
   weiter oben gaebe ihr sonst Rahmen, Hintergrund und ein Seitenverhaeltnis.
   Sie ist zugleich das Raster [Kategoriename | Medien]. */
.gal-akkordeon .gal-reihe{
  /* FLEX, nicht Grid: eine Grid-Zeile ohne feste Hoehe richtet sich nach
     ihrem Inhalt, und der Inhalt (die Kacheln) rechnet mit height:100%
     ihrer Zeile - ein Zirkelschluss, der die Zeile auf 2 Pixel zusammenfallen
     liess. Ein Flex-Behaelter streckt seine Kinder dagegen von selbst. */
  display:flex; min-height:0;
  /* align-items ausdruecklich: ".gal div" setzt weiter oben center fuer
     ALLE divs in der Galerie. Zentrierte Kinder werden nicht gestreckt,
     und ein height:100% der Kacheln hatte dadurch nichts, worauf es sich
     beziehen konnte - die Kacheln fielen auf Inhaltshoehe zusammen. */
  align-items:stretch; justify-content:flex-start;
  flex:var(--h, 40) 1 0;
  aspect-ratio:auto; border:0; background:none; padding:0; overflow:visible;
  /* Die Verzoegerung gilt nur fuer den RUECKWEG (beim Zeigen wird sie auf 0
     gesetzt). Zwischen zwei Kacheln liegt eine Luecke; ohne sie faengt beim
     Hinueberfahren alles an zurueckzuschnellen und gleich wieder aufzugehen
     - das ist das Pumpen beim Wechseln. */
  transition:flex-grow .5s cubic-bezier(.65,0,.2,1) .1s;
}
.gal-akkordeon.mit-kat .gal-reihe{gap:24px;}
.gal-akkordeon .gal-reihe-inhalt{
  flex:1 1 auto;
  display:flex; gap:12px; min-width:0; min-height:0;
  align-items:stretch; justify-content:flex-start;
  aspect-ratio:auto; border:0; background:none; padding:0; overflow:visible;
}
.gal-akkordeon .gal-kat-kopf{
  flex:0 0 170px;
  aspect-ratio:auto; border:0; background:none; padding:0;
  display:block; align-self:flex-start; overflow:hidden; text-align:left;
}
.gal-akkordeon .gal-kachel{
  flex:var(--w, 5) 1 0; min-width:0; height:100%;
  aspect-ratio:auto;
  transition:flex-grow .5s cubic-bezier(.65,0,.2,1) .1s;
}
/* Auf schmalen Schirmen gibt es kein Zeigen und keinen Platz zum Verteilen:
   die Zeilen brechen um und die Kacheln bekommen wieder feste Hoehe. */
@media(max-width:760px){
  .gal-akkordeon{height:auto;}
  .gal-akkordeon .gal-reihe, .gal-akkordeon.mit-kat .gal-reihe{
    flex-direction:column; gap:10px; flex:none;
  }
  .gal-akkordeon .gal-kat-kopf{flex:none;}
  .gal-akkordeon .gal-reihe-inhalt{flex-wrap:wrap;}
  .gal-akkordeon .gal-kachel{flex:1 1 44%; height:auto; aspect-ratio:1;}
  .gal-akkordeon .gal-kat-kopf:empty{display:none;}
}

/* ---- Kategorien in der Galerie ----
   Ein Ordner IN der Galerie, der weitere Ordner enthaelt, ist eine Kategorie
   (Kunde, Projekt, Gewerk …). Name links, Bilder rechts. Ohne diese
   Gliederung lag alles wild durcheinander in einem Raster. */
.gal-kat{display:grid; grid-template-columns:170px 1fr; gap:24px;
         align-items:start; margin-bottom:36px;}
.gal-kat:last-child{margin-bottom:0;}
.gal-kat-kopf h3{font-family:var(--schrift-ueberschrift); font-size:1rem;
                 line-height:1.3; margin:0 0 6px;}
.gal-kat-kopf p{font-size:.82rem; color:var(--sub); margin:0;}
/* Ein Block OHNE Namen sind die Bilder, die in keiner Kategorie liegen. Der
   leere Kopf bleibt stehen, damit ihre Kacheln auf derselben Linie beginnen
   wie die der Kategorien - sonst entstuende eine Stufe. */
@media(max-width:760px){
  .gal-kat{grid-template-columns:1fr; gap:10px; margin-bottom:26px;}
  .gal-kat-kopf:empty{display:none;}
}

/* ---- Was beim Zeigen auf eine Kachel passiert ----
   Einstellbar im Panel (layouts.galleryHover):
     aus     - nichts, die Kachel bleibt wie sie ist
     ganz    - das Medium wird vollstaendig sichtbar, die Kachel bleibt gleich
     wachsen - die Kachel wird groesser UND zeigt das Medium vollstaendig

   Warum "vollstaendig" ueberhaupt: die Kacheln sind quadratisch oder breit,
   die Medien sind es nicht. Im Ruhezustand ist der Beschnitt gewollt (er macht
   das Raster ruhig), beim Hinsehen aber stoerend - dann will man das Bild als
   Ganzes. object-fit wechselt deshalb von cover auf contain.

   Nur mit Maus: auf dem Handy gibt es kein "Zeigen", dort bliebe die Kachel
   im Wachstumszustand haengen, sobald man sie einmal beruehrt hat. */
@media(hover:hover){
  /* Den Rest des Bildes stufenlos freigeben. object-fit laesst sich nicht
     animieren - ein Umschalten auf contain liess das Bild schlagartig
     zusammenschnappen, und erst danach wuchs die Kachel. Deshalb steht
     object-fit fest auf contain, und der Beschnitt entsteht durch eine
     Skalierung, die sich weich zuruecknehmen laesst. --fuell setzt ui.js,
     sobald das Medium geladen ist. */
  .gal .gal-kachel.gal-fuell > img,
  .gal .gal-kachel.gal-fuell > video,
  .gal .gal-kachel.gal-fuell > .gal-auto{
    object-fit:contain; background:#000;
    transform:scale(var(--fuell, 1));
    /* Dieselbe Kurve und dieselbe Verzoegerung wie bei der Kachel: Zoom und
       Wachstum muessen zusammenlaufen, sonst sieht man zwei Bewegungen. */
    transition:transform .5s cubic-bezier(.65,0,.2,1) .1s;
  }
  /* Der Videorahmen bringt seine eigene Zentrierung mit. */
  .gal .gal-kachel.gal-fuell > .gal-auto{
    object-fit:fill; background:none;
    transform:translate(-50%,-50%) scale(1);
  }
  .gal-wurzel:not([data-hover="aus"]) .gal-kachel.gal-fuell:hover > img,
  .gal-wurzel:not([data-hover="aus"]) .gal-kachel.gal-fuell:hover > video{
    transform:scale(1); transition-delay:0s;
  }
  /* ---- Bento als Reihe ----
     Die Kachelgroessen des Bento, aber je Kategorie nur EINE Zeile, die
     seitlich laeuft. Gebraucht wird das, sobald eine Kategorie mehr als drei
     Aufnahmen hat: im Bento wird sie dann mehrere Zeilen hoch, und bei sieben
     Kategorien ist die Galerie mehrere Bildschirme lang.

     Die Zeile hat eine feste Hoehe statt einer Hoehenbilanz. Ohne Umbruch
     gibt es nichts mehr zu verteilen, und eine Zeile, die sich nach ihrem
     Inhalt richtet, waere bei jeder Kategorie anders hoch. */
  .gal-bentoreihe{display:flex; flex-direction:column; gap:14px;}
  .gal-bentoreihe .gal-reihe{
    display:flex; align-items:stretch; justify-content:flex-start;
    height:clamp(190px, 21vw, 300px);
    /* ".gal div" weiter oben gaebe jeder Zeile Rahmen, Hintergrund und ein
       Seitenverhaeltnis - dieselbe Zuruecknahme wie beim Akkordeon. */
    aspect-ratio:auto; border:0; background:none; padding:0; overflow:visible;
  }
  .gal-bentoreihe.mit-kat .gal-reihe{gap:24px;}
  .gal-bentoreihe .gal-kat-kopf{
    flex:0 0 170px;
    aspect-ratio:auto; border:0; background:none; padding:0;
    display:block; align-self:flex-start; overflow:hidden; text-align:left;
  }
  /* Das Rondell nimmt den Rest der Zeile ein. min-width:0, sonst waechst ein
     Flex-Kind mit Ueberlauf ueber seinen Anteil hinaus. */
  .gal-bentoreihe .gal-reihe > .karten-reihe{flex:1 1 auto; min-width:0;}
  .gal-bentoreihe .gal-reihe-inhalt{
    flex:1 1 auto; display:flex; gap:12px; min-width:0;
    aspect-ratio:auto; border:0; background:none; padding:0; overflow:visible;
  }
  /* DIE BREITE KOMMT AUS DEM BENTO-VERHAELTNIS, ist aber fest statt wachsend.
     6,6 % je Einheit heisst: eine Dreiergruppe (6+4+4 = 14) fuellt gut 92 %
     der Spur, die vierte Kachel schaut angeschnitten herein und sagt damit
     "hier geht es weiter". Prozent und nicht Pixel, damit die Kacheln auf
     einem schmalen Schirm mitgehen, statt den Rand zu sprengen. */
  .karten-reihe > .reihe-spur.gal-bento-spur > .gal-kachel{
    flex:0 0 calc(var(--w, 5) * 6.6%);
    min-width:120px; height:100%; aspect-ratio:auto;
  }
  /* KEIN ZIEHHARMONIKA-WACHSEN.
     Im Akkordeon nimmt eine Kachel beim Zeigen ihren Nachbarn Platz weg. In
     einer Reihe gibt es keinen Nachbarn, dem etwas gehoert: dort veraenderte
     das Wachsen die Gesamtbreite der Spur, und das Rondell rechnete bei jedem
     Zeigen neu aus, ob es Pfeile braucht. Gemessen wurden dabei 518
     Zustandswechsel in 800 ms. Der Zoom im Bild bleibt, er kostet keine
     Breite. */
  .gal-bentoreihe .gal-kachel:hover{flex-grow:0;}

  /* Eine Zeile ohne Rondell (genau eine Kachel) streckt diese ueber die
     ganze Breite - sonst behielte sie ihre Bildgroesse und stuende verloren
     links in der Zeile. */
  .gal-bentoreihe .gal-reihe-inhalt > .gal-kachel{
    flex:1 1 auto; min-width:0; height:100%;
  }
  /* Und eine Zeile ohne Kategorienamen (der Banner ganz unten) bekommt weder
     die Namensspalte noch eine feste Hoehe: sie zeigt ihr Bild in voller
     Breite und in seinem eigenen Verhaeltnis. */
  .gal-bentoreihe .gal-reihe:has(.gal-kat-kopf:empty){height:auto;}
  .gal-bentoreihe .gal-reihe:has(.gal-kat-kopf:empty) .gal-kat-kopf{display:none;}
  .gal-bentoreihe .gal-reihe:has(.gal-kat-kopf:empty) .gal-kachel{
    height:auto; aspect-ratio:auto;
  }
  .gal-bentoreihe .gal-reihe:has(.gal-kat-kopf:empty) .gal-kachel > img,
  .gal-bentoreihe .gal-reihe:has(.gal-kat-kopf:empty) .gal-kachel > video{
    height:auto; object-fit:contain;
  }
  .gal-bentoreihe .gal-reihe:has(.gal-kat-kopf:empty) .gal-kachel.gal-fuell > img,
  .gal-bentoreihe .gal-reihe:has(.gal-kat-kopf:empty) .gal-kachel.gal-fuell > video{
    transform:none; background:none;
  }

  @media(max-width:760px){
    .gal-bentoreihe .gal-reihe{
      flex-direction:column; gap:10px; height:auto;
    }
    .gal-bentoreihe .gal-kat-kopf{flex:none;}
    .gal-bentoreihe .gal-kat-kopf:empty{display:none;}
    .karten-reihe > .reihe-spur.gal-bento-spur > .gal-kachel{
      flex:0 0 min(232px, 74vw); height:auto; aspect-ratio:1;
    }
  }

  /* WEICHER WECHSEL AUF EINER SAMMELKACHEL.
     Steht ein ganzer Ordner hinter einer Kachel, blaettert sie von selbst
     durch ihn hindurch (ui.js, sammlungVorschau). Ein harter Schnitt alle
     fuenf Sekunden liest sich als Fehler, nicht als Abfolge.

     Die Zoom-Angabe muss mit wiederholt werden: eine zweite transition-Zeile
     ERSETZT die erste, sie ergaenzt sie nicht. */
  .gal .gal-kachel[data-blaettern] > img,
  .gal .gal-kachel[data-blaettern] > video{
    transition:transform .5s cubic-bezier(.65,0,.2,1) .1s,
               opacity .7s cubic-bezier(.4,0,.2,1);
  }
  .gal .gal-kachel[data-blaettern].gal-wechselt > img,
  .gal .gal-kachel[data-blaettern].gal-wechselt > video{opacity:0;}
  .gal-wurzel:not([data-hover="aus"]) .gal-kachel.gal-fuell:hover > .gal-auto{
    transform:translate(-50%,-50%) scale(calc(1 / var(--fuell, 1)));
    transition-delay:0s;
  }
  /* Ziehharmonika: die gehoverte Kachel bekommt mehr Gewicht, ihre Nachbarn
     geben welches ab; dasselbe eine Ebene hoeher zwischen den Zeilen. Die
     Gesamthoehe bleibt fest - es wird nur umverteilt, nichts ueberlappt. */
  .gal-wurzel[data-hover="wachsen"] .gal-reihe:has(.gal-kachel:hover),
  .gal-wurzel[data-hover="wachsen"] .gal-kachel:hover{
    transition-delay:0s;
  }
  .gal-wurzel[data-hover="wachsen"] .gal-reihe:has(.gal-kachel:hover),
  .gal-wurzel[data-hover="wachsen"] .gal-kachel:hover{
    transition-delay:0s;
  }
  .gal-wurzel[data-hover="wachsen"] .gal-reihe:has(.gal-kachel:hover){
    flex-grow:calc(var(--h, 40) * var(--wachs-h, 1.55));
  }
  .gal-wurzel[data-hover="wachsen"]:has(.gal-kachel:hover)
    .gal-reihe:not(:has(.gal-kachel:hover)){
    flex-grow:calc(var(--h, 40) * 0.75);
  }
  .gal-wurzel[data-hover="wachsen"] .gal-kachel:hover{
    flex-grow:calc(var(--w, 5) * var(--wachs-w, 1.8));
  }
  .gal-wurzel[data-hover="wachsen"]
    .gal-reihe:has(.gal-kachel:hover) .gal-kachel:not(:hover){
    flex-grow:calc(var(--w, 5) * 0.85);
  }

  /* Im gleichmaessigen Raster gibt es keine Zeilen, unter denen sich Platz
     umverteilen liesse - dort waechst die Kachel ueber ihre Nachbarn. */
  .gal-wurzel[data-hover="wachsen"] .gal:not(.gal-akkordeon) .gal-kachel{
    transition:transform .5s cubic-bezier(.65,0,.2,1) .1s,
               opacity .5s ease .1s, box-shadow .5s ease .1s;
  }
  .gal-wurzel[data-hover="wachsen"] .gal:not(.gal-akkordeon) .gal-kachel:hover{
    transform:scale(1.12); z-index:6;
    box-shadow:0 18px 50px -12px rgba(0,0,0,.45);
    transition-delay:0s;
  }
  .gal-wurzel[data-hover="wachsen"] .gal:not(.gal-akkordeon):has(.gal-kachel:hover)
    .gal-kachel:not(:hover){ opacity:.5; }
}
@media(prefers-reduced-motion: reduce){
  .gal-akkordeon .gal-reihe, .gal-akkordeon .gal-kachel,
  .gal .gal-kachel.gal-fuell > img, .gal .gal-kachel.gal-fuell > video,
  .gal .gal-kachel.gal-fuell > .gal-auto,
  .gal-wurzel[data-hover="wachsen"] .gal-kachel{transition:none;}
  .gal-wurzel[data-hover="wachsen"] .gal:not(.gal-akkordeon) .gal-kachel:hover{transform:none;}
}

/* Abspieldreieck: macht sichtbar, dass hinter der Kachel ein Film steckt. Es
   wird IMMER mitgeliefert und hier ausgeblendet, sobald der Film wirklich
   laeuft - ob er das tut, weiss erst der Browser, und ui.js meldet es. */
.gal .gal-play{
  position:absolute; left:50%; top:50%; z-index:2;
  width:46px; height:46px; margin:-23px 0 0 -23px; border-radius:50%;
  background:rgba(0,0,0,.42); border:1px solid rgba(255,255,255,.55);
  pointer-events:none; transition:opacity .2s ease;
}
.gal .gal-play::after{
  content:''; position:absolute; left:18px; top:13px;
  border-left:15px solid #fff;
  border-top:9px solid transparent; border-bottom:9px solid transparent;
}
.gal .gal-laeuft .gal-play{opacity:0;}

/* Kachel-Video, das von selbst laeuft (autoplay in der meta.txt). Es soll NUR
   zeigen - der Klick gehoert der Lupe, wo der Film mit Ton und Bedienung
   laeuft. Deshalb faengt der Rahmen keine Zeigergesten ab.
   Der Rahmen ist 16:9, die Kachel meist nicht: aspect-ratio zusammen mit
   min-width/min-height fuellt sie wie ein object-fit:cover, das es fuer
   iframes nicht gibt. */
.gal .gal-auto{
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  width:auto; height:auto; aspect-ratio:16/9;
  min-width:100%; min-height:100%;
  border:0; display:block; background:#000; pointer-events:none;
}

/* ---------- Kontakt ---------- */
.kontakt-spalten{display:grid; grid-template-columns:minmax(220px,1fr) 2fr; gap:36px; align-items:start;}
@media(max-width:820px){ .kontakt-spalten{grid-template-columns:1fr;} }
.kontakt-daten{font-style:normal; color:var(--sub); font-size:.96rem;}
.kontakt-daten div{margin-bottom:6px;}
.cform{display:grid; gap:16px; max-width:560px;}
.cform label{display:block; font-size:.8rem; font-weight:600; color:var(--sub); margin-bottom:6px;}
.cform input, .cform textarea{
  width:100%; padding:12px 14px; border:1px solid var(--line);
  border-radius:var(--ecken); background:var(--surface); color:var(--ink); font:inherit;
}
.cform textarea{min-height:130px; resize:vertical;}
/* Honigtopf und unsichtbare Beschriftungen. Nicht display:none, sondern aus
   dem Bild geschoben: eine Vorlesefunktion soll die Beschriftung weiterhin
   finden, und ein ausgeblendetes Feld fuellt kein Bot aus. Gilt fuer JEDES
   Formular - auch das Newsletter-Feld in der Fusszeile. */
.hp{position:absolute; left:-9999px;}
.cform button{
  justify-self:start; font:inherit; font-weight:600; font-size:.9rem; cursor:pointer;
  padding:14px 26px; border:1px solid var(--ink); border-radius:var(--ecken);
  background:var(--ink); color:var(--bg);
}
.cform button:hover{background:var(--accent); border-color:var(--accent);}
.cform button:disabled{opacity:.5; cursor:not-allowed;}
.form-msg{font-size:.88rem; padding:12px 14px; border:1px solid var(--line);
          border-radius:var(--ecken); display:none;}
.form-msg.ok{display:block; border-color:var(--accent); color:var(--accent);}
/* Die Fehlerfarbe ist eine Variable, weil sie als EINZIGE feste Farbe in
   dieser Datei auf dunklem Grund durchfiel: dasselbe Rostrot, das auf hellem
   Papier kraeftig wirkt, verschwindet vor Schwarz fast. Und ausgerechnet die
   Meldung "Ihre Nachricht kam nicht an" darf man nicht uebersehen. */
.form-msg.err{display:block; border-color:var(--fehler); color:var(--fehler);}

/* ---------- Fusszeile ---------- */
/* Zwei Ebenen: oben der ausgebaute Bereich (nur wenn gefuellt), unten die
   Zeile mit Namen und Rechtstexten. Frueher trug das <footer> selbst die
   Klasse "wrap"; jetzt liegen zwei .wrap darin, damit der obere Bereich eine
   eigene Trennlinie und eigene Abstaende bekommen kann. */
footer{font-size:.84rem; color:var(--sub); position:relative; z-index:45;}
/* Die eigene Ebene aus demselben Grund wie beim Kopf: sonst laege die
   Fusszeile hinter den Zeichenflaechen (.leuchtspur, .klickfunken).
   Die Schalter "mitlaufend" und "fest" ueberschreiben position weiter
   oben und behalten dieselbe Ebene. */
/* padding-block statt der Kurzform "padding: X 0".
   Beide Kaesten tragen zusaetzlich die Klasse "wrap", und die setzt den
   seitlichen Rand ueber padding:0 var(--gutter). Die Kurzform hier stand
   spaeter in der Datei und hat ihn damit auf 0 zurueckgesetzt - die ganze
   Fusszeile klebte am Fensterrand, auf jeder Seite mit oberem Fussbereich.
   padding-block fasst nur oben und unten an und laesst die Seiten in Ruhe. */
.fuss-unten{
  padding-block:24px; display:flex; justify-content:space-between;
  flex-wrap:wrap; gap:12px; align-items:center;
}
.fuss-oben{
  padding-block:clamp(36px,5vw,58px) clamp(28px,4vw,40px);
  border-top:1px solid var(--line);
  display:grid; gap:clamp(24px,4vw,48px);
  /* Markenblock, Linkspalten, Newsletter. Die Linkspalten in der Mitte
     nehmen den Rest - sie sind der Teil, der wachsen darf. */
  grid-template-columns:minmax(200px,1fr) minmax(0,1.6fr) minmax(220px,1fr);
  align-items:start;
}
.fuss-oben + .fuss-unten{border-top:1px solid var(--line);}
@media(max-width:900px){
  .fuss-oben{grid-template-columns:1fr 1fr;}
  .fuss-marke{grid-column:1 / -1;}
}
@media(max-width:560px){
  .fuss-oben{grid-template-columns:1fr;}
}

/* Der Markenblock misst sich selbst, damit der Markenname darin auf die
   SPALTE rechnen kann und nicht auf das Fenster (siehe .fuss-name). */
.fuss-marke{container-type:inline-size;}
.fuss-logo{height:calc(var(--logo-hoehe, 32px) * 1.1); width:auto; display:block; margin-bottom:16px;}
.fuss-text{max-width:34ch; line-height:1.7;}
/* --- Symbolreihe unter dem Startbereich (design.socialPlatz) -------------
   Sie bekommt einen eigenen Streifen mit Luft nach oben UND unten. Das ist
   die eigentliche Anforderung: die Knoepfe sollen nicht zwischen Startbereich
   und ersten Abschnitt gequetscht werden, sondern selbst eine Station sein.
   Deshalb Abstaende in der Groessenordnung eines halben Abschnitts und keine
   Trennlinie - eine Linie machte daraus einen weiteren Abschnitt, und einen
   Abschnitt ohne Ueberschrift liest niemand als solchen. */
.social-reihe{
  display:flex; flex-wrap:wrap; justify-content:center;
  gap:clamp(14px,2vw,22px);
  padding:clamp(34px,5vw,58px) 24px clamp(38px,5.5vw,64px);
}
/* Groesser als im Fussbereich: dort sind sie eine Fussnote, hier eine
   Einladung. Die Zahlen sind das Anderthalbfache der Fusszeilenfassung. */
.social-reihe a, .social-reihe .ist-gesperrt{
  display:inline-flex; align-items:center; justify-content:center;
  width:58px; height:58px; border-radius:999px;
  border:1px solid color-mix(in srgb, var(--accent) 45%, var(--line));
  color:var(--ink); text-decoration:none;
  background:color-mix(in srgb, var(--bg) 70%, transparent);
  transition:color .2s, border-color .2s, transform .2s, box-shadow .2s;
}
.social-reihe a:hover{
  color:var(--accent); border-color:var(--accent); transform:translateY(-3px);
  box-shadow:0 0 calc(20px * var(--leuchtkraft))
             color-mix(in srgb, var(--accent) calc(45% * var(--leuchtkraft)), transparent);
}
.social-reihe .icon{width:26px; height:26px; vertical-align:0;}
.social-reihe a img{width:28px; height:28px; object-fit:contain; display:block;}

.fuss-social{display:flex; gap:14px; margin-top:20px; flex-wrap:wrap;}
.fuss-social a{
  display:inline-flex; align-items:center; justify-content:center;
  width:38px; height:38px; border:1px solid var(--line); border-radius:50%;
  color:var(--sub); text-decoration:none;
  transition:color .2s, border-color .2s;
}
.fuss-social a:hover{color:var(--accent); border-color:var(--accent);}
.fuss-social .icon{width:19px; height:19px; vertical-align:0;}
/* Hochgeladene Symbole. contain statt cover: ein Logo darf nicht beschnitten
   werden, auch wenn die Datei nicht quadratisch ist.
   Keine Einfaerbung - ein hochgeladenes Logo soll aussehen wie es ist. Wer
   es in der Zierfarbe will, nimmt eines der eingebauten Zeichen. */
.fuss-social a img{width:20px; height:20px; object-fit:contain; display:block;}

/* Die Spalten sitzen NEBENEINANDER, aber ohne feste Anzahl: wer eine vierte
   anlegt, bekommt eine vierte, ohne dass hier etwas zu aendern waere. */
.fuss-spalten{display:flex; flex-wrap:wrap; gap:clamp(24px,4vw,52px);}
.fuss-spalte{min-width:110px;}
.fuss-spalte h3{
  font-family:var(--schrift-mono); font-size:.72rem; font-weight:600;
  letter-spacing:.12em; text-transform:uppercase; color:var(--ink);
  margin-bottom:14px;
}
.fuss-spalte ul{list-style:none; display:grid; gap:9px;}
.fuss-spalte a, .fuss-spalte button{
  color:var(--sub); text-decoration:none; font-size:.86rem;
  background:none; border:0; padding:0; cursor:pointer; font:inherit;
  font-size:.86rem; text-align:left;
}
.fuss-spalte a:hover, .fuss-spalte button:hover{color:var(--accent);}
/* Eine Zeile ohne Ziel ist eine Angabe, kein Menuepunkt (siehe loader.js).
   Sie sieht aus wie die Links daneben, laesst sich aber nicht anklicken -
   und genau das soll man ihr auch ansehen: kein Zeigefinger, kein
   Farbwechsel beim Darueberfahren. */
.fuss-spalte .fuss-angabe{color:var(--sub); font-size:.86rem;}

/* Der Markenname statt des Logos (design.fussMarke: name).
   Dieselbe Hoehe wie das Logo an dieser Stelle, damit die Fusszeile nicht je
   nach Einstellung anders hoch wird. Die Farbe bleibt hier absichtlich
   schlicht - was eine Marke daraus macht, steht in ihrer site.css. */
.fuss-name{
  display:block; width:fit-content;
  margin-bottom:16px;
  font-family:var(--schrift-ueberschrift); font-weight:800;
  /* Die Groesse haengt an der SPALTE, nicht am Fenster.
     Vorher stand hier eine Fensterrechnung mit einer Obergrenze von 100 %.
     Auf einem breiten Schirm wurde die Schrift gross, die Spalte blieb
     schmal - und max-width kappte den Kasten mitten im Wort. Da der Name
     seine Farbe ueber background-clip:text bekommt, endete damit auch die
     Farbe: das letzte G stand unbemalt daneben, also unsichtbar. Aus
     NACHTUNDTAG wurde NACHTUNDTA.
     8cqw ist gerechnet, nicht geraten: elf gesperrte Grossbuchstaben sind
     rund 11,5 em breit, und 100/11,5 ergibt 8,7 - mit etwas Luft also 8. */
  font-size:min(1.5rem, 8cqw);
  letter-spacing:.28em; text-transform:uppercase;
  /* Zwei Dinge auf einmal:
     white-space:nowrap, damit der Name nicht mitten im Wort umbricht - bei
     einem Markennamen ist ein Umbruch immer falsch.
     padding-right, weil letter-spacing auch HINTER dem letzten Buchstaben
     einen Abstand setzt. Faerbt eine Marke den Namen ueber
     background-clip:text ein (siehe die NuT-Seite), reicht der Farbkasten
     sonst genau bis zu diesem Abstand - und der letzte Buchstabe steht
     unbemalt daneben, also unsichtbar. Aus NACHTUNDTAG wurde NACHTUNDTA. */
  white-space:nowrap;
  padding-right:.32em;
}

.fuss-news-titel{
  display:block; font-family:var(--schrift-mono); font-size:.72rem;
  letter-spacing:.12em; text-transform:uppercase; color:var(--ink);
  margin-bottom:14px;
}
/* Feld und Knopf sind EIN Bauteil mit einem gemeinsamen Rand - der Knopf ist
   das rechte Ende des Feldes, nicht ein zweites Ding daneben. */
.fuss-news-feld{
  display:flex; border:1px solid var(--line); border-radius:var(--ecken);
  overflow:hidden; background:var(--surface);
}
.fuss-news-feld input{
  flex:1 1 auto; min-width:0; border:0; background:none; color:var(--ink);
  font:inherit; font-size:.86rem; padding:11px 14px;
}
.fuss-news-feld input:focus{outline:none;}
.fuss-news-feld:focus-within{border-color:var(--accent);}
.fuss-news-feld button{
  flex:none; border:0; cursor:pointer; font:inherit; font-size:1rem;
  padding:0 16px; background:var(--accent); color:#fff;
}
.fuss-news-hinweis{display:block; margin-top:10px; font-size:.74rem; opacity:.8;}
.fuss-news .form-msg{margin-top:10px;}

.legal-links{display:flex; gap:18px;}
.legal-links button{background:none; border:none; padding:0; cursor:pointer;
                    color:inherit; font:inherit; font-size:.84rem; text-decoration:underline;}
.legal-links button:hover{color:var(--accent);}

/* ---------- Rechtstexte (Modal) ---------- */
.modal{position:fixed; inset:0; z-index:200; display:none; padding:24px;
       align-items:center; justify-content:center; background:rgba(31,59,51,.72);
       backdrop-filter:blur(5px);}
.modal.open{display:flex;}
.modal-box{background:var(--surface); border:1px solid var(--line); border-radius:var(--ecken);
           max-width:660px; width:100%; max-height:80vh; overflow:auto; padding:32px;}
.modal-box h3{font-size:1.2rem; margin-bottom:16px;}
.modal-box p, .modal-box li{font-size:.92rem; color:var(--sub); margin-bottom:10px;}
.modal-close{margin-top:20px; font:inherit; font-size:.86rem; cursor:pointer;
             background:none; border:1px solid var(--line); border-radius:var(--ecken);
             padding:10px 20px; color:var(--ink);}

/* Fliesstext im Flyover (Kurzbiografie). Schmaler als der Kasten: ein Absatz
   ueber die volle Breite eines grossen Bildschirms liest sich nicht mehr -
   das Auge findet den Zeilenanfang nicht wieder. */
.fly-allg-text{max-width:62ch; margin:0 auto;}
.fly-allg-text p{margin-bottom:1.1em; color:var(--sub); line-height:1.75;}
.fly-allg-text p:last-child{margin-bottom:0;}
.fly-allg-text em{font-style:normal; color:var(--accent);}

/* ---------- Flyover: einen Abschnitt vollstaendig zeigen ---------- */
/* Ebene und Inhalt baut ui.js (flyover()). Der Inhalt ist derselbe Abschnitt
   wie auf der Seite - deshalb steht hier NUR die Ebene drumherum und keine
   einzige Regel fuer Karten oder Kacheln. Kaeme hier eine dazu, saehe der
   Abschnitt drinnen anders aus als draussen, und genau das soll er nicht. */
.fly-allg{
  position:fixed; inset:0; z-index:210; display:flex;
  align-items:flex-start; justify-content:center;
  padding:clamp(12px,3vw,48px);
  background:rgba(6,8,10,.86); backdrop-filter:blur(6px);
  opacity:0; transition:opacity .22s ease;
}
/* Zwei Stufen, damit die Ebene weich aufgeht: [hidden] nimmt sie aus dem
   Dokumentfluss (auch fuer Screenreader), .auf blendet sie ein. Ein reines
   display:none/flex kann nicht ueberblenden. */
.fly-allg[hidden]{display:none;}
.fly-allg.auf{opacity:1;}

.fly-allg-box{
  background:var(--bg); border:1px solid var(--line); border-radius:var(--ecken);
  box-shadow:var(--leuchten);
  width:100%; max-width:1120px; max-height:92vh;
  display:flex; flex-direction:column; overflow:hidden;
}
.fly-allg-kopf{
  display:flex; align-items:center; gap:16px; flex:none;
  padding:18px clamp(16px,3vw,32px); border-bottom:1px solid var(--line);
  background:var(--surface);
}
.fly-allg-titel{font-size:1.15rem; flex:1; min-width:0;}
.fly-allg-zu{
  font:inherit; font-size:.84rem; cursor:pointer; flex:none;
  background:none; border:1px solid var(--line); border-radius:var(--ecken);
  padding:8px 16px; color:var(--ink);
}
.fly-allg-zu:hover{border-color:var(--accent); color:var(--accent);}
/* Nur der Koerper scrollt, nicht die ganze Ebene: sonst wandert die
   Ueberschrift mitsamt Schliessknopf aus dem Bild, und bei einer langen Liste
   sucht man den Ausgang. */
.fly-allg-koerper{
  flex:1; min-height:0; overflow:auto;
  padding:clamp(18px,3vw,32px);
}
.fly-allg-leer{color:var(--sub); font-size:.94rem;}

@media(max-width:640px){
  .fly-allg{padding:0;}
  .fly-allg-box{max-height:100vh; height:100vh; border:0; border-radius:0;}
}

/* ============ Lupe: Galeriebild gross ansehen ============ */
/* Die Ebene baut ui.js selbst, damit nicht in jeder index.html dasselbe
   Markup stehen muss. Farben kommen aus den Variablen der jeweiligen Zone. */
.gal [data-lupe]{cursor:zoom-in;}
.gal [data-lupe]:focus-visible{outline:2px solid var(--accent); outline-offset:2px;}

.lupe{
  position:fixed; inset:0; z-index:200; display:none;
  align-items:center; justify-content:center; padding:clamp(16px,4vw,56px);
  background:rgba(6,8,10,.92); backdrop-filter:blur(6px);
}
.lupe.auf{display:flex;}

/* Medium links, Text rechts. Der Text bekommt eine feste Spaltenbreite und
   darf bei Bedarf selbst scrollen - so passen auch lange Beschreibungen
   hinein, ohne dass das Bild kleiner wird. */
/* Ohne Beschreibungstext steht der Titel UNTER dem Medium und dieses
   bleibt mittig. Erst mit echtem Text wird daraus die zweispaltige
   Aufteilung - ui.js setzt dafuer die Klasse mit-text. */
.lupe-inhalt{
  display:flex; flex-direction:column; align-items:center; gap:clamp(12px,2vw,20px);
  max-width:min(1500px,100%); max-height:100%; margin:0;
}
.lupe-inhalt.mit-text{
  flex-direction:row; align-items:center; gap:clamp(18px,3vw,38px);
}
.lupe-buehne{
  display:flex; align-items:center; justify-content:center;
  min-width:0; flex:1 1 auto;
}
.lupe-buehne img, .lupe-buehne video{
  max-width:100%; max-height:84vh; object-fit:contain; display:block;
}
.lupe-buehne iframe{
  width:min(1100px,60vw); aspect-ratio:16/9; max-height:84vh; border:0; display:block;
}

.lupe figcaption{
  color:#D8E4DC; font-size:.92rem; line-height:1.6;
  text-align:center; max-width:70ch;
}
.lupe-inhalt.mit-text figcaption{
  flex:0 0 clamp(260px, 26vw, 400px);
  align-self:stretch; display:flex; flex-direction:column; justify-content:center;
  max-height:84vh; overflow-y:auto; text-align:left; max-width:none;
}
.lupe figcaption h3{
  color:#fff; font-size:1.15rem; line-height:1.3; margin-bottom:12px;
}
.lupe figcaption p{margin-bottom:.9em;}
.lupe figcaption p:last-child{margin-bottom:0;}
/* Ohne Beschreibung soll das Medium mittig stehen, nicht nach links versetzt */
.lupe figcaption[hidden]{display:none;}

/* Schmale Fenster: Text unter das Medium, sonst bleibt fuer beides zu wenig */
@media(max-width:900px){
  .lupe-inhalt{flex-direction:column; align-items:center;}
  .lupe figcaption{
    flex:0 0 auto; align-self:auto; max-height:24vh;
    text-align:center; justify-content:flex-start;
  }
  .lupe-buehne img, .lupe-buehne video{max-height:58vh;}
  .lupe-buehne iframe{width:88vw; max-height:58vh;}
}

.lupe button{
  position:absolute; border:1px solid rgba(255,255,255,.28);
  background:rgba(0,0,0,.42); color:#fff; cursor:pointer;
  width:46px; height:46px; border-radius:50%; font-size:1.5rem; line-height:1;
  display:flex; align-items:center; justify-content:center;
  transition:background-color .18s, border-color .18s;
}
.lupe button:hover{background:rgba(0,0,0,.72); border-color:rgba(255,255,255,.6);}
.lupe button:focus-visible{outline:2px solid #fff; outline-offset:2px;}
.lupe-zu{top:16px; right:16px;}
.lupe-vor{left:16px;  top:50%; transform:translateY(-50%);}
.lupe-nach{right:16px; top:50%; transform:translateY(-50%);}
@media(max-width:700px){
  .lupe-vor{left:8px;} .lupe-nach{right:8px;}
  .lupe-zu{top:8px; right:8px;}
}
@media (prefers-reduced-motion: reduce){ .lupe button{transition:none;} }

/* Produkt-Kategorien. Zwei Ebenen: h3 fuer Kategorien, h4 fuer Unterkategorien. */
.tpl-kategorie{margin:38px 0 6px; font-size:1.15rem;}
.tpl-kategorie:first-child{margin-top:0;}
h4.tpl-kategorie{font-size:1rem; opacity:.85; margin-top:26px;}
.tpl-kategorie-text{color:var(--sub); font-size:.92rem; max-width:60ch; margin-bottom:18px;}

/* ---------- Beschriftung auf der Galeriekachel ---------- */
/* Oben die Credit-Zeile, unten die Schlagworte. Beide liegen AUF dem Bild,
   nicht darunter: das Raster behaelt seine geschlossene Flaeche.
   Sichtbar werden sie erst beim Zeigen auf die Kachel - dauerhaft
   eingeblendet verdecken sie genau das, was man ansehen will.
   Der Verlauf dahinter ist noetig, weil ein heller Bildausschnitt weissen
   Text sonst verschluckt. */
.gal .gal-kachel{position:relative;}
/* Die Regel .gal div setzt aspect-ratio, display:flex, overflow und position
   fuer ALLE divs in der Galerie - sie ist staerker als eine einzelne Klasse
   und wuerde die Zeile quadratisch und zentriert machen. Deshalb hier ein
   Selektor mit zwei Klassen und ausdrueckliches Zuruecksetzen. */
.gal .gal-kachel > .gal-zeile,
.gal .gal-kachel > .gal-tags{
  aspect-ratio:auto; display:block; border:0;
  position:absolute; left:0; right:0; z-index:2;
  font-family:var(--schrift-mono); letter-spacing:.02em; color:#fff;
  /* Umbruch ausdruecklich erlaubt - lange Zeilen sollen mehrzeilig stehen,
     nicht abgeschnitten werden. */
  white-space:normal; overflow-wrap:anywhere;
  pointer-events:none;   /* der Klick soll die Lupe oeffnen … */
  opacity:0; transition:opacity .18s ease, transform .18s ease;
}
.gal .gal-kachel > .gal-zeile{
  /* Hoehe begrenzen: auf einer kleinen Bento-Kachel wuerde eine lange Zeile
     sonst ueber das Bild hinauslaufen. Was hier abgeschnitten wird, steht
     vollstaendig in der Lupe. */
  top:0; max-height:58%; overflow:hidden;
  padding:10px 12px 18px; font-size:.72rem; line-height:1.45;
  transform:translateY(-6px);
  background:linear-gradient(180deg, rgba(0,0,0,.68) 0%, rgba(0,0,0,.42) 55%, rgba(0,0,0,0) 100%);
}
/* Schlagworte unten: Technik, Kunde, Gewerk - was man einem Bild sonst nicht
   ansieht. Getrennt von der Credit-Zeile, damit oben der Satz und unten die
   Stichworte stehen. */
.gal .gal-kachel > .gal-tags{
  bottom:0; max-height:52%; overflow:hidden;
  display:flex; flex-wrap:wrap; gap:5px;
  align-items:flex-end; justify-content:flex-start;
  padding:18px 12px 10px; font-size:.66rem; line-height:1.35;
  transform:translateY(6px);
  background:linear-gradient(0deg, rgba(0,0,0,.68) 0%, rgba(0,0,0,.42) 55%, rgba(0,0,0,0) 100%);
}
.gal .gal-kachel > .gal-tags .gal-tag{
  border:1px solid rgba(255,255,255,.4); border-radius:999px;
  padding:1px 8px; white-space:nowrap;
}
.gal .gal-kachel:hover > .gal-zeile,        .gal .gal-kachel:hover > .gal-tags,
.gal .gal-kachel:focus-within > .gal-zeile, .gal .gal-kachel:focus-within > .gal-tags{
  opacity:1; transform:none;
}
/* Ohne Maus gibt es kein Zeigen - auf dem Handy bleibt die Beschriftung
   deshalb dauerhaft stehen, sonst waere sie dort nie zu sehen. */
@media(hover:none){
  .gal .gal-kachel > .gal-zeile, .gal .gal-kachel > .gal-tags{opacity:1; transform:none;}
}
.gal .gal-kachel > .gal-zeile .tag, .gal .gal-kachel > .gal-tags .tag{
  color:var(--accent); font-weight:600;
  pointer-events:auto;   /* … nur die Hashtags fangen ihn ab */
}
.gal .gal-kachel > .gal-zeile a.tag, .gal .gal-kachel > .gal-tags a.tag{
  text-decoration:none; border-bottom:1px solid currentColor;
}
.gal .gal-kachel > .gal-zeile a.tag:hover, .gal .gal-kachel > .gal-tags a.tag:hover{color:#fff;}
@media(max-width:600px){
  .gal .gal-kachel > .gal-zeile{font-size:.66rem; padding:8px 10px 14px;}
  .gal .gal-kachel > .gal-tags{font-size:.6rem; padding:14px 10px 8px;}
}

/* ---------- Logo und Markenname im Kopf ---------- */
/* Den Block baut loader.js um den vorhandenen Markennamen herum, damit
   nicht in jeder index.html dasselbe Markup stehen muss. */
.marke-block{display:flex; align-items:center; gap:10px; min-width:0;}
.marke-block[data-pos="oben"], .marke-block[data-pos="unten"]{
  flex-direction:column; align-items:flex-start; gap:4px;
}
.marke-logo{height:var(--logo-hoehe, 32px); width:auto; display:block; flex:none;}
/* Ein breites Logo mit Schriftzug fuellt auf dem Handy sonst die ganze Zeile
   und schiebt den Menueknopf hinaus. Kleiner statt abgeschnitten: ein halbes
   Logo sieht kaputt aus, ein kleineres nur kleiner. */
@media(max-width:560px){
  .marke-logo{height:calc(var(--logo-hoehe, 32px) * .72);}
}
/* Logo mit eingebautem Schriftzug: der Markenname bleibt im Dokument (fuer
   Vorlesefunktionen und Suchmaschinen), ist aber nicht zu sehen. */
.marke-nur-logo .marke, .marke-nur-logo .brand{
  position:absolute; width:1px; height:1px; overflow:hidden;
  clip-path:inset(50%); white-space:nowrap;
}
/* Der hervorgehobene Teil des Markennamens: "GRAF *Systems*".
   font-style:normal, weil <em> sonst kursiv waere - hier soll nur die
   Farbe wechseln. */
.brand em, .marke em{font-style:normal; color:var(--accent);}

/* ============================================================================
   Bereiche, Aufmacher, Rueckblick, Newsletter

   Vier Abschnittstypen, die zusammen eine Marke mit mehreren Bereichen
   beschreiben: wer darunter steht (Bereiche), was als Naechstes ansteht
   (Aufmacher), was gewesen ist (Rueckblick), wie man in Verbindung bleibt
   (Newsletter).

   Entstanden fuer die NACHTUNDTAG-Seite, aber bewusst ohne deren Farben:
   die kommen aus --accent, und den setzt jeder Eintrag fuer sich selbst
   (akzent: in der meta.txt). Deshalb steht hier keine einzige feste Farbe
   ausser Schwarz und Weiss.
   ========================================================================= */

/* ---------- Gesperrt ----------
   Ein Knopf, den es geben SOLL, den es aber noch nicht gibt: Ticketverkauf
   ohne Ticketsystem, eine Unterseite, die noch nicht existiert.

   Sichtbar und deutlich nicht benutzbar - nicht halb ausgegraut. Ein Knopf,
   bei dem man raten muss, ob er kaputt ist, ist schlechter als gar keiner.
   Der Mauszeiger sagt es zusaetzlich; per Tastatur ist er uebersprungen,
   weil disabled ihn aus der Reihenfolge nimmt. */
.ist-gesperrt{
  opacity:.45; cursor:not-allowed; filter:saturate(.5);
  text-decoration:none;
}

/* ---------- Bereiche ---------- */
.bereich-grid{display:grid; gap:22px; grid-template-columns:repeat(auto-fit,minmax(320px,1fr));}
.bereich{
  position:relative; overflow:hidden;
  border:1px solid color-mix(in srgb, var(--accent) 55%, transparent);
  border-radius:var(--ecken);
  background:
    radial-gradient(120% 140% at 100% 50%,
      color-mix(in srgb, var(--accent) 22%, transparent) 0%, transparent 62%),
    var(--bg-warm);
  box-shadow:0 0 calc(28px * var(--leuchtkraft))
             color-mix(in srgb, var(--accent) calc(26% * var(--leuchtkraft)), transparent);
  min-height:230px; display:flex;
  /* Die Karte misst sich selbst.
     Ob Text und Zeichnung nebeneinander passen, haengt an der Breite DIESER
     KARTE - nicht an der des Fensters. Drei Karten nebeneinander sind auf
     einem breiten Schirm genauso schmal wie eine einzelne auf dem Telefon,
     und eine Fensterabfrage kann das nicht unterscheiden. */
  container-type:inline-size;
}
/* Die Zeichnung sitzt im fertigen Kartenbild rechts. Gezeigt wird nur SIE -
   der eingebrannte Text der Vorlage bleibt ausserhalb des Ausschnitts, weil
   er hier als echter Text darueber steht (aenderbar, vorlesbar, mitwachsend).
   Zugeschnitten wird im Browser ueber background-position; eine zweite,
   beschnittene Bilddatei waere ein Duplikat, das beim naechsten Austausch
   des Motivs stehenbliebe. */
.bereich-kunst{
  position:absolute; inset:0 0 0 auto; width:46%;
  background-repeat:no-repeat; background-size:auto 165%;
  background-position:82% center;
  -webkit-mask-image:linear-gradient(90deg, transparent, #000 38%);
          mask-image:linear-gradient(90deg, transparent, #000 38%);
  pointer-events:none;
}
.bereich-kunst[data-kunst="links"]{
  inset:0 auto 0 0; background-position:22% center;
  -webkit-mask-image:linear-gradient(270deg, transparent, #000 38%);
          mask-image:linear-gradient(270deg, transparent, #000 38%);
}
/* "ganz": das Bild IST die Tafel - fertig gestaltet, mit Rahmen und Motiv.
   Kein Ausschnitt, keine Abdunklung. Der Text liegt darueber und bleibt
   dadurch aenderbar; wo er im Bild schon steht, wird er beim naechsten
   Austausch der Datei daraus entfernt. */
.bereich-kunst[data-kunst="ganz"]{
  width:100%; background-size:cover; background-position:center;
  -webkit-mask-image:none; mask-image:none; opacity:1;
}
/* --- Die Karte IST das Bild ("kunst: ganz") ---------------------------
   Bild und Text liegen im selben Rasterfeld uebereinander. Das Bild steht
   im Fluss und gibt die Hoehe vor; der Text legt sich darueber, ohne die
   Karte zu strecken. Waechst der Text auf einer schmalen Karte doch ueber
   das Bild hinaus, waechst die Karte mit - beschnitten wird nichts.
   (Begruendung ausfuehrlich in sections.js, bei "vollBild".) */
.bereich-voll{
  display:grid; grid-template-columns:1fr;
  min-height:0; background:none;
  /* Die Tafel bringt ihr eigenes Motiv mit, aber keinen Rand - und ohne Rand
     verliert sie sich auf schwarzem Grund. Der Rand traegt die Farbe DIESES
     Kollektivs, nicht die der Seite: drei Karten nebeneinander sollen sich
     unterscheiden lassen, ohne dass man die Wortmarke liest. */
  border:1px solid color-mix(in srgb, var(--accent) 60%, transparent);
  box-shadow:0 0 calc(26px * var(--leuchtkraft))
             color-mix(in srgb, var(--accent) calc(24% * var(--leuchtkraft)), transparent);
}
.bereich-voll > *{grid-area:1 / 1;}
.bereich-kunst-voll{
  display:block; width:100%; height:100%; object-fit:cover;
  border-radius:var(--ecken);
}
.bereich-voll .bereich-text{
  max-width:100%; justify-content:flex-start;
  /* Enger als auf einer gewoehnlichen Karte: hier ist der Platz durch das
     Bild vorgegeben und nicht durch den Text. */
  padding:clamp(14px, 4cqw, 26px);
  gap:4px;
}
/* Ein Schleier unter dem Text - und zwar nur dort, wo der Text steht.
   Die fertigen Kartenbilder haben die Textseite meistens dunkel gehalten;
   "meistens" reicht aber nicht. Sobald ein Bild ein Foto ueber die ganze
   Karte legt (bei NuT die Sunsound-Karte mit dem Sonnenuntergang), steht
   weisse Schrift auf hellem Himmel. Der Verlauf laeuft nach rechts aus,
   damit er auf den dunklen Karten gar nicht auffaellt und das Motiv auf
   der rechten Seite frei bleibt. */
.bereich-voll .bereich-text::before{
  content:''; position:absolute; inset:0; z-index:-1; pointer-events:none;
  border-radius:var(--ecken);
  background:linear-gradient(90deg,
    rgba(0,0,0,.72) 0%, rgba(0,0,0,.6) 38%, rgba(0,0,0,.24) 66%, transparent 88%);
}
/* Der Text muss in die Hoehe des Bildes passen, sonst zieht er die Karte
   doch wieder auseinander. Deshalb ist hier alles eine Spur kleiner und
   enger als auf einer gewoehnlichen Bereichskarte. */
/* Mausverhalten - dasselbe wie bei Aufmacher, Newsletter und Rueckblick:
   leicht anheben, Schein in der EIGENEN Zierfarbe des Eintrags verstaerken,
   das Bild eine Spur naeher holen. Die Karte ist eine grosse, anklickbare
   Flaeche und soll sich auch so anfuehlen.

   Der Schein muss hier ausdruecklich gesetzt werden: fuer die Vollbildkarte
   ist er weiter oben abgeschaltet (border:0, box-shadow:none), weil das
   fertige Kartenbild seinen Rahmen schon mitbringt. Im Ruhezustand soll
   also nichts leuchten - beim Darueberfahren schon. */
.bereich-voll{
  transition:transform .28s ease, box-shadow .28s ease;
}
.bereich-voll .bereich-kunst-voll{transition:transform .6s ease;}
.bereich-voll:hover{
  transform:translateY(-4px);
  box-shadow:0 0 calc(60px * var(--leuchtkraft))
             color-mix(in srgb, var(--accent) calc(45% * var(--leuchtkraft)), transparent);
}
.bereich-voll:hover .bereich-kunst-voll{transform:scale(1.03);}
/* Der Knopf fuellt sich mit der Farbe des Kollektivs, sobald die Karte
   angefasst wird - auch dann, wenn der Zeiger gar nicht auf ihm steht. Er
   ist der Knopf DIESER Karte, nicht ein eigenes Ziel daneben. */
.bereich-voll:hover .bereich-knopf{
  background:var(--accent); color:#000; border-color:var(--accent);
}

.bereich-voll .bereich-punkte li{font-size:.68rem; line-height:1.7;}
.bereich-voll .bereich-lede{font-size:.76rem; line-height:1.5; margin-top:0;}
.bereich-voll .bereich-unter{font-size:.72rem; letter-spacing:.2em;}
.bereich-voll .bereich-hinweis{font-size:.58rem; padding:3px 8px;}
.bereich-voll .bereich-knopf{padding:7px 13px; font-size:.68rem;}
.bereich-text{
  position:relative; z-index:2; padding:26px 28px;
  display:flex; flex-direction:column; align-items:flex-start; gap:8px;
  max-width:58%;
}
/* Die Wortmarke wird ueber die BREITE bemessen, nicht ueber die Hoehe.
   Ein Schriftzug hat so viele Seitenverhaeltnisse wie es Marken gibt -
   "BÖSEBÄSSE" ist breit und flach, ein Wort mit Zeichen darueber hoch und
   schmal. Eine feste Hoehe macht das eine winzig und das andere riesig.
   Ueber die Breite behaelt jede Marke den Anteil an der Karte, den ihr
   Entwurf ihr gegeben hat.

   cqw und nicht vw: gemessen wird die KARTE (.bereich ist ein Container),
   nicht das Fenster. Drei Karten nebeneinander sind auf einem breiten
   Schirm genauso schmal wie eine einzelne auf dem Telefon. */
.bereich-wortmarke{
  width:min(48cqw, 320px); height:auto; display:block;
  margin-bottom:2px;
}
.bereich-name{font-size:clamp(1.4rem,3vw,2rem); line-height:1.05;}
.bereich-unter{
  font-family:var(--schrift-mono); font-size:.8rem; letter-spacing:.22em;
  color:var(--accent); text-transform:uppercase;
}
.bereich-punkte{list-style:none; margin-top:4px;}
.bereich-punkte li{
  font-family:var(--schrift-mono); font-size:.74rem; letter-spacing:.1em;
  color:var(--ink); text-transform:uppercase; line-height:1.9;
}
.bereich-lede{color:var(--sub); font-size:.9rem; margin-top:2px;}
/* Pflichtkennzeichnungen ("EIN PROJEKT VON ...") stehen klein, aber nicht
   versteckt: sie sind eine Aussage ueber die Marke, keine Fussnote. */
.bereich-hinweis{
  font-family:var(--schrift-mono); font-size:.62rem; letter-spacing:.16em;
  text-transform:uppercase; color:var(--sub);
  border:1px solid var(--line); border-radius:999px; padding:4px 10px;
}
.bereich-knopf{
  margin-top:auto; display:inline-flex; align-items:center; gap:6px;
  font-family:var(--schrift-mono); font-size:.74rem; letter-spacing:.08em;
  text-transform:uppercase; color:var(--accent);
  border:1px solid color-mix(in srgb, var(--accent) 60%, transparent);
  border-radius:999px; padding:9px 16px; background:none;
  transition:background .18s, color .18s;
}
a.bereich-knopf:hover{background:var(--accent); color:#000;}
/* Schmale Karte: der Text nimmt die volle Breite, die Zeichnung rueckt
   dahinter. */
@container (max-width: 520px){
  .bereich{min-height:0;}
  .bereich-text{max-width:100%; padding:20px;}
  /* Der Ausschnitt bleibt AUCH hier bestehen.
     Hier stand kurz "background-size:cover" fuer die volle Breite - und damit
     war der gesetzte Text der Bildvorlage wieder da, quer unter dem echten
     Text. Genau das, was der Ausschnitt verhindern soll. Auf schmalen Karten
     rueckt die Zeichnung deshalb nur nach hinten, sie wird nicht ausgepackt. */
  .bereich-kunst{
    width:100%; opacity:.3; background-size:auto 210%;
    background-position:88% center;
    -webkit-mask-image:linear-gradient(90deg, transparent, #000 45%);
            mask-image:linear-gradient(90deg, transparent, #000 45%);
  }
}

/* ---------- Aufmacher ---------- */
.aufmacher{
  position:relative; overflow:hidden; border-radius:var(--ecken);
  box-shadow:0 0 calc(46px * var(--leuchtkraft))
             color-mix(in srgb, var(--accent) calc(30% * var(--leuchtkraft)), transparent);
  min-height:clamp(320px, 34vw, 430px); display:flex; align-items:stretch;
}
/* Der Rahmen laeuft von links nach rechts durch die beiden Hausfarben - bei
   NACHTUNDTAG also vom Violett der Nacht ins Warme des Sonnenuntergangs.
   Genau das ist die Aussage der Marke, und der naechste Event ist die Stelle,
   an der sie steht.
   Umgesetzt als Ring aus zwei Masken und nicht als "border-image": das kennt
   keine abgerundeten Ecken und wuerde den Verlauf ueber Eck abschneiden.
   Eine Seite ohne zweite Farbe bekommt --accent-2 = --accent (siehe oben bei
   den Variablen) und damit einen gewoehnlichen einfarbigen Rand. */
.aufmacher::after{
  content:''; position:absolute; inset:0; z-index:3; pointer-events:none;
  border-radius:inherit; padding:1px;
  background:linear-gradient(90deg, var(--accent), var(--accent-2));
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor; mask-composite:exclude;
}
.aufmacher-bild{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; z-index:0;
}
/* Der Verlauf laeuft nach LINKS aus, nicht gleichmaessig ueber das ganze
   Bild: der Text steht links, das Motiv rechts. Ein Schleier ueber allem
   macht den Text lesbar und das Foto tot. */
.aufmacher-schleier{
  position:absolute; inset:0; z-index:1;
  background:linear-gradient(90deg,
    color-mix(in srgb, var(--bg) 92%, transparent) 0%,
    color-mix(in srgb, var(--bg) 66%, transparent) 42%,
    transparent 78%);
}
.aufmacher-inhalt{
  position:relative; z-index:2; padding:clamp(22px,3.4vw,40px);
  display:flex; flex-direction:column; align-items:flex-start; gap:9px;
  max-width:min(560px, 68%);
}
.aufmacher-kicker{
  font-family:var(--schrift-mono); font-size:.7rem; letter-spacing:.28em;
  text-transform:uppercase; color:var(--sub);
}
.aufmacher-titel{font-size:clamp(1.9rem,4.6vw,3.1rem); line-height:1;}
.aufmacher-unter{
  font-family:var(--schrift-mono); font-size:clamp(.8rem,1.5vw,1rem);
  letter-spacing:.14em; text-transform:uppercase; color:var(--ink);
}
.aufmacher-daten{display:flex; flex-direction:column; gap:4px; margin-top:8px;}
.aufmacher-zeile{display:flex; align-items:center; gap:10px;}
.aufmacher-zeichen{display:inline-flex; color:var(--accent);}
.aufmacher-datum span:last-child{
  font-size:clamp(1.2rem,2.4vw,1.7rem); font-family:var(--schrift-ueberschrift);
}
.aufmacher-ort span:last-child{
  font-family:var(--schrift-mono); font-size:.84rem; letter-spacing:.12em;
  text-transform:uppercase;
}
.aufmacher-platz{color:var(--accent); font-size:.9rem; padding-left:34px;}
.aufmacher-text{color:var(--sub); font-size:.92rem;}
.aufmacher-marken{
  font-family:var(--schrift-mono); font-size:.72rem; letter-spacing:.14em;
  color:var(--sub); margin-top:6px;
}
.aufmacher-knoepfe{display:flex; flex-wrap:wrap; gap:12px; margin-top:14px;}
@media(max-width:760px){
  .aufmacher-inhalt{max-width:100%;}
  .aufmacher-schleier{
    background:linear-gradient(180deg,
      color-mix(in srgb, var(--bg) 50%, transparent) 0%,
      color-mix(in srgb, var(--bg) 90%, transparent) 55%);
  }
}

/* ---------- Rueckblick ---------- */
.rueck-grid{display:grid; gap:18px; grid-template-columns:repeat(auto-fill,minmax(210px,1fr));}
.rueck{
  position:relative; overflow:hidden; border-radius:var(--ecken);
  aspect-ratio:313/429; display:block;
  /* Dieselbe Begruendung wie bei den Kollektivkarten: die Flyer laufen unten
     ins Schwarze aus und haetten sonst keine Unterkante. */
  border:1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  box-shadow:0 0 calc(22px * var(--leuchtkraft))
             color-mix(in srgb, var(--accent) calc(22% * var(--leuchtkraft)), transparent);
  transition:transform .25s ease, box-shadow .25s ease;
}
.rueck:hover{
  transform:translateY(-4px);
  box-shadow:0 0 calc(38px * var(--leuchtkraft))
             color-mix(in srgb, var(--accent) calc(38% * var(--leuchtkraft)), transparent);
}
.rueck-bild{position:absolute; inset:0; width:100%; height:100%; object-fit:cover;}
/* Der Text sitzt in der unteren Haelfte - dort, wo die Kartenvorlage ohnehin
   dunkel auslaeuft. Der eigene Verlauf haelt ihn auch dann lesbar, wenn
   jemand spaeter ein helleres Bild einsetzt. */
.rueck-text{
  position:absolute; inset:auto 0 0 0; z-index:2;
  padding:14px 12px 18px; text-align:center;
  display:flex; flex-direction:column; gap:2px;
  background:linear-gradient(180deg, transparent, rgba(0,0,0,.8) 42%);
}
.rueck-titel{
  font-size:clamp(1rem,1.7vw,1.3rem); line-height:1.05;
  color:var(--accent); text-transform:uppercase;
}
.rueck-unter{
  font-family:var(--schrift-mono); font-size:.64rem; letter-spacing:.2em;
  text-transform:uppercase; color:#e9e6ea;
}
.rueck-datum{
  font-family:var(--schrift-mono); font-size:.84rem; letter-spacing:.08em;
  color:#fff; margin-top:8px;
}
.rueck-ort{
  font-family:var(--schrift-mono); font-size:.6rem; letter-spacing:.14em;
  text-transform:uppercase; color:#c9c4cc;
}

/* ---------- Newsletter ---------- */
.news{
  position:relative; overflow:hidden; border-radius:var(--ecken);
  border:1px solid color-mix(in srgb, var(--accent) 60%, transparent);
  box-shadow:0 0 calc(40px * var(--leuchtkraft))
             color-mix(in srgb, var(--accent) calc(28% * var(--leuchtkraft)), transparent);
  display:flex; align-items:center; min-height:210px; background:#08050a;
}
/* Wie bei den Bereichen: aus der fertigen Grafik wird nur der bildliche Teil
   gezeigt, der gesetzte Text bleibt draussen und steht daneben als HTML. */
.news-kunst{
  position:absolute; inset:0 auto 0 0; width:46%;
  background-repeat:no-repeat; background-size:auto 118%;
  background-position:24% center;
  -webkit-mask-image:linear-gradient(270deg, transparent, #000 42%);
          mask-image:linear-gradient(270deg, transparent, #000 42%);
}
.news-kunst[data-kunst="rechts"]{
  inset:0 0 0 auto; background-position:76% center;
  -webkit-mask-image:linear-gradient(90deg, transparent, #000 42%);
          mask-image:linear-gradient(90deg, transparent, #000 42%);
}
.news-text{
  position:relative; z-index:2; margin-left:auto; width:min(560px, 56%);
  padding:26px clamp(22px,3vw,40px); display:flex; flex-direction:column; gap:8px;
}
.news-titel{font-size:clamp(1.7rem,4vw,2.7rem); line-height:1; color:#fff;}
.news-lede{color:var(--accent); font-size:.94rem;}
.news-feld{
  display:flex; align-items:center; gap:10px; margin-top:8px;
  border:1px solid var(--accent); border-radius:var(--ecken);
  padding:8px 14px; background:rgba(0,0,0,.35);
}
.news-feld .news-zeichen{color:var(--accent); display:inline-flex;}
.news-feld input{
  flex:1; min-width:0; background:none; border:0; color:#fff;
  font-family:var(--schrift-text); font-size:.96rem; padding:6px 0;
}
.news-feld input::placeholder{color:var(--accent); opacity:.85;}
.news-feld button{
  background:none; border:0; color:var(--accent); cursor:pointer;
  display:inline-flex; padding:4px;
}
.news-feld.ist-gesperrt{opacity:.5; cursor:not-allowed; filter:saturate(.5);}
.news-feld.ist-gesperrt input, .news-feld.ist-gesperrt button{cursor:not-allowed;}
.news-hinweis{color:var(--sub); font-size:.74rem;}
@media(max-width:760px){
  .news{flex-direction:column; align-items:stretch;}
  /* Auch hier bleibt der Ausschnitt bestehen - ein "cover" ueber die volle
     Breite holt den gesetzten Text der Vorlage zurueck, und er stuende dann
     doppelt da (einmal als Pixel, einmal als HTML darunter). */
  .news-kunst{position:relative; inset:auto; width:100%; height:150px;
    background-size:auto 260%; background-position:20% center;
    -webkit-mask-image:linear-gradient(180deg, #000 62%, transparent);
            mask-image:linear-gradient(180deg, #000 62%, transparent);}
  .news-text{width:100%; margin-left:0;}
}

/* ---------- Personen: Abzeichen und anklickbare Karte ---------- */
.person-abzeichen{
  display:inline-block; margin-bottom:10px;
  font-family:var(--schrift-mono); font-size:.6rem; letter-spacing:.16em;
  text-transform:uppercase; color:var(--accent);
  border:1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius:999px; padding:3px 9px;
}
.person{transition:border-color .2s, box-shadow .2s;}
a.person-klick{text-decoration:none; display:block;}
a.person-klick:hover{border-color:var(--accent);}

/* ============================================================================
   Startbereich, Bauform "geteilt"

   Text links, das Markenzeichen gross in der Mitte, darunter die Knoepfe und
   eine Leiste mit den Bereichen. Fuer Dachmarken, die mehrere Welten unter
   sich haben - das Hintergrundfoto zeigt sie, die Leiste benennt sie.
   ========================================================================= */
/* Der obere Abstand haelt nur die Kopfzeile frei - der Text sitzt darunter
   und soll DORT beginnen, nicht in der Fensterhoehe schwimmen. Die Mitte
   haelt das Markenzeichen (align-self weiter unten). */
.hero-geteilt{
  min-height:min(100vh, 900px);
  display:flex; flex-direction:column; justify-content:center;
  padding:calc(var(--kopf-hoehe, 88px) + clamp(8px,2vh,28px)) 0 clamp(36px,6vh,64px);
}
/* width:100% ist hier NICHT ueberfluessig.
   Beide Kaesten tragen zusaetzlich die Klasse "wrap", und die bringt
   margin:0 auto mit. In einem Flex-Kasten hebt ein automatischer Rand auf
   der Querachse die Dehnung auf - der Kasten schrumpft dann auf die Breite
   seines Inhalts, und die Markenleiste stand als einzelne Spalte in der
   Mitte statt als Dreierreihe ueber die volle Breite. */
.hero-geteilt-raster{
  display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);
  align-items:center; gap:clamp(20px,4vw,56px); flex:1; width:100%;
}
/* Der Textblock steht OBEN, das Zeichen bleibt mittig.
   Im Entwurf beginnt die Schlagzeile kurz unter der Kopfzeile, waehrend das
   Markenzeichen die Mitte des Bildes haelt. Beides mittig zu setzen macht
   aus zwei Aussagen eine Zeile. */
.hero-geteilt .hero-text{
  display:flex; flex-direction:column; gap:12px; align-items:flex-start;
  align-self:start;
}
/* Die Schlagzeile ist hier ein h2, weil der Namenszug daneben das h1 ist.
   Sie soll trotzdem wie eine Schlagzeile aussehen. */
.hero-schlagzeile{
  font-size:clamp(1.9rem,4.4vw,3.4rem); line-height:1.02;
  letter-spacing:.01em; text-transform:uppercase;
}
.hero-geteilt .hero-sub{max-width:44ch; font-size:.92rem; color:var(--sub);}
.hero-zeichen{display:flex; justify-content:center;}
/* Zweite Ebene NUR fuer die Mausbewegung (ui.js, heroTiefe). Sie traegt
   sonst nichts - siehe die Begruendung dort.

   Sie wird SELBST nicht mehr verschoben: ui.js setzt hier nur --tiefe-x und
   --tiefe-y, und bewegt werden die Bilder darin (Regel weiter unten). Der
   Grund steht beim Neonrand - ein transform auf einem Vorfahren schneidet
   dessen Schein ab, solange die Maus laeuft. */
.hero-zeichen-tiefe{display:flex; justify-content:center;}
/* Zeichen ueber Namenszug. Beide kommen aus content/schriftzug/, in der
   Reihenfolge der Ordner. */
.hero-geteilt .hero-schriftzug{
  display:flex; flex-direction:column; align-items:center; gap:clamp(8px,1.6vw,18px);
  margin:0;
}
/* Die Groesse steht in EINER Variablen und wird daraus als Breite gesetzt.
   Der Grund steht beim Neonrand darunter: der Schein muss mit dem Zeichen
   mitwachsen, und dafuer muss er die Groesse kennen. */
/* DIE BEWEGUNG SITZT AM BILD, NICHT AM KASTEN DARUEBER.

   Erster Anlauf war ein transform auf ".hero-zeichen-tiefe" und zusaetzlich
   ein translateZ(0) am Bild, damit dessen Schein eine eigene Ebene bekommt.
   Das reichte nicht: der Vorfahre bleibt eine bewegte Ebene, und Chromium
   schneidet beim Zusammensetzen weiterhin an dessen Kanten zu.

   Jetzt traegt DASSELBE Element beides - die Verschiebung und den
   drop-shadow. Damit gehoert der Schein zur Groessenrechnung genau der
   Ebene, die bewegt wird, und es gibt nichts mehr, was ihn abschneiden
   koennte. ui.js liefert nur noch die zwei Zahlen.

   will-change sagt es vorher an: sonst entsteht die Ebene erst bei der
   ersten Bewegung, und genau in diesem einen Bild fehlt der Schein. */
/* DRITTER ANLAUF - und diesmal eine Regel statt einer Beobachtung:
   KEIN Element traegt gleichzeitig ein transform und den drop-shadow.

   Anlauf 1 hatte beides auf verschiedenen Elementen, aber den Schein auf dem
   KIND eines bewegten Vorfahren - der Vorfahre ist die Ebene, an deren Kanten
   zugeschnitten wird. Anlauf 2 legte deshalb beides auf DASSELBE Element (das
   Bild). Damit war der Vorfahre entschaerft, aber ein Element mit transform
   plus will-change wird selbst zur Ebene - und ein drop-shadow, der ueber
   deren Rand hinausragt, faellt genauso weg. Der Fehler war nur umgezogen.

   Anlauf 3 trennte die beiden Aufgaben: Schein auf den span, Bewegung auf das
   Bild darin. Der Schein war damit zwar da, blieb aber STEHEN, waehrend das
   Bild wanderte - und ein stehender Umriss neben einem wandernden Logo sieht
   aus wie ein Doppelbild. Der Grund: Chromium setzt das bewegte Bild auf eine
   eigene Ebene und faltet den Filter des Elternteils gegen dessen alten
   Schnappschuss.

   VIERTER UND LETZTER ANLAUF - und die Regel von oben war schlicht falsch.
   Filter und transform gehoeren auf DASSELBE Element, denn in der
   Zeichenreihenfolge kommt der Filter VOR dem transform: erst wird der Schein
   aus der Form gerechnet, dann wird beides zusammen verschoben. Sie koennen
   gar nicht auseinanderlaufen.

   Was in Anlauf 2 wirklich schiefging, war nicht die Kombination, sondern
   "will-change:transform" und "translate3d": beide erzwingen eine eigene
   GPU-Ebene, und DIE wird auf die Bildgroesse zugeschnitten. Ohne sie bleibt
   das Element im normalen Zeichenweg, und der Schein steht ausserhalb des
   Bildes, ohne beschnitten zu werden.

   Also: zweidimensionales translate, kein will-change, beides am span. */
.hero-geteilt .hero-zeichen-bild{
  transform:translate(var(--tiefe-x, 0px), var(--tiefe-y, 0px));
}
.hero-geteilt .hero-zeichen-bild img{ filter:none; }
.hero-geteilt .hero-zeichen-bild:first-child{--zeichen:clamp(150px,20vw,290px); width:var(--zeichen);}
.hero-geteilt .hero-zeichen-bild:last-child {--zeichen:clamp(240px,32vw,470px); width:var(--zeichen);}
.hero-geteilt .hero-zeichen-bild:only-child {--zeichen:clamp(240px,32vw,470px); width:var(--zeichen);}
/* Der Neonrand des Markenzeichens.

   DER TRICK IST DAS WIEDERHOLEN, NICHT DAS VERGROESSERN.
   Verkettete drop-shadows rechnen jeweils auf dem ERGEBNIS des vorigen
   weiter. Zweimal 2 px hintereinander ergibt deshalb keinen 4-px-Schatten,
   sondern einen doppelt so dichten Saum an derselben Stelle - und genau das
   ist der Unterschied zwischen "leuchtet" und "ist leicht unscharf".

   Vorher standen hier drei einzelne, breite Lagen. Sie waren da, aber jede
   nur einmal aufgetragen: 85 px Streuung verteilen die Farbe so duenn, dass
   ueber einem bunten Foto nichts uebrig bleibt. Auf einem Zeichen von 400
   bis 540 px ist ein einzelner 2-px-Saum ausserdem kaum breiter als die
   Kantenglaettung.

   Jetzt in vier Stufen, jede doppelt aufgetragen:
     1. weisser Kern     - das Glasrohr selbst
     2. enge Zierfarbe   - die Farbe unmittelbar am Rohr
     3. mittlerer Schein - der sichtbare Halo
     4. weiter Schein    - das Licht im Raum

   Nur die aeusseren beiden haengen an der Leuchtkraft. Kern und Kante
   bleiben, wie sie sind: sie SIND der Rand, und der soll auch auf einer
   zurueckhaltend eingestellten Seite zu sehen sein.

   drop-shadow und nicht box-shadow: gerechnet wird gegen die FORM des
   Bildes, nicht gegen sein Rechteck. Bei einem freigestellten Zeichen ist
   das der ganze Unterschied. */
/* DER SCHEIN WAECHST MIT DEM ZEICHEN.

   Das war der Fehler, den niemand gefunden hat, weil er nicht wie ein Fehler
   aussah: die Streuung stand in festen Pixeln (4 / 8 / 22 / 60), das Zeichen
   aber wird mit clamp() gegen die Fensterbreite gerechnet und ist zwischen
   240 und 470 px breit. Auf einem schmalen Fenster war der Halo damit ein
   Achtel der Zeichenbreite und deutlich zu sehen; auf einem breiten nur noch
   ein Fuenfzehntel - und ueber einem bunten Foto blieb davon nichts uebrig.

   Genau das war das Raetsel "auf dem Screenshot bei 900 px sichtbar, bei
   1544 px nicht". Es lag nie am Browser.

   Jetzt sind alle Radien Bruchteile von --zeichen. Damit sieht der Rand auf
   jedem Fenster gleich aus - und auf dem Telefon nicht ploetzlich fett.

   --zeichen-schein ist der Regler dazu (site.config.json -> zeichenSchein,
   im Panel unter Darstellung). 100 = wie entworfen.

   ALLE VIER FARBIGEN LAGEN haengen am Regler, nicht nur die beiden aeusseren.
   Hier stand vorher "die engen zwei bleiben fest, sie SIND der Rand" - das
   klang schluessig, hat aber genau die Rueckmeldung ausgeloest, die es
   verhindern sollte: der Regler aenderte sichtbar nur die STREUUNG, nicht die
   DICKE der Kontur, und wirkte deshalb wie kaputt. Jetzt skaliert die enge
   Kante mit, nur mit einem Mindestwert (siehe --schein-faktor) - bei 0 % bleibt
   wenigstens ein Hauch Farbe an der Kontur, bei 400 % wird sie sichtbar dicker.

   NUR der weisse Kern (die beiden ersten Lagen) bleibt fest: das ist die
   Glasroehre selbst, kein Leuchten - sie soll immer scharf dastehen, auch
   wenn der Regler auf 0 % steht. */
.hero-geteilt .hero-zeichen-bild:first-child,
.hero-geteilt .hero-zeichen-bild:only-child{
  /* Nie ganz 0: eine Kontur, die komplett verschwindet, wirkt wie ein
     fehlendes Bild, nicht wie "kein Schein". max() haelt mindestens 15%. */
  /* Wie stark der Schein waere, WENN er an ist. */
  --schein-soll:max(.15, calc(var(--leuchtkraft) * var(--zeichen-schein, 1)));
  /* Und wie stark er gerade IST. Aus, bis die Maus darueberfaehrt.

     WIE EINE ECHTE LAMPE: SOFORT AN, DANN NOCH EIN BISSCHEN HELLER.

     Eine Neonroehre geht nicht auf, sie geht AN - deshalb springt der Wert
     beim Beruehren sofort auf einen Grossteil der Helligkeit. Danach zieht
     er ueber eine knappe halbe Sekunde nach: das ist der Moment, in dem sich
     das Gas erwaermt und die Roehre ihre volle Leuchtkraft erreicht.

     Umgekehrt genauso: beim Verlassen faellt sie sofort auf einen Rest ab
     und verglimmt dann. Ein Leuchtmittel ist nicht schlagartig dunkel.

     Gemacht wird das ueber eine Animation und nicht ueber eine Ueberblendung:
     eine Ueberblendung kann nur gleichmaessig von A nach B: der Sprung am
     Anfang liesse sich damit nicht bauen. Zwei Bilder in einer Animation
     koennen genau das - Sprung, dann Nachziehen. */
  --schein-faktor:0;
  filter:
    drop-shadow(0 0 1px #fff)
    drop-shadow(0 0 calc(var(--zeichen) * .008 * var(--schein-faktor)) var(--accent))
    drop-shadow(0 0 calc(var(--zeichen) * .018 * var(--schein-faktor)) var(--accent))
    drop-shadow(0 0 calc(var(--zeichen) * .040 * var(--schein-faktor)) var(--accent))
    drop-shadow(0 0 calc(var(--zeichen) * .110 * var(--schein-faktor))
      color-mix(in srgb, var(--accent) 70%, transparent));
}
/* DER LICHTSCHALTER.
   Die Roehre steht immer da (der weisse Kern bleibt), aber sie brennt erst,
   wenn jemand hinfasst. Ausgeloest wird es am ZEICHEN und nicht am ganzen
   Startbereich: sonst ginge das Licht schon an, wenn die Maus irgendwo oben
   auf der Seite steht, und ein Schalter, der immer an ist, ist keiner.

   Der Wechsel ist absichtlich hart - siehe oben bei --schein-faktor. */
.hero-geteilt .hero-zeichen-bild{
  animation:roehreAus .55s ease-out both;
}
.hero-geteilt .hero-zeichen-bild:hover{
  animation:roehreAn .45s ease-out both;
}
/* Anspringen auf 78 %, dann in den vollen Wert nachziehen. */
@keyframes roehreAn{
  0%  { --schein-faktor:calc(var(--schein-soll) * .78); }
  100%{ --schein-faktor:var(--schein-soll); }
}
/* Sofort auf einen Rest herunter, dann verglimmen. */
@keyframes roehreAus{
  0%  { --schein-faktor:calc(var(--schein-soll) * .30); }
  100%{ --schein-faktor:0; }
}
/* Ohne diese Anmeldung ist --schein-faktor fuer den Browser blosser Text,
   und Text kennt keinen Zwischenwert: die Animation spraenge dann hart von
   Bild zu Bild statt nachzuziehen. */
@property --schein-faktor{
  syntax:'<number>';
  inherits:true;
  initial-value:0;
}
@media(prefers-reduced-motion: reduce){
  .hero-geteilt .hero-zeichen-bild,
  .hero-geteilt .hero-zeichen-bild:hover{ animation:none; }
  .hero-geteilt .hero-zeichen-bild:hover{ --schein-faktor:var(--schein-soll); }
}
/* Wer keine Maus hat, kann nicht darueberfahren - dort brennt das Licht
   dauerhaft, sonst saehe das Zeichen auf dem Telefon nie den Rand. */
@media(hover: none){
  .hero-geteilt .hero-zeichen-bild:first-child,
  .hero-geteilt .hero-zeichen-bild:only-child{ --schein-faktor:var(--schein-soll); }
}
.hero-geteilt-fuss{
  display:flex; flex-direction:column; gap:clamp(16px,2.6vw,28px);
  align-items:center; position:relative; z-index:2; width:100%;
}
.hero-geteilt .hero-ctas{display:flex; flex-wrap:wrap; gap:14px; justify-content:center;}

/* Die Markenleiste. Liest dieselben Ordner wie der Abschnitt "bereiche" -
   deshalb steht hier nur, wie sie aussieht, und nirgends, was drinsteht. */
/* Flex statt Raster: bei drei Bereichen legt auto-fit eine vierte, leere
   Spalte an und laesst rechts eine Luecke stehen. Mit flex teilen sich genau
   die vorhandenen Bereiche die Breite - egal ob es zwei, drei oder fuenf
   sind. */
/* Nach oben gedeckelt: drei Tafeln, die sich ueber einen breiten Schirm
   ziehen, lesen sich als zweite Menuezeile. Im Entwurf stehen sie als
   geschlossene Gruppe unter den Knoepfen. */
.hero-marken{
  display:flex; flex-wrap:wrap; gap:14px;
  width:100%; max-width:min(940px, 100%); margin-inline:auto;
}
.hero-marke{flex:1 1 220px;}
/* Die Leiste sitzt als Gruppe in der Mitte und laeuft nicht ueber die volle
   Breite: im Entwurf sind es drei abgesetzte Tafeln, keine Menuezeile.

   Innerhalb der Gruppe stehen sie LINKSBUENDIG und fuellen sie aus.
   Zentriert sass die linke Tafel irgendwo im Kasten - und der Knopf
   darueber, der an der Kastenkante haengt, stand dann nicht mehr auf ihrer
   Kante. Beim Verkleinern des Fensters wanderte der Versatz mit, weil sich
   die Restbreite aendert. Mit flex-grow gibt es keine Restbreite. */
.hero-marken{justify-content:flex-start;}
.hero-marke{flex:1 1 230px; max-width:none;}
.hero-marke{
  position:relative;
  display:grid; grid-template-columns:1fr; justify-items:center;
  gap:2px; text-align:center; text-decoration:none;
  padding:12px 44px 12px 22px; border-radius:var(--ecken);
  border:1px solid color-mix(in srgb, var(--accent) 60%, transparent);
  background:color-mix(in srgb, #000 62%, transparent);
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
  box-shadow:0 0 calc(24px * var(--leuchtkraft))
             color-mix(in srgb, var(--accent) calc(28% * var(--leuchtkraft)), transparent);
  transition:background .2s, box-shadow .2s;
}
a.hero-marke:hover{
  background:color-mix(in srgb, var(--accent) 18%, rgba(0,0,0,.6));
  box-shadow:0 0 calc(38px * var(--leuchtkraft))
             color-mix(in srgb, var(--accent) calc(46% * var(--leuchtkraft)), transparent);
}
.hero-marke-name{
  font-family:var(--schrift-ueberschrift); font-weight:700;
  font-size:clamp(1rem,1.7vw,1.35rem); letter-spacing:.06em;
  text-transform:uppercase; color:#fff; line-height:1.1;
}
.hero-marke-unter{
  font-family:var(--schrift-mono); font-size:.64rem;
  letter-spacing:.12em; text-transform:uppercase; color:var(--accent);
}
/* Der Winkel sitzt am rechten Rand und nicht in der Textspalte - sonst
   waere die Beschriftung nicht mehr mittig, sondern nur fast. */
.hero-marke-pfeil{
  position:absolute; right:12px; top:50%; transform:translateY(-50%);
  display:inline-flex; align-items:center; justify-content:center;
  width:26px; height:26px; border-radius:50%; color:var(--accent);
  border:1px solid color-mix(in srgb, var(--accent) 60%, transparent);
}
.hero-marke-pfeil .icon{width:.9em; height:.9em;}

@media(max-width:860px){
  .hero-geteilt-raster{grid-template-columns:1fr; text-align:center; gap:26px;}
  .hero-geteilt .hero-text{align-items:center;}
  .hero-geteilt .hero-sub{max-width:52ch;}
  /* Das Zeichen zuerst: auf dem Telefon ist es das, was die Marke traegt. */
  .hero-zeichen{order:-1;}
}

/* ---------- Zierstrich als eigenes Bild ----------
   Gesetzt von zierstriche() im loader.js aus content/zierstrich/.
   Ohne Bilder bleibt alles beim gezeichneten Strich darueber - das Attribut
   wird dann gar nicht erst gesetzt.

   mix-blend-mode:screen, weil die Vorlagen auf schwarzem Grund liegen statt
   freigestellt zu sein: "screen" laesst Schwarz verschwinden und nur die
   Linie stehen. Damit taugt jede Zeichnung, die jemand aus einem Entwurf
   herausschneidet, ohne dass er sie vorher freistellen muesste. */
:root[data-zierstrich="bild"] .band-linie{
  display:block; flex:1 1 60px; min-width:30px; height:26px;
  background:none; opacity:1;
  mix-blend-mode:screen;
  background-repeat:no-repeat; background-size:100% 100%;
}
:root[data-zierstrich="bild"] .band-linie{background-image:var(--zier-linie);}
/* Ein einzelnes Bild ist symmetrisch gemeint - die RECHTE Seite gespiegelt.
   Warum rechts und nicht links: so eine Zeichnung laeuft von aussen nach
   innen, sie wird zur Ueberschrift hin heller. Gelesen wird von links, also
   ist die Datei so gemalt - links passt sie unveraendert, rechts nicht. */
:root[data-zierstrich="bild"] .band-linie-rechts{transform:scaleX(-1);}

/* --- Linie + feste Welle (der Normalfall, sobald zwei Ordner da sind) --- */
:root[data-zierstrich="linie-welle"] .band-linie{
  display:flex; align-items:center; flex:1 1 60px; min-width:40px;
  height:26px; background:none; opacity:1; mix-blend-mode:screen;
}
/* Die Linie dehnt sich, die Welle nicht. Genau darum geht es. */
:root[data-zierstrich="linie-welle"] .band-linie::before{
  content:''; flex:1 1 auto; min-width:0; height:100%;
  background:var(--zier-linie) center/100% 100% no-repeat;
}
:root[data-zierstrich="linie-welle"] .band-linie::after{
  content:''; flex:0 0 var(--zier-welle-breite, 60px); height:100%;
  background:var(--zier-welle) center/contain no-repeat;
}
/* Die rechte Seite ist das Spiegelbild der linken - und zwar KOMPLETT.
   Drei Dinge gehoeren dazu, und das dritte war lange vergessen:
     1. die Reihenfolge dreht sich (row-reverse), damit die Welle auch rechts
        innen an der Ueberschrift sitzt,
     2. die Welle selbst dreht sich, damit ihr Ausschlag nach aussen zeigt,
     3. die LINIE dreht sich ebenfalls.
   Punkt 3 faellt nur auf, wenn die Zeichnung nicht symmetrisch ist: die
   Vorlage laeuft von dunkel nach hell und endet in einem hellen Rot. Ohne
   Spiegelung sass dieses helle Ende am Fensterrand statt an der Ueberschrift
   - ein leuchtender Strich, der ins Nichts zeigt. */
:root[data-zierstrich="linie-welle"] .band-linie-rechts{flex-direction:row-reverse;}
:root[data-zierstrich="linie-welle"] .band-linie-rechts::after,
:root[data-zierstrich="linie-welle"] .band-linie-rechts::before{transform:scaleX(-1);}
/* In der Fassung "links" gibt es nur den rechten Strich - dort soll er nicht
   gespiegelt sein, er steht ja allein. */
:root[data-zierstrich="bild"][data-kopfstil="linie"] .band-linie-rechts{transform:none;}
@media(max-width:560px){
  :root[data-zierstrich="bild"] .band-linie{flex-basis:24px; min-width:16px;}
}

/* ---------- Rueckweg zur uebergeordneten Seite ----------
   Gebaut von elternWeg() im loader.js, sobald in site.config.json ein
   "eltern" steht. Ohne das gibt es keins dieser Elemente.

   Der Griff um Logo und Markenname bleibt UNSICHTBAR: er soll aussehen wie
   vorher, nur eben anklickbar sein. Ein Rahmen oder eine Unterstreichung um
   das Logo saehe nach Fehler aus. Sichtbar wird er erst beim Darueberfahren
   und beim Ansteuern mit der Tastatur - dort muss er es sein, sonst weiss
   niemand, dass da etwas zu klicken ist. */
.zurueck-marke{
  display:inline-block; text-decoration:none; color:inherit;
  border-radius:8px; transition:opacity .18s;
}
.zurueck-marke:hover{opacity:.72;}

/* Der Knopf ganz unten, ueber der Fusszeile.
   Wer eine Unterseite zu Ende gelesen hat, ist unten - und scrollt nicht
   wieder hoch, um weiterzukommen. Deshalb steht der Weg dorthin da, wo der
   Text aufhoert, und nicht nur oben im Kopf.

   Der Pfeil zeigt nach LINKS: zurueck, nicht weiter. Gedreht wird das
   eingebaute Zeichen, damit es nur eines davon gibt. */
.zurueck-band{
  display:flex; justify-content:center;
  padding:clamp(28px,5vw,54px) var(--gutter);
}
.zurueck-knopf{
  display:inline-flex; align-items:center; gap:10px;
  font-family:var(--schrift-mono); font-size:.76rem; letter-spacing:.14em;
  text-transform:uppercase; text-decoration:none; color:var(--accent);
  border:1px solid color-mix(in srgb, var(--accent) 55%, transparent);
  border-radius:999px; padding:12px 22px; background:none;
  transition:background .18s, color .18s, box-shadow .18s;
}
.zurueck-knopf:hover{
  background:var(--accent); color:#000;
  box-shadow:0 0 calc(30px * var(--leuchtkraft))
             color-mix(in srgb, var(--accent) calc(40% * var(--leuchtkraft)), transparent);
}
.zurueck-pfeil{display:inline-flex; transform:scaleX(-1);}
.zurueck-knopf:hover .zurueck-pfeil{color:#000;}

/* ---------- Leuchtspur unter der Maus ----------
   Die Zeichenflaeche legt ui.js an; hier steht nur, wo sie liegt.

   z-index:-1 ist der ganze Trick: die Flaeche steht damit VOR dem Grund der
   Seite und HINTER allem, was darauf steht. Bei 0 laege sie ueber dem Text
   (positionierte Elemente gewinnen gegen Text im Fluss), und man haette
   eine Leuchtspur quer ueber die Schrift.

   Standzeit und Staerke sind Zahlen und keine Zeitangabe: ui.js liest sie
   und rechnet damit, CSS animiert hier nichts. */
/* --leuchtspur-runde bleibt hier bewusst UNGESETZT: ohne Angabe rechnet
   ui.js sie aus der Standzeit (siehe dort). Ein fester Wert hier wuerde
   diese Rechnung stillschweigend ausschalten. */
:root{ --leuchtspur-dauer:1.5; --leuchtspur-breite:3; --funken-anzahl:26; }
.leuchtspur, .klickfunken{
  position:fixed; inset:0; pointer-events:none;
  width:100%; height:100%;
}
/* WIE WEIT HINTEN LIEGEN DIE EFFEKTE?

   Beide lagen auf z-index:-1, also hinter allem - auch hinter dem
   Hintergrundbild des Startbereichs. Von einem Laserfaecher aus zehn Strahlen
   war dadurch genau EINER zu sehen, naemlich der, der zufaellig ueber eine
   Stelle ohne Bild lief.

   Jetzt liegen sie auf 0: ueber dem Seitenhintergrund und ueber den Fotos,
   aber UNTER allem, was Inhalt ist. Die Panels, Karten und der Text tragen
   ohnehin ihre eigene Ebene (position:relative mit z-index 1 oder 2) und
   bleiben deshalb vorn - genau so ist es gewollt: Licht im Nebel gehoert
   hinter die Buehne, nicht davor.

   pointer-events:none steht oben und bleibt entscheidend: eine Flaeche ueber
   dem Hintergrund darf keinen Klick abfangen. */
.leuchtspur, .klickfunken{ z-index:0; }
/* Der Startbereich und die Abschnitte bekommen ihre eigene Ebene, damit die
   Zeichenflaeche wirklich DAHINTER bleibt und nicht ueber der Schrift liegt.

   KOPF- UND FUSSZEILE STEHEN HIER NICHT MEHR MIT DRIN. Sie standen es, und
   das hat die mitlaufende Kopfzeile ausgehebelt: weiter oben steht
   "header{position:sticky}", diese Regel hier steht spaeter in derselben
   Datei und gewinnt damit bei gleicher Spezifitaet. Aus sticky wurde
   relative, und der Kopf scrollte weg, obwohl im Panel "mitlaufend" stand.
   Dasselbe galt fuer eine mitlaufende oder feste Fusszeile.

   Ueber der Zeichenflaeche liegen beide trotzdem: sie tragen ihre eigene
   Ebene (z-index 50 bzw. 45), und die ist hoeher als die 1 hier. Nur fuer
   den Fall "kopf: normal" und eine Fusszeile ohne Schalter muss die Ebene
   ausdruecklich gesetzt werden, weil ein Element ohne position keine
   bekommt. Das steht unten bei den beiden. */
.hero, .band{ position:relative; z-index:1; }

/* Ein Mandala, das bei einem Klick aufblueht (ui.js, mandalaKlick).
   Anders als die beiden Zeichenflaechen oben steht es ABSOLUT in der Seite
   und nicht fest im Fenster: es gehoert an die Stelle, an der geklickt wurde,
   und soll beim Scrollen dort bleiben. Deshalb auch keine feste Groesse im
   Skript - sie steht hier, wo auch der Rest der Gestaltung steht. */
.klick-mandala{
  position:absolute; z-index:-1; pointer-events:none;
  width:clamp(180px, 22vw, 300px); aspect-ratio:1;
  transform:translate(-50%,-50%);
}
.klick-mandala svg{width:100%; height:100%; display:block;}

/* ---------- Personenkarten: Mausverhalten ----------
   (Anordnung der Marken steht weiter unten, bei der Farbregel.) */

/* Die Karte hebt sich beim Zeigen an und nimmt die Farbe der Person an.
   Auch dann, wenn sie noch nicht verlinkt ist ("Unterseite folgt"): sie
   soll sich anfuehlen wie das, was sie werden wird. */
.person{
  transition:border-color .22s ease, box-shadow .22s ease, transform .22s ease;
}
.team-grid .person:hover{
  transform:translateY(-5px);
  border-color:color-mix(in srgb, var(--accent) 70%, transparent);
  box-shadow:0 0 calc(34px * var(--leuchtkraft))
             color-mix(in srgb, var(--accent) calc(40% * var(--leuchtkraft)), transparent);
}
.team-grid .person:hover .person-bild img{transform:scale(1.04);}
.person-bild img{transition:transform .4s ease;}
a.person-klick{text-decoration:none; display:block; cursor:pointer;}
/* Vorgesehene, aber noch nicht gebaute Unterseite: der Zeiger sagt es,
   die Karte selbst bleibt vollwertig. */
.person-folgt{cursor:default;}

/* ---------- Text markieren aus ----------
   Gesetzt vom Loader aus design.textMarkieren. Warum das nichts schuetzt und
   trotzdem ein Schalter ist, steht dort.

   Eingabefelder sind ausgenommen: wer seine E-Mail-Adresse im Newsletterfeld
   nicht mehr korrigieren kann, haelt die Seite fuer kaputt. */
:root[data-markieren="aus"] body{
  -webkit-user-select:none; user-select:none;
}
:root[data-markieren="aus"] input,
:root[data-markieren="aus"] textarea,
:root[data-markieren="aus"] select{
  -webkit-user-select:text; user-select:text;
}

/* ---------- Personenkarten: Zugehoerigkeit ----------
   "abzeichen:" in der meta.txt, beliebig oft. Der ERSTE Eintrag ist die
   Hauptzugehoerigkeit und traegt die Farbe des Eintrags, alle weiteren sind
   Zusatz und bleiben grau - "BÖSEBÄSSE Resident", "Praxis Nord Fachärztin".

   Damit steht die Zuordnung in den INHALTEN (Reihenfolge der Zeilen) und
   nicht in zwei verschiedenen Schluesselnamen, die man verwechseln kann.

   Wie die Marken AUSSEHEN, entscheidet die jeweilige Seite: hier stehen nur
   Anordnung und Farbregel. Die NuT-Seite macht daraus laufenden Text nach
   ihrem Entwurf, eine Arztpraxis darf bei ihren Etiketten bleiben. */
.person-marken{display:flex; flex-wrap:wrap; gap:6px; margin-bottom:10px;}
.person-abzeichen{margin-bottom:0;}

/* Das erste Abzeichen ist die Zugehoerigkeit und kommt aus dem Ordner
   DARUEBER (content/team/<Kollektiv>/<Person>/). Es traegt die Farbe des
   Kollektivs, nicht die der Karte: setzt jemand an einer Person eine eigene
   Farbe, bleibt die Zugehoerigkeit trotzdem lesbar als das, was sie ist.

   Ohne Kollektiv faellt --kollektiv weg und es gilt wieder --accent - die
   Arztpraxis mit vier Behandelnden sieht aus wie vorher. */
.person-kollektiv{
  color:var(--kollektiv, var(--accent));
  border-color:color-mix(in srgb, var(--kollektiv, var(--accent)) 45%, transparent);
  font-weight:600;
}
/* Schreibweise so lassen, wie sie im Ordnernamen steht - fuer Namen, deren
   Schreibweise die Marke ist ("Trance4matioN"). Umgeschaltet in
   site.config.json -> layouts.teamKollektivSchrift, im Panel unter dem
   Bereich Team. Die Sperrung bleibt: sie macht die Zeile zum Etikett, und
   das ist sie in beiden Faellen. */
.person-kollektiv-original{text-transform:none;}

/* ---------- Startbereich: Tafel als fertiges Bild ----------
   "tafel:" in der meta.txt des Bereichs. Dann ist die Tafel das Bild aus dem
   Entwurf, und der Rahmen aus CSS entfaellt - er laege sonst als zweiter
   Rahmen um den bereits gezeichneten. Der Text bleibt darueber liegen und
   damit aenderbar; wo er im Bild schon steht, verschwindet er beim naechsten
   Austausch der Datei. */
.hero-marke.hat-tafel{
  background:var(--tafel) center/100% 100% no-repeat;
  border:0; box-shadow:none; backdrop-filter:none; -webkit-backdrop-filter:none;
  aspect-ratio:558/190; padding:0;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
}
a.hero-marke.hat-tafel:hover{
  background:var(--tafel) center/100% 100% no-repeat;
  filter:brightness(1.15);
}
.hero-marke.hat-tafel .hero-marke-pfeil{border:0;}

/* ---------- Startbereich: Knoepfe linksbuendig, Zeichen mittig ----------
   Im Entwurf stehen die beiden Knoepfe auf einer Kante mit der Markenleiste
   darunter, nicht in der Fenstermitte. Das Markenzeichen dagegen haelt die
   Mitte des Bildes - es ist die Achse, um die alles andere sitzt. */
.hero-geteilt-fuss{align-items:stretch;}
/* Das Zeichen sitzt mittig im BILD, nicht in einer Rasterspalte.
   Beide Bausteine liegen deshalb in DERSELBEN Zelle uebereinander: der Text
   haelt die linke Kante, das Zeichen die Mitte des Startbereichs. Mit zwei
   Spalten stuende das Zeichen in der Mitte SEINER Spalte - also bei rund
   74 % statt bei 50 %, und der Entwurf zeigt es genau mittig. */
.hero-geteilt-raster{grid-template-columns:1fr;}
.hero-geteilt-raster > *{grid-area:1 / 1;}
.hero-geteilt-raster .hero-text{justify-self:start; max-width:min(46%, 560px);}
.hero-geteilt-raster .hero-zeichen{justify-self:center; align-self:center;}
@media(max-width:860px){
  /* Uebereinander wird auf schmalen Schirmen zu eng - dort wieder nacheinander. */
  .hero-geteilt-raster > *{grid-area:auto;}
  .hero-geteilt-raster .hero-text{justify-self:stretch; max-width:100%;}
}

@media(max-width:860px){
  .hero-geteilt .hero-ctas{justify-content:center;}
}

/* ---------- Startbereich: Fussgruppe ----------
   Im Entwurf sind die drei Tafeln als Gruppe MITTIG gesetzt, und die beiden
   Knoepfe darueber beginnen an der linken Kante genau dieser Gruppe. Beide
   liegen deshalb in einem gemeinsamen, zentrierten Kasten - die Knoepfe
   linksbuendig darin, die Tafeln fuellen ihn aus.

   Vorher standen beide linksbuendig am Seitenrand: die Kante stimmte
   zueinander, aber die Gruppe sass nicht mehr in der Mitte des Bildes. */
.hero-geteilt .hero-ctas,
.hero-marken{
  width:min(940px, 100%); margin-inline:auto;
}

/* Die Markenleiste als Reihe (layouts.markenReihe).
   Sie traegt dann dieselbe Spur wie die uebrigen Rondelle - die Regeln oben
   fuer ".karten-reihe > .reihe-spur" greifen also mit. Was hier steht, ist
   nur, was an DIESER Reihe anders ist: die Tafeln sind breiter als eine
   Personenkarte, und die Reihe steht im Startbereich und nicht in einem
   Band, darf also nicht ueber den Satzspiegel hinausbrechen. */
.karten-reihe > .reihe-spur.hero-marken{
  width:100%; max-width:none; flex-wrap:nowrap; margin-inline:0;
}
.karten-reihe > .reihe-spur > .hero-marke{
  flex:0 0 clamp(240px, 24vw, 300px);
}
.hero-geteilt .hero-ctas{justify-content:flex-start;}

/* ---------- Aufmacher und Newsletter: Mausverhalten ----------
   Beide sind grosse, anklickbare Flaechen und sollen sich auch so anfuehlen.
   Dasselbe Verhalten wie bei den Rueckblick-Karten: leicht anheben, Schein
   in der eigenen Zierfarbe verstaerken, das Bild eine Spur naeher holen. */
.aufmacher, .news{
  transition:transform .28s ease, box-shadow .28s ease, border-color .28s ease;
}
.aufmacher:hover, .news:hover{
  transform:translateY(-4px);
  border-color:color-mix(in srgb, var(--accent) 85%, transparent);
  box-shadow:0 0 calc(66px * var(--leuchtkraft))
             color-mix(in srgb, var(--accent) calc(46% * var(--leuchtkraft)), transparent);
}
.aufmacher-bild{transition:transform .6s ease;}
.aufmacher:hover .aufmacher-bild{transform:scale(1.04);}
.news-kunst{transition:transform .6s ease;}
.news:hover .news-kunst{transform:scale(1.04);}

/* ---------- Startsequenz ----------
   Ein inszenierter Moment beim Laden statt vieler Einzeleffekte: erst das
   Markenzeichen, dann die Schlagzeile, dann der Text, zuletzt Knoepfe und
   Tafeln. Die Reihenfolge ist die Leserichtung des Entwurfs.

   Gestaffelt ueber Verzoegerungen und nicht ueber Skript: es gibt nichts zu
   berechnen, und wer "Bewegung reduzieren" eingestellt hat, sieht die Seite
   sofort fertig (die Regel dafuer steht in kunde.css ganz oben und setzt
   alle Dauern auf null).

   Nur im geteilten Startbereich - die uebrigen Vorlagen bleiben, wie sie
   sind. */
@keyframes auftritt{
  from{ opacity:0; transform:translateY(14px); }
  to  { opacity:1; transform:none; }
}
@keyframes auftrittZeichen{
  from{ opacity:0; transform:scale(.94); }
  to  { opacity:1; transform:none; }
}
.hero-geteilt .hero-zeichen{ animation:auftrittZeichen .9s ease .05s both; }
.hero-geteilt .hero-text .mono{ animation:auftritt .7s ease .45s both; }
/* "schimmer" stand hier als zweite Animation, aber die Keyframes dazu gibt es
   nirgends - der Aufruf lief seit jeher ins Leere. Entfernt statt nachgebaut:
   die Schlagzeile hat keinen Verlauf, den man wandern lassen koennte, und
   einen zu ergaenzen wuerde auf den Psy-Seiten den Farbversatz (text-shadow)
   erschlagen. Wer den Effekt will, sagt es - er gehoert dann dorthin, wo auch
   der Verlauf herkommt. */
.hero-geteilt .hero-schlagzeile{ animation:auftritt .7s ease .6s both; }
.hero-geteilt .hero-sub{ animation:auftritt .7s ease .78s both; }
.hero-geteilt .hero-ctas{ animation:auftritt .7s ease .95s both; }
.hero-geteilt .hero-marken{ animation:auftritt .7s ease 1.1s both; }

/* Die Tiefe unter der Maus setzt beim Zeichen ein eigenes transform - waehrend
   der Startsequenz wuerde es die Animation ueberschreiben. Deshalb bekommt
   es seinen Platz erst danach (ui.js setzt nichts, bevor die Maus bewegt
   wird - der Fall tritt also nur ein, wenn jemand sofort die Maus bewegt,
   und dann ist der Auftritt ohnehin gemeint). */
@media (prefers-reduced-motion: reduce){
  .hero-geteilt .hero-zeichen, .hero-geteilt .hero-text .mono,
  .hero-geteilt .hero-schlagzeile, .hero-geteilt .hero-sub,
  .hero-geteilt .hero-ctas, .hero-geteilt .hero-marken{ animation:none; }
}


/* ===========================================================================
   TELEFON: GENAU EINE KARTE JE RONDELL

   Ganz am Schluss und nicht oben bei den uebrigen Telefonregeln - und das ist
   kein Schoenheitsfehler, sondern noetig:

   Die Kartensorten bekommen ihre Breite an drei verschiedenen Stellen dieser
   Datei (.person, .bereich, .hero-marke), alle mit derselben Spezifitaet wie
   die Regel hier. Bei gleicher Spezifitaet gewinnt die SPAETERE - eine
   Telefonregel weiter oben blieb deshalb wirkungslos, und auf einem 375px
   breiten Schirm standen weiterhin 240px breite Karten samt angeschnittener
   Nachbarin.

   Eine Medienabfrage erhoeht die Spezifitaet nicht. Der einzige saubere Weg
   ohne "!important" ist die Reihenfolge.
   ========================================================================= */
@media(max-width:560px){
  .karten-reihe > .reihe-spur > *,
  .karten-reihe > .reihe-spur > .person,
  .karten-reihe > .reihe-spur > .bereich,
  .karten-reihe > .reihe-spur > .rueck,
  .karten-reihe > .reihe-spur > .hero-marke{
    flex:0 0 100%;
  }
}
