/* ==========================================================================
   Wagner Engineering GmbH — Stylesheet
   Navy-graue Fläche, abgesetzte Karten, Grün als leuchtender Akzent.
   Schriften selbst gehostet (Inter variabel) — keine Google-Fonts, kein Tracking.
   ========================================================================== */

@font-face {
  font-family: 'Inter';
  src: url('fonts/inter-var-latin.woff2') format('woff2-variations');
  font-weight: 100 900; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  src: url('fonts/inter-var-latin-ext.woff2') format('woff2-variations');
  font-weight: 100 900; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Grundfläche Navy-Grau statt hell: auf dunklem Grund steht der Markenton nicht
   mehr gegen Weiß, sondern leuchtet — und die grünen Beschriftungen (Eyebrows,
   aktiver Menüpunkt, Textlinks) erreichen endlich hohe Kontraste, statt sich auf
   Hell zu einer dunkeloliven Notlösung verdunkeln zu müssen.

   Die Fläche ist in vier Stufen gestaffelt, damit Tiefe auch ohne die auf Dunkel
   kaum sichtbaren Schlagschatten entsteht:
     --bg-2 (getönte Bänder)  <  --bg (Grund)  <  --card (Karten)
     --dark liegt darunter — für Blöcke, die sich absetzen sollen (CTA, Fußzeile,
     Terminal-Ansichten). Kontraste in Klammern gegen die jeweilige Fläche. */
:root {
  color-scheme: dark;

  /* Die Stufen sind in CIE-L* gerechnet, nicht per Augenmaß am Hexwert: nur so
     bleiben die Abstände gleichmäßig, wenn die ganze Treppe angehoben wird.
     L*:  --dark 7,5 · --bg-2 11 · --bg 14 · --card 20 · --card-2 28 */
  --bg: #192434;
  --bg-2: #151E2B;
  --card: #243142;
  --card-2: #31435E;         /* angehobene Fläche: Diagrammteile, die für sich
                                stehen müssen — Radsegmente, Rondell-Chips,
                                Fensterrahmen der Screenshots */
  --dark: #101722;
  --ink: #EDF1F7;            /* auf --bg 13.8:1, auf --card 11.6:1 */
  --ink-2: #C2CCDA;          /* auf --bg 9.6:1 (AAA) */
  --muted: #A4B1C2;          /* auf --card 6.1:1, auf --card-2 4.6:1 (AA) */
  --line: #3D4E6A;           /* Kanten tragen auf Dunkel die Form, nicht der
                                Helligkeitssprung — deshalb bewusst kräftig */
  --line-2: #4F6488;         /* Kante auf --card-2 */
  --green: #7FCB28;          /* Markenton – Flächen, Grafik: auf --bg 7.9:1 */
  --green-deep: #8FD93A;     /* Grafik/Icons auf Dunkel */
  --green-ink: #9BDD4A;      /* Text/Links auf Dunkel: auf --bg 9.5:1 (AAA) */
  --green-wash: rgba(127,203,40,.13);
  --on-green: #0C1420;       /* Text auf grüner Fläche: 9.3:1 */

  --r: 20px; --r-sm: 13px; --r-lg: 24px; --pill: 999px;
  --sh-1: 0 2px 6px rgba(0,0,0,.22), 0 14px 34px rgba(0,0,0,.30);
  --sh-2: 0 4px 10px rgba(0,0,0,.28), 0 22px 50px rgba(0,0,0,.42);
  --gutter: clamp(20px, 4vw, 40px);
  --max: 1220px;
  --band: clamp(52px, 6.5vw, 96px);
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
html:focus-within { scroll-behavior: smooth; }

body {
  margin: 0; background: var(--bg); color: var(--ink);
  font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
  font-size: 17px; line-height: 1.65;
  -webkit-hyphens: none; hyphens: none; overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
}
img, svg { display: block; max-width: 100%; }
/* Die HTML-Attribute width/height wirken als Darstellungshinweis. Ohne dieses
   height:auto bliebe die Attributhöhe stehen, sobald CSS nur die Breite setzt. */
img { height: auto; }
a { color: inherit; text-decoration: none; }
:focus-visible { outline: 3px solid var(--green-ink); outline-offset: 3px; border-radius: 6px; }

.wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); }
.band { padding-block: var(--band); }
/* Fuer Abschnitte, die inhaltlich am vorigen haengen: das volle Band ergaebe
   zusammen mit dessen Unterkante fast 190px Totraum. */
.band--eng { padding-block: clamp(26px, 3vw, 44px); }
.tint { background: var(--bg-2); }

.skip {
  position: fixed; left: 14px; top: -100px; z-index: 999;
  background: var(--green); color: var(--on-green); padding: 13px 20px;
  border-radius: var(--pill); font-size: 14px; font-weight: 600;
}
.skip:focus { top: 14px; }

/* --- Typografie ----------------------------------------------------------- */
h1, h2, h3, h4 { margin: 0; hyphens: none; text-wrap: balance; }
.t-h1 { font-size: clamp(2.1rem, 4.3vw, 3.4rem); line-height: 1.07; letter-spacing: -.035em; font-weight: 700; }
.t-h1--sub { font-size: clamp(1.8rem, 3.5vw, 2.7rem); line-height: 1.1; letter-spacing: -.03em; font-weight: 700; }
.t-h2 { font-size: clamp(1.6rem, 2.9vw, 2.3rem); line-height: 1.12; letter-spacing: -.03em; font-weight: 700; }
.t-h3 { font-size: 17px; line-height: 1.3; letter-spacing: -.015em; font-weight: 700; }
.lead { font-size: 16.5px; line-height: 1.65; color: var(--ink-2); max-width: 60ch; }
.lead--muted { color: var(--muted); font-size: 15.5px; }
.gruen { color: var(--green-ink); }

.eyebrow {
  display: inline-block; font-size: 12.5px; letter-spacing: .16em;
  font-weight: 700; color: var(--green-ink); text-transform: uppercase;
}
.sec-head { margin-bottom: clamp(28px, 3.5vw, 44px); }
.sec-head .t-h2 { margin-top: 8px; max-width: 26ch; }
.sec-head-row { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 16px; }
.sec-head-row p { margin: 0; color: var(--muted); font-size: 15.5px; max-width: 44ch; }
/* Gestapelt statt nebeneinander: Der Erklaersatz steht unter der Ueberschrift
   und nicht rechts daneben. Fuer Abschnitte, in denen er die Aussage traegt
   und nicht bloss einordnet — rechts oben liest ihn, wer ihn sucht. */
.sec-head-row--stapel { display: block; }
.sec-head-row--stapel p { margin-top: 14px; max-width: 68ch; font-size: 16.5px;
  line-height: 1.62; color: var(--ink-2); }

/* --- Schaltflächen -------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 15px 26px; border-radius: var(--pill);
  font-size: 15px; font-weight: 600; cursor: pointer;
  background: var(--green); color: var(--on-green); border: 1.5px solid var(--green);
  box-shadow: 0 10px 26px rgba(127,203,40,.24);
  transition: transform .2s ease, box-shadow .2s ease;
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 14px 32px rgba(127,203,40,.36); }
.btn svg { width: 17px; height: 17px; transition: transform .22s ease; }
.btn:hover svg { transform: translateX(4px); }
/* Auf hellem Grund war die Hauptschaltfläche dunkel und das Grün der Zweitrang.
   Auf Navy kehrt sich das um: Grün ist die Hauptschaltfläche, der Umriss die
   zweite Stufe. --btn--dark bleibt als Klassenname bestehen, damit die Seiten
   unverändert bleiben. */
.btn--dark { background: var(--green); color: var(--on-green); border-color: var(--green); }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); box-shadow: none; }
.btn--ghost:hover { border-color: var(--green); color: var(--green-ink); }
.btn-row { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 32px; }

/* Textverweis mit Pfeil. Ohne die Groessenvorgabe fuer das SVG laeuft das
   Symbol auf die volle Spaltenbreite auf — inline-SVG hat keine Eigengroesse. */
.tlink { display: inline-flex; align-items: center; gap: 8px; color: var(--green-ink);
  font-size: 15px; font-weight: 600; }
.tlink svg { width: 15px; height: 15px; flex: 0 0 auto; transition: transform .22s ease; }
.tlink:hover svg { transform: translateX(4px); }

.back { display: inline-flex; align-items: center; gap: 8px; color: var(--green-ink);
  font-size: 13.5px; font-weight: 600; margin-bottom: 18px;
  min-height: 26px; padding: 2px 0; }
.back svg { width: 15px; height: 15px; }

/* --- Kopfzeile ------------------------------------------------------------ */
.top {
  position: sticky; top: 0; z-index: 100;
  /* Deutlich durchscheinend: der Inhalt soll unter der Leiste sichtbar
     durchlaufen. Die Sättigung fängt ab, dass Durchscheinendes ausbleicht. */
  background: rgba(25,36,52,.58); backdrop-filter: blur(20px) saturate(150%);
  -webkit-backdrop-filter: blur(20px) saturate(150%);
  border-bottom: 1px solid var(--line);
}
.top-in { display: flex; align-items: center; gap: 22px; height: 76px; }
/* Kein CSS-Filter: der färbt den grünen Keil mit weiß. Stattdessen liegt eine
   eigens aufgehellte Fassung bei, die den Markenton behält (logo_hell.py). */
.top-logo img { width: 218px; height: auto; }
.top-nav { margin-left: auto; display: flex; align-items: center; gap: 4px; }
.top-nav a { padding: 9px 15px; border-radius: var(--pill); font-size: 14.5px; font-weight: 500; color: var(--ink-2); transition: background .2s, color .2s; }
.top-nav a:hover { background: var(--card); color: var(--ink); }
.top-nav a[aria-current] { background: var(--green-wash); color: var(--green-ink); }
/* Achtung Spezifität: .top-nav a (0,1,1) überschreibt sonst .btn--dark (0,1,0)
   und färbt die Schaltfläche dunkelgrau auf dunklem Grund. */
.top-nav a.btn, .top-nav a.btn--dark { margin-left: 10px; padding: 12px 21px; font-size: 13.5px;
  color: var(--on-green); background: var(--green); border: 1.5px solid var(--green); }
.top-nav a.btn:hover { background: var(--green-deep); border-color: var(--green-deep); color: var(--on-green); }
/* --- Untermenü Produkte ---------------------------------------------------
   Bewusst ohne JavaScript: :hover oeffnet fuer die Maus, :focus-within fuer die
   Tastatur — wer den Elternpunkt antabbt, kann direkt in die Eintraege
   weitertabben. Der Elternpunkt bleibt ein echter Verweis auf den
   Produktabschnitt der Startseite, damit ein Fingertipp nicht ins Leere geht.
   Deshalb auch kein aria-expanded: es gibt keine Schaltflaeche, die luege. */
.nav-drop { position: relative; display: inline-flex; }
/* Der Elternpunkt ist eine Schaltflaeche, keine Verknuepfung — er sieht aber
   aus wie die uebrigen Menuepunkte. */
.nav-drop-knopf { display: inline-flex; align-items: center; gap: 5px;
  padding: 9px 15px; border: 0; border-radius: var(--pill); background: none;
  font: inherit; font-size: 14.5px; font-weight: 500; color: var(--ink-2);
  cursor: pointer; transition: background .2s, color .2s; }
.nav-drop-knopf:hover { background: var(--card); color: var(--ink); }
/* Auf einer Unterseite: der Zweig ist zu erkennen, ohne zu behaupten, der
   Elternpunkt sei die aktuelle Seite — deshalb nur die Schriftfarbe. */
.top-nav .nav-drop--hier .nav-drop-knopf { color: var(--green-ink); }
.nav-drop-pfeil { width: 15px; height: 15px; transition: transform .2s ease; }
.nav-drop:hover .nav-drop-pfeil, .nav-drop:focus-within .nav-drop-pfeil,
[aria-expanded="true"] .nav-drop-pfeil { transform: rotate(180deg); }
.nav-sub {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 10;
  margin: 0; padding: 6px; list-style: none; min-width: 208px;
  background: var(--card); border: 1px solid var(--line-2);
  border-radius: var(--r-sm); box-shadow: var(--sh-2);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
}
/* Drei Wege, dasselbe zu oeffnen: Schweben fuer die Maus, Fokus fuer die
   Tastatur, aria-expanded fuer den Fingertipp (gesetzt von main.js).
   Der aria-Zweig steht bewusst als eigene Regel mit hoeherer Gewichtung —
   in der gemeinsamen Liste blieb er wirkungslos. */
.nav-drop:hover .nav-sub, .nav-drop:focus-within .nav-sub {
  opacity: 1; visibility: visible; transform: none;
}
.top-nav .nav-drop .nav-drop-knopf[aria-expanded="true"] + .nav-sub {
  opacity: 1; visibility: visible; transform: none;
}
/* Ohne diese Bruecke reisst der Zeiger auf dem Weg nach unten ab und das
   Menue klappt zu, bevor es erreicht ist. */
.nav-drop::after { content: ""; position: absolute; top: 100%; left: 0; right: 0; height: 10px; }
.top-nav .nav-sub a { display: block; padding: 10px 14px; border-radius: 9px;
  font-size: 14.5px; font-weight: 500; color: var(--ink-2); white-space: nowrap;
  border-left: 3px solid transparent; }
.top-nav .nav-sub a:hover { background: var(--card-2); color: var(--ink); }
/* Nur ein schmaler Balken statt einer gefuellten Flaeche: ein grüner Block
   im Aufklappmenue liest sich wie eine Vorauswahl, gemeint ist aber "hier
   stehen Sie gerade". */
.top-nav .nav-sub a[aria-current] { background: none; color: var(--green-ink);
  border-left-color: var(--green); font-weight: 600; }

.burger { display: none; margin-left: auto; width: 44px; height: 44px; padding: 11px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm); cursor: pointer; }
.burger svg { width: 22px; height: 22px; }
.burger .ic-x, .burger[aria-expanded="true"] .ic-menu { display: none; }
.burger[aria-expanded="true"] .ic-x { display: block; }

/* --- Karten --------------------------------------------------------------- */
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: 28px; box-shadow: var(--sh-1); }
.card--hover { transition: transform .28s cubic-bezier(.2,.75,.3,1), box-shadow .28s ease; }
.card--hover:hover { transform: translateY(-5px); box-shadow: var(--sh-2); }
.grid { display: grid; gap: clamp(16px, 2vw, 22px); }
.grid--2 { grid-template-columns: repeat(2, minmax(0,1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0,1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0,1fr)); }
.duo { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1.25fr); gap: clamp(28px, 4vw, 48px); align-items: start; }
.duo--even { grid-template-columns: repeat(2, minmax(0,1fr)); }
/* Zwei verschieden geformte Zeichnungen nebeneinander: Das V-Modell steht
   hochkant (Hoehe zu Breite 1,17), der Orchestrator quer (0,87). Bei gleich
   breiten Spalten waere das V-Modell ein Drittel hoeher als sein Nachbar.
   Damit beide gleich hoch stehen, bekommt die rechte Spalte das 1,4-fache —
   gerechnet aus den beiden Seitenverhaeltnissen, nicht geschaetzt. */
.duo--breiter-links { grid-template-columns: minmax(0,1.4fr) minmax(0,1fr); }
.duo--center { align-items: center; }
/* .duo richtet oben aus, damit ungleich lange Spalten nicht auseinanderlaufen.
   Stehen dort aber zwei gleichrangige Karten, sollen sie dieselbe Hoehe haben —
   sonst wirkt das Paar wie ein Versehen. */
.duo--gleich { align-items: stretch; }

/* Auf Navy war die 13-%-Auflage zu zaghaft — die Kachel verschwamm mit der
   Karte und das Symbol darin wirkte matt. Kräftigere Unterlage, sichtbare
   Kante, hellerer Strich: sichtbar, ohne zu leuchten. */
.ico-tile { display: grid; place-items: center; width: 46px; height: 46px; border-radius: var(--r-sm); background: var(--card-2); border: 1px solid var(--line-2); color: var(--ink); margin-bottom: 18px; flex: 0 0 auto; }
.ico-tile svg { width: 23px; height: 23px; }
.card p { margin: 8px 0 0; color: var(--muted); font-size: 14.5px; line-height: 1.6; }
/* Die Ueberschriftenebene richtet sich nach der Gliederung der Seite, die
   Optik nach der Klasse — deshalb hier alle Ebenen ansprechen. */
.card h2, .card h3, .card h4 { color: var(--ink); }

.chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
/* Auf Hell waren die Pillen eine Stufe dunkler als die Karte. Auf Navy kehrt
   sich das um: sie liegen über der Karte, sonst wirken sie wie Löcher. */
.chips li { background: var(--card-2); border-radius: var(--pill); padding: 8px 15px; font-size: 13.5px; color: var(--ink-2); }
.flowchips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 24px; }
.flowchips span { background: var(--card-2); color: var(--ink-2); border-radius: var(--pill); padding: 7px 15px; font-size: 12.5px; font-weight: 600; }
.flowchips svg { width: 14px; height: 14px; color: var(--ink-2); }
.tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.tags span { background: var(--card-2); border-radius: var(--pill); padding: 5px 12px; font-size: 12px; color: var(--ink-2); }
/* --- Wortfeld: Begriffe, die auftauchen und verblassen ---------------------
   Die Woerter stehen verstreut, jedes blendet zu seiner eigenen Zeit ein,
   haelt kurz und geht wieder. Wer nur zwei Sekunden hinsieht, nimmt trotzdem
   etwas mit.

   **Sie ueberlappen sich nie** — das ist gerechnet, nicht gehofft. Sechs
   Spalten, vier Zeilen, Schrittweite elf: In dieser Anordnung stoesst bei zehn
   gleichzeitig sichtbaren Woertern kein Paar zusammen, gemessen an den echten
   Textbreiten der Schrift.

   Ausgenommen sind die vier Kernbegriffe. Sie stehen auf eigenen Plaetzen in
   der Mitte und duerfen sich ueber alles legen — ihr Zoom traegt sie auf das
   Doppelte, am Rand schnitte die Maske sie an.

   Statt einer harten Kante blendet eine Maske das Feld nach aussen weich aus.
   Ein Wort, das beim Zoomen an den Rand geraet, verliert sich dort, statt
   abgeschnitten zu werden. */
.wortfeld { position: relative; margin: 24px 0 0; overflow: hidden;
  /* Alle Groessen darin haengen an der Breite dieses Kastens (cqw), die Hoehe
     ueber aspect-ratio ebenfalls. Dadurch ist das Band auf dem Telefon
     dasselbe Bild wie auf dem Rechner, nur kleiner: gleiche Reihen, gleiche
     Plaetze, gleiche Bewegung. Die Deckel (min(), max-height) halten den
     Rechner bei den Werten, fuer die der Entwurf gemacht ist — kleiner als
     proportional ist immer sicher, groesser waere es nicht. */
  container-type: inline-size; aspect-ratio: 47 / 9; height: auto; max-height: 210px;
  -webkit-mask-image: radial-gradient(ellipse 130% 150% at 50% 50%, #000 62%, transparent 100%);
  mask-image: radial-gradient(ellipse 130% 150% at 50% 50%, #000 62%, transparent 100%); }
.wortfeld span { position: absolute; transform: translate(-50%,-50%); white-space: nowrap;
  opacity: 0; color: var(--ink); font-weight: 600;
  animation: wf-auf 66s linear infinite; }
/* Elf Eintraege teilen sich einen Platz, jeder also ein Elftel des Umlaufs
   (9,09 %): 0,89 s einblenden, 3,0 s stehen, 1,78 s wieder gehen. Das Ausblenden
   dauert genau doppelt so lang wie das Einblenden — ein Begriff soll da sein, ehe
   man ihn erwartet, und sich Zeit lassen beim Gehen. Die Kurven sind dieselben wie
   beim Kernbegriff: herein schnell und dann bremsend, hinaus zoegernd los und dann
   immer schneller. Linear sah bei gleicher Dauer traeger aus als das Gruen daneben. Danach bleibt der Platz 0,3 s
   leer, bevor der naechste beginnt: Ohne diese Luecke blendete an derselben
   Stelle einer aus, waehrend der naechste schon einblendet. Die Prozentwerte
   haengen an der Zahl der Eintraege je Platz — build.py bricht ab, wenn
   begriffe.md eine andere ergibt, und nennt die neuen Werte.

   Weil an jedem Platz fast immer einer laeuft, ist das Band durchgehend voll,
   und eine Ueberlappung kann es gar nicht geben, solange die Plaetze sich
   nicht beruehren. Das laesst sich einmal beim Bauen pruefen statt fuer jede
   Zeitscheibe. */
@keyframes wf-auf {
  0%     { opacity: 0; filter: blur(7px);
           animation-timing-function: cubic-bezier(.08,.82,.17,1); }
  1.35%  { opacity: var(--wf-o); filter: blur(0);
           animation-timing-function: linear; }
  5.9%   { opacity: var(--wf-o); filter: blur(0);
           animation-timing-function: cubic-bezier(.8,0,.92,.3); }
  8.6%   { opacity: 0; filter: blur(7px); }
  100%   { opacity: 0; filter: blur(7px); }
}
/* Nur noch die Deckkraft staffelt die Groessen. Die kleinen Grade trugen aus
   der Parallax-Fassung eine dauerhafte Unschaerfe mit, die dort Tiefe erzeugen
   sollte; in einem Band ohne Ebenen macht sie kleine Schrift bloss schwer
   lesbar. Unscharf ist jetzt allein der Weg herein und hinaus. */
.wf-0 { --wf-o: .34; font-size: min(1.915cqw, 18px); }
.wf-1 { --wf-o: .55; font-size: min(2.447cqw, 23px); }
.wf-2 { --wf-o: .80; font-size: min(3.085cqw, 29px); }
/* Der Kernbegriff tritt als Paar auf: Symbol und Wort. Ein Bild allein muesste
   geraten werden, neben dem Wort erklaert es sich. Zeitlich laeuft er wie die
   uebrigen, nur mit Zoom statt Stillstand. */
.wortfeld .wf-kern { display: flex; align-items: center; gap: min(.851cqw, 8px);
  color: var(--green-ink); z-index: 3; animation-name: wf-kern-auf; }
.wortfeld .wf-kern b { font-size: min(2.34cqw, 22px); font-weight: 700; }
.wortfeld .wf-kern svg { width: min(2.766cqw, 26px);
  height: min(2.766cqw, 26px); flex: 0 0 auto; }
/* Herein schnell und dann bremsend, wie ein Objektiv, das jemand von Hand
   zuzieht; hinaus zoegernd los und dann immer schneller. */
@keyframes wf-kern-auf {
  0%    { opacity: 0; transform: translate(-50%,-50%) scale(1.15); filter: blur(11px);
          animation-timing-function: cubic-bezier(.08,.82,.17,1); }
  1.35% { opacity: 1; transform: translate(-50%,-50%) scale(1);    filter: blur(0);
          animation-timing-function: linear; }
  5.9%  { opacity: 1; transform: translate(-50%,-50%) scale(1);    filter: blur(0);
          animation-timing-function: cubic-bezier(.8,0,.92,.3); }
  8.6%  { opacity: 0; transform: translate(-50%,-50%) scale(.88);  filter: blur(11px); }
  100%  { opacity: 0; transform: translate(-50%,-50%) scale(.88);  filter: blur(11px); }
}
.wf-hinweis { margin: 14px 0 0; max-width: 76ch; font-size: 13px; line-height: 1.6;
  color: var(--muted); }
/* Bei reduzierter Bewegung wird aus dem Band eine ruhige Begriffsliste — auf
   jeder Breite, und nur einmal: Die schmale Fassung traegt dieselben Woerter
   und wuerde die Liste sonst verdoppeln. Die Symbole entfallen dabei, sie
   sagen nichts, was die Woerter nicht sagen. */
@media (prefers-reduced-motion: reduce) {
  .wortfeld { display: flex; flex-wrap: wrap; position: static; height: auto;
    aspect-ratio: auto; max-height: none; gap: 9px 18px;
    -webkit-mask-image: none; mask-image: none; }
  .wortfeld span { position: static; transform: none; opacity: .6; animation: none;
    filter: none; font-size: 15px; font-weight: 500; }
  .wortfeld .wf-kern { opacity: .95; font-weight: 700; }
  .wortfeld .wf-kern b { font-size: 15px; }
}

/* --- Orchestrator und Rollen ------------------------------------------------
   Das Gegenstueck zum V-Modell daneben: dort was geprueft wird, hier wer es
   tut. Steht in einer halben Spalte, deshalb kein Mindestmass — die Zeichnung
   ist von vornherein fuer diese Breite entworfen. */
.orch { margin: 20px 0 0; }
.orch svg { display: block; width: 100%; height: auto; }

/* --- Anlagenskizze: vom Sensor bis zur Meldung ------------------------------
   Eine Zeichnung, die mit ihrer Breite skaliert — auf dem Telefon dasselbe
   Bild wie auf dem Rechner, nur kleiner. Frueher gab es eine zweite,
   gestapelte Fassung fuer schmale Schirme; sie war besser lesbar, zeigte aber
   eine andere Anordnung, und gewollt ist dieselbe. */
.skizze { margin: 30px 0 0; }
.skizze svg { display: block; width: 100%; height: auto; margin: 0 auto;
  max-width: 1040px; }

/* Der Regelfall neben seinem Text: klein, gerahmt, und die Erklaerung
   daneben als echte Schrift statt als Beschriftung im Bild. */
.skizze-klein { margin: 0; padding: 22px; border: 1px solid var(--line-2);
  border-radius: var(--r); background: var(--card-2); }
.skizze-klein svg { display: block; width: 100%; height: auto; }

/* --- Vier Welten im Ring ---------------------------------------------------
   Das Bild der Leistungsseite. Es sagt etwas anderes als das Kompetenzrad auf
   der Startseite: dort "was koennen die", hier "wo sitzen die". Deshalb ein
   zweites Bild und nicht ein umgebautes erstes.

   Die Beschriftung darunter ist echter Text und keine Bildunterschrift im
   Wortsinn: Sie traegt die Erklaerung der vier Nahtstellen und bleibt damit
   lesbar, wenn jemand das SVG nicht sieht. */
.venn { margin: 32px 0 0; }
.venn svg { display: block; width: 100%; max-width: 470px; height: auto; margin: 0 auto; }
.venn figcaption { display: grid; gap: 9px; margin-top: 20px; font-size: 14.5px;
  line-height: 1.55; color: var(--muted); }
.venn figcaption b { color: var(--ink); font-weight: 600; }

/* --- Gruppenkarten (Leistungen: Bauen, Planen, Führen) -------------------- */
/* Drei Karten mit je zwei bis drei Punkten statt sieben gleicher Zeilen: die
   Gruppe gibt die Ordnung, der Punkt bleibt Sprungmarke aus der Fusszeile. */
.gruppe .t-h3 { margin-top: 6px; }
.gruppe-punkt { display: flex; gap: 12px; align-items: flex-start; margin-top: 16px; }
.gruppe-punkt > svg { flex: 0 0 auto; width: 20px; height: 20px; margin-top: 2px; color: var(--green-deep); }
.gruppe-punkt b { display: block; font-size: 15px; line-height: 1.35; }
.gruppe-punkt p { margin: 3px 0 0; font-size: 13.5px; line-height: 1.5; color: var(--muted); }

/* --- Kopfbereich ---------------------------------------------------------- */
.hero-sec { padding-block: clamp(40px, 5vw, 84px) 0 !important; }
/* Oben ausrichten, nicht mittig: das Rad ist deutlich hoeher als der Text, bei
   zentrierter Ausrichtung rutschte die Ueberschrift rund hundert Pixel unter
   die Kopfzeile. Der Text soll direkt anschliessen. */
.hero-grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: clamp(32px, 4vw, 52px); align-items: start; }
.hero-visual { display: flex; justify-content: flex-end; padding-bottom: 96px; }

/* --- Kompetenzrad --------------------------------------------------------- */
.wheel { position: relative; width: 100%; max-width: 510px; aspect-ratio: 1; container-type: inline-size; margin: 0; }
.wheel svg.wheel-svg { width: 100%; height: 100%; }
.wheel-seg { transition: fill .5s ease, stroke .5s ease; cursor: default; }
/* Der aktive Ring-Abschnitt hebt sich als grün angehobene Fläche von den
   übrigen ab (--card-2 mit 18 % Markenton unterlegt), Rand im vollen Grün. */
.wheel-seg.on { fill: #3F5B54; stroke: var(--green); stroke-width: 1.6; }
.wheel-ol { position: absolute; inset: 0; pointer-events: none; }
/* Die Mitte lag auf --dark und ging zwischen den angehobenen Segmenten unter.
   Sie trägt jetzt den Markenton: der Kern des Rades ist auch der Kern der
   Aussage. Dunkle Schrift darauf liefert 9.2:1. */
.wheel-core { position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); text-align: center; color: var(--on-green); font-weight: 700; font-size: clamp(16px, 4.2cqi, 24px); line-height: 1.28; }
.wheel-lab { position: absolute; display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; width: clamp(66px, 16.4cqi, 96px); transform: translate(-50%,-50%); color: var(--ink); transition: color .5s ease, transform .5s ease; }
/* Ruhezustand hell genug zum Lesen, aber unbunt — den Markenton bekommt erst
   das aktive Segment, sonst ginge der Zustandswechsel verloren. */
.wheel-lab svg { width: clamp(18px, 4.6cqi, 26px); height: clamp(18px, 4.6cqi, 26px); color: var(--ink-2); transition: color .5s ease; }
.wheel-lab span { font-size: clamp(11px, 2.7cqi, 16px); line-height: 1.22; font-weight: 500; }
.wheel-lab.on { color: var(--green-ink); transform: translate(-50%,-50%) scale(1.06); }
.wheel-lab.on svg { color: var(--green-deep); }
.wheel-bico { position: absolute; transform: translate(-50%,-50%); }
/* Keine Strichstärke hier: die setzt der Generator je Symbol, damit sie trotz
   der Größennormierung überall gleich ausfällt (siehe _viewbox in build.py). */
.wheel-bico svg { width: clamp(18px, 4.6cqi, 26px); height: clamp(18px, 4.6cqi, 26px); color: var(--green-deep); }
/* Der Erklärkasten hängt unter dem Rad und liegt bewusst *über* dem Fluss:
   Die Hervorhebung wandert alle fünf Sekunden weiter, und die acht Texte sind
   verschieden lang. Läge der Kasten im Fluss, schöbe er bei jedem Wechsel die
   halbe Seite auf und ab. Den Platz dafür hält `.hero-visual` mit seinem
   unteren Innenabstand frei — die beiden Werte gehören zusammen, wer den einen
   ändert, muss den anderen nachziehen. */
.wheel-note { position: absolute; inset-inline: 0; top: 100%; padding-top: 14px; }
/* Gehört zum Rad und liegt deshalb auf derselben angehobenen Fläche wie
   dessen Segmente — sonst fiele der Erklärtext hinter die Grafik zurück. */
.wheel-note > div { display: flex; align-items: flex-start; gap: 12px; background: var(--card-2); border: 1px solid var(--line-2); border-radius: var(--r); padding: 12px 16px; min-height: 74px; box-shadow: var(--sh-1); }
.wheel-note .ico-tile { width: 34px; height: 34px; margin: 0; border-radius: 11px; }
.wheel-note .ico-tile svg { width: 17px; height: 17px; }
.wheel-note b { font-size: 13.5px; }
.wheel-note p { margin: 0; font-size: 13px; line-height: 1.5; color: var(--ink-2); }

@keyframes weSpin { to { transform: rotate(360deg); } }
@keyframes weDraw { from { stroke-dashoffset: var(--len); } to { stroke-dashoffset: 0; } }
/* Zwei gegenläufige Bahnen; Drehpunkt kommt aus dem Markup. */
.we-dots--in  { animation: weSpin 150s linear infinite; }
.we-dots--out { animation: weSpinR 105s linear infinite; }
@keyframes weSpinR { to { transform: rotate(-360deg); } }
/* Die Kugelbahnen laufen durchgehend — auch bei Zeigerkontakt. */
.we-band { stroke-dasharray: var(--len); animation: weDraw 1.15s cubic-bezier(.3,.7,.3,1) both; }
.we-band[data-i="1"] { animation-delay: .18s; }
.we-band[data-i="2"] { animation-delay: .36s; }

/* --- Produktkarten -------------------------------------------------------- */
/* Kopf der Kachel: entweder das Produktlogo oder – solange keines vorliegt –
   Kuerzel und Name. Feste Hoehe, damit beide Kacheln auf einer Linie beginnen. */
.prod-head { display: flex; align-items: center; gap: 12px; min-height: 46px; }
/* Das Logo braucht eine helle Unterlage, sonst verschwindet die farbige Marke
   auf Navy. Breite ueber die Hoehe geregelt, da das SVG width/height="100%"
   traegt und keine ableitbare Eigengroesse hat. */
.prod-logo { height: 46px; width: auto; max-width: 250px; object-fit: contain;
  background: #FFFFFF; border-radius: 12px; padding: 8px 14px; }
/* Freigestellte PNG-Wortmarke (TerraOptima) auf dunkler Flaeche: kein weisses Plaettchen.
   Hoehe entspricht dem Plaettchen der SVG-Marke (46 + 2 x 8), damit beide
   Kacheln auf einer Linie stehen; das Seitenverhaeltnis kommt aus width/height. */
.prod-logo--marke { height: 62px; max-width: 100%; background: none; padding: 0;
  border-radius: 0; }
/* --- Auftakt der Pilot-Seite ---------------------------------------------
   Erst die Marke, dann der Termin, dann der Satz, der sagt was sie tut. Alles
   mittig und vor dem ersten Fliesstext: Wer die Seite oeffnet, soll sie in
   einem Blick einordnen koennen. Das Logo steht auf einem weissen Plaettchen,
   damit die farbige Marke auch auf dem dunklen Grund der Firmenseite traegt. */
.auftakt { display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 20px; padding: 30px 0 6px; }
/* Ueber die ganze Spaltenbreite, damit der Satz in zwei Zeilen steht und nicht
   als schmaler Block unter dem Logo klebt. */
.auftakt-claim { margin: 0; max-width: 100%; text-wrap: balance;
  font-size: clamp(1.75rem, 4.5vw, 3.3rem); }
/* Der Slogan ist ein ganzer Satz: vorn, was es ist, danach die drei Aufgaben.
   Alles in voller Groesse ergab auf dem Telefon sechs Zeilen Ueberschrift. Der
   Wortlaut bleibt vollstaendig in der h1, nur die Aufzaehlung tritt zurueck. */
.auftakt-claim-rest { display: block; margin-top: .45em; font-size: clamp(1.05rem, 2vw, 1.55rem);
  font-weight: 600; line-height: 1.35; letter-spacing: -.012em; color: var(--ink-2);
  text-wrap: balance; }
.auftakt-sec { padding-bottom: 0; }
@media (max-width: 560px) {
  .auftakt { gap: 16px; padding-top: 12px; }
  .auftakt-claim { max-width: 22ch; font-size: 1.6rem; }
}

.prod-claim { margin: 18px 0 0; font-size: 16px; font-weight: 700; color: var(--ink);
  letter-spacing: -.015em; line-height: 1.35; }
.prod-text { margin: 10px 0 0; color: var(--ink-2); font-size: 14.5px; line-height: 1.6; }

/* Zwei Ansichten nebeneinander. Es sind Ausschnitte echter Oberflaechen: das
   Bild wird oben links verankert, damit der wesentliche Bereich sichtbar
   bleibt, statt die ganze Ansicht auf Briefmarkengroesse zu stauchen. */
/* auto-fit statt fester Zweispaltigkeit: Steht dort nur ein Bild, nimmt es die
   ganze Breite ein, statt halb so breit neben einer Luecke zu haengen. */
.prod-shots { display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: 12px; margin-top: 22px; }
.prod-shot { margin: 0; }
.prod-shot img { width: 100%; aspect-ratio: 16 / 11; object-fit: cover;
  object-position: top left; border-radius: var(--r-sm);
  border: 1px solid var(--line-2); background: var(--dark); display: block; }
/* Ein Bild sieht nicht nach Verweis aus. Der Zeiger sagt es zuerst, beim
   Ueberfahren kommen Markenrand und ein leichtes Anheben dazu — dieselbe
   Sprache, die die Karten der Seite ohnehin sprechen. */
.prod-shot-link { display: block; border-radius: var(--r-sm); cursor: pointer;
  transition: transform .25s cubic-bezier(.2,.7,.2,1), box-shadow .25s ease; }
.prod-shot-link:hover, .prod-shot-link:focus-visible { transform: translateY(-3px);
  box-shadow: var(--sh-1); }
.prod-shot-link:hover img, .prod-shot-link:focus-visible img { border-color: var(--green); }
.prod-shot figcaption { margin-top: 8px; font-size: 12px; line-height: 1.4; color: var(--muted); }
@media (prefers-reduced-motion: reduce) { .prod-shot-link { transition: none; }
  .prod-shot-link:hover, .prod-shot-link:focus-visible { transform: none; } }
@media (max-width: 520px) { .prod-shots { grid-template-columns: minmax(0,1fr); } }

/* Die beiden Produkte stehen untereinander statt nebeneinander: erst so werden
   die Ansichten gross genug, um etwas zu erkennen. Der Text bleibt schmaler als
   die Kachel, damit die Zeilenlaenge lesbar bleibt. */
.prod-stack { grid-template-columns: minmax(0,1fr); gap: clamp(20px, 3vw, 32px); }
.prod-stack .card { padding: clamp(26px, 3.2vw, 40px); }
.prod-stack .prod-claim { font-size: clamp(17px, 2.1vw, 21px); max-width: 34ch; }
.prod-stack .prod-text { font-size: 15.5px; max-width: 78ch; }
.prod-stack .prod-logo { height: 54px; max-width: 290px; }
.prod-stack .prod-logo--marke { height: 70px; max-width: 100%; }
.prod-stack .prod-shot img { aspect-ratio: 16 / 10; }
/* --- Kopf der Produktseiten -----------------------------------------------
   Das Logo ersetzt den Schriftzug und ist zugleich der Verweis auf die
   Marken-Domain. Groesse an der Ueberschrift ersten Grades orientiert, die es
   ersetzt; die Ueberschrift selbst bleibt fuer Suchmaschinen und Vorleser
   unsichtbar im Code (.sr-only). */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.prod-titel { display: inline-block; margin: 14px 0 16px; border-radius: 12px; }
.prod-titel .prod-logo { height: 64px; max-width: 340px; display: block; }
/* Die PNG-Wortmarke traegt links 59 von 1600 Pixeln Luft; der negative Rand
   stellt das T buendig an die Textkante. Breite statt Hoehe, damit das Bild
   auf schmalen Schirmen mitschrumpft und der Rand im selben Verhaeltnis bleibt. */
.prod-titel .prod-logo--marke { height: auto; width: min(100%, 440px);
  margin-left: calc(min(100%, 440px) * -0.037); }
.prod-titel:hover { opacity: .88; }
.prod-titel:focus-visible { outline: 2px solid var(--green); outline-offset: 4px; }
.prod-stack .prod-shot figcaption { font-size: 12.5px; }

/* Weiß auf --green ergäbe nur 2.0:1. Dunkle Schrift auf der Markenfläche liefert
   9.3:1 und entspricht der Schaltfläche. */
.prod-mark { display: grid; place-items: center; width: 42px; height: 42px; border-radius: 11px; background: var(--green); color: var(--on-green); font-weight: 700; font-size: 15px; }
.badge { display: inline-flex; align-items: center; gap: 6px; background: var(--card-2); color: var(--ink-2); border-radius: var(--pill); padding: 6px 13px; font-size: 12px; font-weight: 600; }
.badge svg { width: 13px; height: 13px; }
/* Verfügbarkeitshinweis für Produkte, die noch nicht zu haben sind. Die Kante
   statt einer Füllung: der Hinweis soll auffallen, sich aber nicht vor den
   Produktnamen schieben. Die Linie liegt als inset-Schatten an, damit die
   Pille exakt so hoch bleibt wie die Einordnungs-Pille daneben. */
.badge--soon { background: transparent; color: var(--green-ink); box-shadow: inset 0 0 0 1px var(--green); }
.badge--soon svg { color: var(--green-deep); }
.badge-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* --- Produktbühne --------------------------------------------------------- */

/* --- Dunkle Blöcke -------------------------------------------------------- */
/* Gleiche Familie wie .cta und aus demselben Grund angehoben statt vertieft:
   der abgesetzte Block trägt auf Navy nur noch nach oben. Ohne Markenschimmer,
   damit der Handlungsaufruf der lauteste Block der Seite bleibt. */
.dark-card { background: var(--card-2); color: var(--ink); border: 1px solid var(--line-2); border-radius: var(--r); box-shadow: var(--sh-1); padding: clamp(26px, 3vw, 38px); }
.dark-card .eyebrow { color: var(--green); }
.dark-card p { color: var(--ink-2); }
.dark-card .chips li { background: rgba(255,255,255,.09); color: var(--ink-2); }
.checks { display: grid; gap: 8px; margin-top: 12px; font-size: 14.5px; color: var(--ink-2); }
.checks span { display: inline-flex; align-items: flex-start; gap: 9px; }
.checks svg { width: 16px; height: 16px; color: var(--ink-2); flex: 0 0 auto; margin-top: 3px; }

/* --- In einfachen Worten -------------------------------------------------
   Steht ganz oben auf den Seiten, die es fachlich in sich haben, und erklaert
   die Sache so, wie man sie einem Nachbarn erklaeren wuerde. Kein Ersatz fuer
   den Fachtext darunter, sondern die Eintrittskarte dazu: Wer den Kasten
   gelesen hat, versteht auch den Rest besser.

   Bewusst als angehobene Flaeche mit gruener Kante, damit man ihn nicht fuer
   eine Randnotiz haelt und ueberspringt. */
.einfach { margin: 26px 0 0; padding: 22px 24px; background: var(--card);
  border: 1px solid var(--line); border-left: 3px solid var(--green);
  border-radius: var(--r-sm); max-width: 74ch; }
.einfach b { display: flex; align-items: center; gap: 9px; font-size: 13px;
  font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--green-ink); }
.einfach b svg { width: 17px; height: 17px; flex: 0 0 auto; }
.einfach p { margin: 12px 0 0; color: var(--ink-2); font-size: 15.5px; line-height: 1.68; }

/* Merksatz neben der Ueberschrift: die Kernaussage eines langen Abschnitts,
   damit sie auch beim Ueberfliegen haengen bleibt. */
.merksatz { margin: 18px 0 0; padding-left: 16px; border-left: 3px solid var(--green);
  color: var(--ink); font-size: 15px; line-height: 1.6; font-weight: 500; max-width: 34ch; }

/* Dunkle Ziffer auf der vollen Markenfläche – heller Text auf Grün bleibt zu schwach. */
.step-no { display: inline-grid; place-items: center; width: 38px; height: 38px; border-radius: var(--pill); background: var(--card-2); border: 1px solid var(--line-2); color: var(--ink); font-weight: 700; font-size: 13.5px; margin-bottom: 14px; }

/* --- Handlungsaufruf ------------------------------------------------------ */
/* Auf hellem Grund war dieser Block fast schwarz — er trug allein durch den
   Helligkeitssprung. Auf Navy ist derselbe Weg nach unten versperrt: „noch
   dunkler" endet in der Fläche. Der Block geht deshalb nach oben — angehobene
   Fläche, kräftige Kante, sichtbarer Markenschimmer. Er ist damit der hellste
   Block der Seite und behält seine Rolle als lautester Punkt. */
.cta { position: relative; overflow: hidden; color: var(--ink);
  background: linear-gradient(152deg, var(--card-2), var(--card) 66%);
  border: 1px solid var(--line-2); border-radius: var(--r-lg);
  box-shadow: var(--sh-2); padding: clamp(30px, 4vw, 56px); }
.cta::before { content: ""; position: absolute; width: 560px; height: 560px; right: -170px; top: -220px; border-radius: 50%; background: radial-gradient(circle, rgba(127,203,40,.30), transparent 66%); }
.cta-in { position: relative; display: grid; grid-template-columns: minmax(0,1.4fr) auto; gap: 32px; align-items: center; }
.cta p { margin: 12px 0 0; color: var(--ink-2); font-size: 15.5px; max-width: 56ch; }
.cta-lock { display: inline-flex; align-items: center; gap: 8px; margin-top: 18px; color: var(--ink-2); font-size: 13.5px; }
.cta-lock svg { width: 15px; height: 15px; }

/* --- Kontakt -------------------------------------------------------------- */
.contact-line { display: flex; align-items: center; gap: 16px; padding: 15px 0; border-bottom: 1px solid var(--line); }
.contact-line .ico-tile { width: 42px; height: 42px; margin: 0; }
.contact-line svg { width: 21px; height: 21px; }
/* :not(.ico-tile) ist Pflicht, nicht Feinschliff: die Kachel ist selbst ein
   <span>, und .contact-line span (0,1,1) schlägt .ico-tile (0,1,0). Ohne den
   Ausschluss wird ihr display:grid zu block überschrieben — place-items greift
   dann nicht mehr und das Symbol hängt oben in der Kachel. */
.contact-line span:not(.ico-tile) { display: block; font-size: 12px; letter-spacing: .08em; color: var(--muted); }
.contact-line b { font-size: 15px; }
/* Die Adresse steht als eigene Angabe da, nicht als Verweis mitten im Satz —
   deshalb bekommt sie die volle Zielgroesse (WCAG 2.2, 24px). */
.contact-line b a, .legal-tile b a { display: inline-flex; align-items: center;
  min-height: 26px; }
.field { display: block; margin-bottom: 18px; font-size: 13.5px; font-weight: 600; color: var(--ink-2); }
.field input, .field select, .field textarea {
  display: block; width: 100%; margin-top: 7px; padding: 13px 15px;
  /* Die Felder lagen auf --dark und wirkten als fast schwarze Löcher in der
     Karte. Sie liegen jetzt eine Stufe über ihr — ein Eingabefeld soll
     anfassbar aussehen, nicht ausgestanzt. */
  border: 1.5px solid var(--line-2); border-radius: var(--r-sm); background: var(--card-2);
  font: inherit; font-size: 16px; font-weight: 400; color: var(--ink);
  transition: border-color .18s ease, box-shadow .18s ease;
}
.field textarea { min-height: 130px; resize: vertical; }
.field ::placeholder { color: var(--muted); }
.field :hover { border-color: #647CA3; }
.field :focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 4px rgba(127,203,40,.22); }
.field-duo { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 16px; }
.consent { display: grid; grid-template-columns: 24px minmax(0,1fr); gap: 12px; align-items: start; font-size: 13px; font-weight: 400; color: var(--muted); line-height: 1.55; margin-bottom: 22px; }
.consent input { width: 24px; height: 24px; margin-top: 0; accent-color: var(--green); }
.consent a { text-decoration: underline; }
.hp { position: absolute !important; left: -9999px !important; }
.form-note { margin: 14px 0 0; font-size: 13px; color: var(--muted); }

/* --- Fußzeile ------------------------------------------------------------- */
.foot { background: var(--dark); color: var(--ink-2); border-top: 1px solid var(--line); margin-top: var(--band); }
.foot-grid { display: grid; grid-template-columns: minmax(0,1.4fr) repeat(3, minmax(0,1fr)); gap: 38px; padding-block: 56px; }
/* Produktseite: nur Marke, Rechtliches, Produkt (Spalte „Anbieter“ entfiel 21.10.2026) */
.foot-grid--drei { grid-template-columns: minmax(0,1.4fr) repeat(2, minmax(0,1fr)); }
.foot-logo { width: 210px; height: auto; filter: brightness(0) invert(1); opacity: .95; }
.foot-brand p { margin: 18px 0 0; font-size: 14px; line-height: 1.65; max-width: 34ch; color: #8995A6; }
.foot h2 { font-size: 13px; color: var(--ink); letter-spacing: .08em; margin: 0 0 14px; font-weight: 600; }
.foot a { display: block; padding: 6px 0; font-size: 14px; color: #98A5B6; }
.foot a:hover { color: #fff; }
.foot-end { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; padding: 20px 0; border-top: 1px solid rgba(255,255,255,.09); font-size: 12.5px; color: #919FB1; }

/* --- Umbruch -------------------------------------------------------------- */
@media (max-width: 1080px) {
  .grid--4 { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .foot-grid { grid-template-columns: repeat(2, minmax(0,1fr)); }
}
@media (max-width: 900px) {
  .top-nav { position: fixed; inset: 76px 0 auto 0; flex-direction: column; align-items: stretch; gap: 6px; background: var(--bg); border-bottom: 1px solid var(--line); padding: 14px var(--gutter) 24px; display: none; box-shadow: var(--sh-2); }
  .top-nav.open { display: flex; }
  .top-nav a { padding: 14px 16px; border-radius: var(--r-sm); font-size: 16px; background: var(--card); border: 1px solid var(--line); }
  .top-nav .btn { margin: 10px 0 0; justify-content: center; }
  /* Im ausgeklappten Menue gibt es kein Schweben — das Untermenue steht
     deshalb dauerhaft offen und eingerueckt unter seinem Elternpunkt. */
  .nav-drop { display: flex; flex-direction: column; gap: 6px; }
  .nav-drop-pfeil { display: none; }
  /* Im Mobilmenue steht das Untermenue ohnehin offen — der Elternpunkt ist
     dort nur noch Ueberschrift und braucht kein Aussehen einer Schaltflaeche. */
  .nav-drop-knopf { padding: 14px 16px 6px; font-size: 13px; font-weight: 700;
    letter-spacing: .1em; text-transform: uppercase; color: var(--muted); cursor: default; }
  .nav-drop-knopf:hover { background: none; color: var(--muted); }
  .nav-sub { position: static; opacity: 1; visibility: visible; transform: none;
    min-width: 0; padding: 0; margin-left: 16px; background: none; border: 0;
    box-shadow: none; display: flex; flex-direction: column; gap: 6px; }
  .nav-drop::after { display: none; }
  .top-nav .nav-sub a { padding: 12px 16px; font-size: 15px;
    background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm); }
  .burger { display: block; }
  .hero-grid, .duo, .duo--even, .duo--breiter-links,
  .cta-in, .grid--2, .grid--3
    { grid-template-columns: minmax(0,1fr); }
  .hero-visual { justify-content: center; }
}
@media (max-width: 700px) {
  body { font-size: 16px; }
  .grid--4 { grid-template-columns: minmax(0,1fr); }
  .field-duo { grid-template-columns: minmax(0,1fr); }
  .btn-row .btn { width: 100%; justify-content: center; }
  .foot-grid { grid-template-columns: minmax(0,1fr); gap: 28px; }
  /* Auf einer Spalte wird der Erklärkasten schmal und damit hoch: derselbe Text
     braucht statt drei Zeilen sechs. Der freigehaltene Platz muss für den
     längsten der acht Texte reichen, sonst schiebt sich der Kasten über die
     Pillen darunter. Die Mindesthöhe hält den Kasten bei kurzen Texten auf
     derselben Größe, damit das freie Feld nicht als Lücke auffällt. */
  .hero-visual { padding-bottom: 186px; }
  .wheel-note > div { min-height: 158px; }
}
@media (max-width: 400px) {
  .hero-visual { padding-bottom: 206px; }
  .wheel-note > div { min-height: 178px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  html:focus-within { scroll-behavior: auto; }
  .we-band { stroke-dashoffset: 0 !important; }
}
/* Gedruckt wird auf Papier, nicht auf Navy: die Fläche wird weiß, und die
   Tokens werden auf die hellen Entsprechungen zurückgedreht — sonst käme
   heller Text auf weißem Grund heraus. */
@media print {
  .top, .foot, .btn-row, .wheel { display: none !important; }
  :root {
    --bg: #fff; --bg-2: #F4F6F9; --card: #fff; --card-2: #fff; --dark: #F4F6F9;
    --ink: #101820; --ink-2: #33404E; --muted: #55616F;
    --line: #C8D1DC; --line-2: #B4C0D0;
    --green-ink: #2F5A08; --green-deep: #4A860D; --green-wash: #EDF7DE;
    --sh-1: none; --sh-2: none;
  }
  body { background: #fff; color: #101820; font-size: 11pt; }
  .cta, .dark-card { color: #101820 !important; }
  .cta p, .dark-card p, .cta-lock { color: #33404E !important; }
}

/* --- Rechtstexte ---------------------------------------------------------- */
.legal h2 { font-size: 1.25rem; letter-spacing: -.02em; font-weight: 700; margin: 38px 0 12px; }
.legal h2:first-child { margin-top: 0; }
.legal p, .legal li { color: var(--ink-2); font-size: 15.5px; }
.legal ul { padding-left: 20px; }

/* Die Pflichtangaben standen als Kette aus Überschrift und Absatz untereinander.
   Als Kachelraster sind sie auf einen Blick erfassbar — und genau das ist der
   Zweck eines Impressums: nachschlagen, nicht lesen. */
.legal-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(238px, 1fr));
  gap: 14px; margin-bottom: 44px; }
.legal-tile { background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 20px 22px; }
.legal-tile .ico-tile { width: 38px; height: 38px; border-radius: 11px; margin-bottom: 14px; }
.legal-tile .ico-tile svg { width: 19px; height: 19px; }
.legal-tile-k { display: block; font-size: 12px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 7px; }
.legal-tile b { display: block; font-size: 15px; font-weight: 600; line-height: 1.55; color: var(--ink); }
.legal-tile a { text-decoration: underline; text-underline-offset: 3px; }

/* Auf schmalen Schirmen ist der Ring zu klein für acht große Beschriftungen.
   Dort wird die Schrift im Rad kleiner — die vollständige Erläuterung steht
   ohnehin darunter in Lesegröße. */
@media (max-width: 760px) {
  .wheel-lab { width: 54px; gap: 2px; }
  .wheel-lab span { font-size: 11px; line-height: 1.15; }
  .wheel-lab svg { width: 15px; height: 15px; }
  .wheel-core { font-size: 15px; }
  .wheel-bico svg { width: 17px; height: 17px; }
}
@media (max-width: 400px) {
  .wheel-lab { width: 50px; }
  .wheel-lab span { font-size: 10.5px; }
  .wheel-lab svg { width: 13px; height: 13px; }
}

/* ==========================================================================
   Einblenden beim Scrollen
   Versteckt wird ausschließlich unter html.js — diese Klasse setzt ein
   Inline-Skript im <head>, also vor dem ersten Bildaufbau. Ohne JavaScript
   und bei prefers-reduced-motion ist alles sofort sichtbar, es gibt kein
   Aufblitzen und keinen unerreichbaren Inhalt.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  html.js .sec-head,
  html.js .card,
  html.js .dark-card,
  html.js .cta,
  html.js .pillchips,
  html.js .legal,
  html.js [data-rise] {
    opacity: 0;
    transform: translateY(22px);
    transition: opacity .7s ease, transform .7s cubic-bezier(.2,.75,.3,1);
  }
  html.js .is-in { opacity: 1 !important; transform: none !important; }

  /* Karten einer Reihe laufen versetzt ein */
  html.js .grid > *:nth-child(2) { transition-delay: .07s; }
  html.js .grid > *:nth-child(3) { transition-delay: .14s; }
  html.js .grid > *:nth-child(4) { transition-delay: .21s; }
  html.js .grid > *:nth-child(5) { transition-delay: .28s; }
  html.js .grid > *:nth-child(6) { transition-delay: .35s; }

  /* Kopfbereich blendet beim Laden ein statt beim Scrollen */
  @keyframes weSeq { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }
  html.js .hero-grid > *  { animation: weSeq .85s cubic-bezier(.2,.75,.3,1) both; }
  html.js .hero-grid > *:nth-child(2) { animation-delay: .14s; }
}

/* --- Produkt-Screenshot ---------------------------------------------------- */
/* Der Fensterrahmen (Titelleiste, Punkteleiste) lag auf --dark und war gegen
   die Navy-Fläche praktisch nicht zu sehen. Er liegt jetzt darüber; dunkel
   bleibt nur die Bildfläche selbst — dort deckt ohnehin der Screenshot. */
.shot { margin: 0; border: 1px solid var(--line-2); border-radius: var(--r); overflow: hidden;
  box-shadow: var(--sh-2); background: var(--card-2); }
.shot img { width: 100%; height: auto; }

/* --- App-Showcase: selbstlaufende Bildergalerie ---------------------------- */
.appshow { position: relative; color: #fff; }
.appshow-bar { display: flex; align-items: center; gap: 7px; padding: 10px 16px;
  border-bottom: 1px solid rgba(255,255,255,.10); font-size: 12px; letter-spacing: .09em; color: #B3BFCE; }
.appshow-bar i { width: 9px; height: 9px; border-radius: 50%; opacity: .85; flex: none; }
.appshow-name { margin-left: 8px; font-weight: 600; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.appshow-count { margin-left: auto; padding-left: 10px; color: #A9B6C7; font-variant-numeric: tabular-nums; flex: none; }
.appshow-view { position: relative; aspect-ratio: 16 / 10; background: var(--dark); }
.appshow-track { list-style: none; margin: 0; padding: 0; height: 100%; }
.appshow-slide { position: absolute; inset: 0; margin: 0; opacity: 0; visibility: hidden;
  transition: opacity .55s ease; }
.appshow-slide.is-active { opacity: 1; visibility: visible; }
.appshow-slide img { width: 100%; height: 100%; object-fit: cover; object-position: top left;
  cursor: zoom-in; }
.appshow-cap { position: absolute; left: 0; right: 0; bottom: 0; margin: 0;
  padding: 34px 18px 14px; font-size: 12.5px; line-height: 1.45; color: #E9EDF4;
  background: linear-gradient(to top, rgba(4,9,15,.86), rgba(4,9,15,.5) 55%, rgba(4,9,15,0)); }
.appshow-nav { position: absolute; top: 50%; transform: translateY(-50%); width: 40px; height: 40px;
  display: grid; place-items: center; border: 0; border-radius: 50%; background: rgba(13,23,35,.55);
  color: #fff; cursor: pointer; opacity: 0; transition: opacity .2s, background .2s, color .2s; }
.appshow-prev { left: 12px; } .appshow-next { right: 12px; }
.appshow-nav svg { width: 20px; height: 20px; }
.appshow-play { position: absolute; right: 12px; bottom: 12px; width: 30px; height: 30px;
  display: grid; place-items: center; border: 0; border-radius: 50%; background: rgba(13,23,35,.55);
  color: #fff; cursor: pointer; opacity: 0; transition: opacity .2s, background .2s, color .2s; }
.appshow-play svg { width: 13px; height: 13px; }
.appshow-play .ic-play { display: none; }
.appshow-play[data-playing="false"] .ic-pause { display: none; }
.appshow-play[data-playing="false"] .ic-play { display: block; }
.appshow:hover .appshow-nav, .appshow:focus-within .appshow-nav,
.appshow:hover .appshow-play, .appshow:focus-within .appshow-play { opacity: 1; }
.appshow-nav:hover, .appshow-play:hover { background: var(--green); color: var(--on-green); }
.appshow-dots { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center;
  padding: 13px 16px; background: var(--card-2); border-top: 1px solid rgba(255,255,255,.10); }
/* Der sichtbare Punkt bleibt klein, die Trefferflaeche waechst ueber einen
   Pseudoelement-Rahmen auf 26x26 — sonst ist er auf dem Handy kaum zu treffen. */
.appshow-dot { position: relative; width: 8px; height: 8px; padding: 0; border: 0; border-radius: 50%;
  background: rgba(255,255,255,.34); cursor: pointer; transition: background .2s, width .2s; }
.appshow-dot::after { content: ""; position: absolute; left: 50%; top: 50%;
  width: 26px; height: 26px; transform: translate(-50%, -50%); }
.appshow-dot:hover { background: rgba(255,255,255,.6); }
.appshow-dot.is-active { background: var(--green); width: 22px; border-radius: 5px; }
.appshow-zoom { position: absolute; right: 12px; top: 12px; width: 30px; height: 30px;
  display: grid; place-items: center; border: 0; border-radius: 50%; background: rgba(13,23,35,.55);
  color: #fff; cursor: pointer; opacity: 0; transition: opacity .2s, background .2s, color .2s; }
.appshow-zoom svg { width: 15px; height: 15px; }
.appshow:hover .appshow-zoom, .appshow:focus-within .appshow-zoom { opacity: 1; }
.appshow-zoom:hover { background: var(--green); color: var(--on-green); }
@media (prefers-reduced-motion: reduce) { .appshow-slide { transition: none; } }

/* --- Geraete ohne Zeiger (Telefon, Tablet) -------------------------------
   Pfeile, Pause und Lupe erscheinen sonst erst beim Ueberfahren — ein Finger
   faehrt aber nicht ueber. Auf solchen Geraeten waere die Galerie damit nur
   ueber die Punkte bedienbar und die Grossansicht gar nicht erreichbar.
   Also: dauerhaft sichtbar, und gross genug, um sie zu treffen. */
@media (hover: none) {
  .appshow-play, .appshow-zoom { opacity: 1; width: 40px; height: 40px; }
  /* Die Pfeile entfallen: gewischt wird ohnehin, und die Punkte stehen
     darunter. Auf einem Bild von 340 Pixeln Breite waeren vier Knoepfe
     schlicht zu viel. */
  .appshow-nav { display: none; }
  /* Beide Knoepfe nach oben, damit sie der Bildunterschrift nicht im Weg
     stehen. */
  .appshow-play { top: 12px; right: 60px; bottom: auto; }
  .appshow-play svg { width: 15px; height: 15px; }
  .appshow-zoom svg { width: 19px; height: 19px; }
  /* Die Punkte bleiben optisch klein; nur die unsichtbare Flaeche waechst.
     Der Abstand muss mitwachsen, sonst ueberlappen sich die Flaechen und man
     trifft den Nachbarn. */
  .appshow-dots { gap: 22px; }
  .appshow-dot::after { width: 30px; height: 34px; }
  /* Verweise, die fuer sich stehen: mindestens 40 Pixel hoch. Im Fliesstext
     bleiben sie, wie sie sind — dort waere eine grosse Flaeche stoerend. */
  .foot a { padding: 11px 0; }
  .back { min-height: 40px; }
  /* Anschrift, E-Mail und Internetadresse in der Kontaktkachel stehen je in
     einer eigenen Zeile — also eigenstaendige Verweise, keine im Fliesstext. */
  .legal-tile b a { display: inline-block; padding: 7px 0; }
}

/* --- Lightbox (Bild vergrößern) -------------------------------------------- */
.lightbox { position: fixed; inset: 0; z-index: 200; display: grid; grid-template-rows: 1fr auto;
  place-items: center; gap: 10px; padding: clamp(16px, 4vw, 48px);
  background: rgba(5,10,17,.92); backdrop-filter: blur(6px); }
.lightbox[hidden] { display: none; }
.lightbox-fig { margin: 0; display: grid; place-items: center; gap: 14px; max-width: 100%; max-height: 100%; }
.lightbox-fig img { max-width: min(1400px, 94vw); max-height: 82vh; width: auto; height: auto;
  border-radius: var(--r-sm); box-shadow: 0 24px 60px rgba(0,0,0,.5); }
.lightbox-fig figcaption { color: #E6EBF3; font-size: 14px; line-height: 1.5; text-align: center;
  max-width: 76ch; }
/* Auf dem Telefon nuetzt die Grossansicht wenig, wenn sie das Bild nur auf
   Fensterbreite aufzieht: Ein Bildschirmfoto einer Anwendung ist bei 390 Pixel
   nicht mehr zu lesen. Deshalb steht es dort in fester Breite und laesst sich
   verschieben — die Bildunterschrift bleibt dabei stehen. */
@media (max-width: 720px) {
  .lightbox-fig { display: block; overflow: auto; overscroll-behavior: contain;
    padding: 6px; -webkit-overflow-scrolling: touch; overflow-anchor: none;
    place-items: start; }
  .lightbox-fig img { max-width: none; max-height: none; width: 980px; height: auto; }
  .lightbox-fig figcaption { position: sticky; left: 0; width: calc(100vw - 28px);
    margin-top: 12px; }
}

.lightbox-close { position: absolute; top: 16px; right: 18px; width: 44px; height: 44px;
  display: grid; place-items: center; border: 0; border-radius: 50%; background: rgba(255,255,255,.12);
  color: #fff; font-size: 26px; line-height: 1; cursor: pointer; }
.lightbox-close:hover { background: var(--green); color: var(--on-green); }
.lightbox-nav { position: absolute; top: 50%; transform: translateY(-50%); width: 48px; height: 48px;
  display: grid; place-items: center; border: 0; border-radius: 50%; background: rgba(255,255,255,.12);
  color: #fff; cursor: pointer; }
.lightbox-nav svg { width: 24px; height: 24px; }
.lightbox-nav:hover { background: var(--green); color: var(--on-green); }
.lightbox-prev { left: clamp(10px, 3vw, 34px); } .lightbox-next { right: clamp(10px, 3vw, 34px); }
.lightbox-count { color: #99A6B7; font-size: 12.5px; font-variant-numeric: tabular-nums; }
@media (max-width: 640px) { .lightbox-nav { width: 40px; height: 40px; } }

/* --- Bausteine-Rad (langsam rotierender Ring) ------------------------------ */
/* Der Ringradius folgt aus Rondellgroesse und Chipbreite, nicht aus eigenen
   Grenzwerten: r = (G - Chip) / 2. Damit steht der Chip in Seitenlage immer
   genau auf der Kante und nie darueber — das war die Ursache des
   Scrollbalkens, der je nach Ringstellung kam und ging.
   Die zweite Bedingung ist die Bogenlaenge: 2*pi*r/n >= Chipbreite, sonst
   beruehren sich die Chips. Aufgeloest ergibt das Chip <= pi*G/(n + pi) — der
   Faktor haengt also an der Chipzahl und kommt als --chipf aus dem Generator,
   weil das Stylesheet sie nicht kennen kann. 132px bleibt die Obergrenze,
   darunter faellt die Chipbreite mit dem Rondell. */
.brad { position: relative; width: var(--w); aspect-ratio: 1; margin: 6px auto 0;
  /* Eine Runde in drei Minuten. Bei 60s las sich die Drehung als Bewegung, der
     man zusieht; jetzt merkt man sie erst, wenn man ein zweites Mal hinschaut —
     und die Beschriftungen lassen sich in Ruhe lesen. */
  --dur: 180s; --w: min(480px, 55vw - 60px);
  --chip: min(132px, calc(var(--w) * var(--chipf)));
  --r: calc((var(--w) - var(--chip)) / 2); }
.brad-ring { position: absolute; inset: 0; animation: brad-spin var(--dur) linear infinite; }
.brad-slot { position: absolute; top: 50%; left: 50%; width: 0; height: 0;
  transform: rotate(var(--a)) translateY(calc(-1 * var(--r))); }
.brad-anti { animation: brad-spin var(--dur) linear infinite reverse; }
.brad-fix { transform: rotate(calc(-1 * var(--a))); }
/* Das Rondell muss sich gegen die Navy-Fläche behaupten: die Chips liegen eine
   Stufe über --card, damit die farbigen Symbole und die kleine Fettschrift nicht
   in der Fläche versinken. */
.brad-chip { position: absolute; left: 0; top: 0; transform: translate(-50%, -50%);
  width: max-content; max-width: var(--chip); display: flex; flex-direction: column;
  align-items: center; gap: 7px; padding: 12px 13px; background: var(--card-2);
  border: 1px solid var(--line-2); border-radius: 16px; box-shadow: var(--sh-1);
  text-align: center; }
/* Die einzige Stelle im Projekt mit Silbentrennung, und sie ist ausdruecklich
   freigeschaltet (siehe HYPHEN_ERLAUBT in pruefen.py). Im Fliesstext bleibt sie
   aus: dort ist genug Breite da, und Trennung stoert den Lesefluss. In einem
   Chip von 85 bis 132px ist sie das Gegenteil — ohne sie bricht „Positionierung“
   mitten im Wort oder schiebt den Chip auf.
   Deutsch getrennt wird nur, weil <html lang="de"> gesetzt ist; ohne das kennt
   der Browser die Trennstellen nicht. break-word bleibt als Notnagel fuer
   Woerter, fuer die auch die Trennung keine Stelle findet. */
.brad-chip b { font-size: 11.5px; font-weight: 700; line-height: 1.2; color: #F2F5FA;
  letter-spacing: -.01em; -webkit-hyphens: auto; hyphens: auto;
  overflow-wrap: break-word; }
.brad-ico { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 11px;
  background: var(--green-wash); color: var(--green-deep); }
.brad-ico svg { width: 19px; height: 19px; }
/* Der Kern trägt das Produktlogo. Logos brauchen eine neutrale, helle Unterlage
   — auf Navy verschwände die farbige Marke. Deshalb bleibt der Kern hell und
   wird zum Blickfang in der Mitte.

   Liegend statt rund, damit die Wortmarke hineinpasst (Seitenverhältnis 5,4:1).
   Der Kern steht im Markup nach dem Ring und wird deshalb darüber gezeichnet:
   die Chips wandern hinter dem Badge durch, statt es zu verdecken. Er darf
   deshalb breiter sein, als der freie Raum zwischen den Chips hergibt. */
.brad-core { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: clamp(196px, 56%, 276px); display: grid; place-items: center; align-content: center;
  text-align: center; gap: 4px; border-radius: 22px; background: #FFFFFF; border: 1px solid #C3CEDD;
  box-shadow: 0 6px 18px rgba(0,0,0,.38), 0 22px 50px rgba(0,0,0,.45); padding: 18px 20px;
  min-height: 104px; }
/* Traegt der Kern ein Logo, wird aus dem Badge eine weiche Scheibe: satt weiss
   in der Mitte, zum Rand hin ausgeblendet. Ohne harte Kante taucht der Ring aus
   dem Verlauf auf, statt an ihr abgeschnitten zu werden — deshalb darf die
   Scheibe groesser sein als der Ring.
   Die Groesse folgt aus zwei Bedingungen: das Logo (5,4:1, breit und flach)
   muss ganz im deckenden Bereich liegen, und der deckende Bereich darf die
   Chips nicht erreichen — sonst verschluckt die Scheibe deren Beschriftung.
   Die Chips beginnen 122px von der Mitte entfernt (Ringradius 188 minus halbe
   Chipbreite 66). Bei 320px Scheibe endet das Deckende bei 115px und das Logo
   reicht bis 104px: beides passt. */
/* Weisses Plaettchen statt weicher Scheibe (User 2026-09-11). Der Verlauf liess
   das Logo im Dunkel schweben und seine Unterkante ausfransen; eine klare Flaeche
   mit abgerundeten Ecken traegt es wie auf Papier und wiederholt die Form, die
   das Logo auf der Startseite ohnehin schon hat (.prod-logo).
   Das Plaettchen folgt der Form des Logos: flach und breit, nicht quadratisch. */
.brad-core--logo {
  /* 46 % statt der 60 %, die die weiche Scheibe hatte: Die lief nach aussen aus
     und durfte die Chipbahn beruehren. Eine harte Kante darf das nicht, sie
     schnitte die Chips an. */
  width: clamp(168px, 46%, 214px); aspect-ratio: auto; min-height: 0;
  padding: 12px 16px; border: 0; border-radius: 16px;
  background: #FFFFFF; box-shadow: 0 6px 22px rgba(0,0,0,.28);
}
/* Feste Hoehe, Breite relativ: die Marke ist ein SVG mit width/height="100%"
   und hat keine vom Browser ableitbare Eigengroesse. */
.brad-core--logo img { width: 100%; height: 36px; object-fit: contain; }
/* Freigestellte PNG-Marke (TerraOptima) auf dem dunklen Rad: kein Plaettchen,
   kein Schatten. Breiter als das Plaettchen (232 statt 214 px), aber unter der
   Chipbahn: Chips beginnen 122 px von der Mitte, halbe Breite also <= 116 px. */
.brad-core--marke { width: clamp(176px, 50%, 232px); padding: 0; background: none;
  border-radius: 0; box-shadow: none; }
.brad-core--marke img { height: auto; }
/* Ohne Logo traegt der Kern nur den Produktnamen. Er bekommt dieselbe weiche
   Scheibe wie der Logokern: derselbe Verlauf, dieselbe Groesse. Vorher stand
   hier eine kleinere Scheibe mit gestricheltem Rand — die las sich wie ein
   Platzhalter, der noch gefuellt werden muss, und die harte Kante schnitt den
   durchwandernden Ring ab, statt ihn aus dem Verlauf auftauchen zu lassen.
   Die Schrift bleibt im deckenden Bereich (bis 55 % des Radius), deshalb die
   Begrenzung auf 52 % der Breite. Was dort nicht in eine Zeile passt, wird
   umbrochen und, wenn noetig, getrennt — wie in den Chips. */
.brad-core--ph {
  width: clamp(216px, 60%, 288px); aspect-ratio: 1; min-height: 0;
  padding: 0; border: 0; border-radius: 50%; box-shadow: none;
  background: radial-gradient(circle closest-side,
    #FFFFFF 0%, #FFFFFF 55%, rgba(255,255,255,.92) 72%,
    rgba(255,255,255,.45) 85%, rgba(255,255,255,0) 100%);
}
.brad-ph-mark { max-width: 52%; font-size: clamp(14px, 3.2vw, 17px); font-weight: 700;
  line-height: 1.2; letter-spacing: -.02em; color: #101A26;
  -webkit-hyphens: auto; hyphens: auto; overflow-wrap: break-word; }
@keyframes brad-spin { to { transform: rotate(360deg); } }

/* Auf dem Handy behalten die Chips ihre Namen. Vorher trugen sie nur ihr Symbol
   und die Namen standen als Liste darunter — der Ring wirkte dadurch leer und
   die Liste kostete noch einmal so viel Hoehe wie das Rondell selbst.
   Moeglich wird es durch zwei Griffe: das Rondell tritt aus dem Spaltenpolster
   heraus und nimmt die volle Gerätebreite, und Schrift wie Symbole schrumpfen.
   Die Geometrie traegt das, weil Radius und Chipbreite an der Groesse haengen:
   bei 348px sind das r = 136 und Chip = 71, macht 343 von 348 — und 95px
   Bogenlaenge gegen 71px Bedarf. */
@media (max-width: 700px) {
  .brad { --w: min(400px, 100vw - 20px); margin: 4px auto 0; }
  .brad-chip { padding: 7px 6px; border-radius: 12px; gap: 4px; }
  .brad-chip b { font-size: 8.5px; line-height: 1.15; }
  .brad-ico { width: 26px; height: 26px; border-radius: 9px; }
  .brad-ico svg { width: 15px; height: 15px; }
  /* Der Kern schrumpft mit: sein deckender Bereich darf die Chips nicht
     erreichen. Deren Innenkante liegt bei r minus halber Chiphoehe. */
  .brad-core--logo, .brad-core--ph { width: clamp(118px, 40%, 150px); }
  .brad-core--logo img { width: 78%; height: 26px; }
  .brad-ph-mark { font-size: 11.5px; }
}

/* Barrierefreiheit (WCAG 2.2.2): bei Tastaturfokus hält die Rotation an. */
.brad:focus-within .brad-ring, .brad:focus-within .brad-anti { animation-play-state: paused; }
.brad:focus-visible { outline: 3px solid var(--green-ink); outline-offset: 6px; border-radius: 50%; }
@media (prefers-reduced-motion: reduce) { .brad-ring, .brad-anti { animation: none; } }
.brad-legend { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px 16px; }
.brad-legend li { display: inline-flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--ink-2); }
.brad-legend i { width: 10px; height: 10px; border-radius: 3px; flex: none; }

/* --- Agentenbaum (Schema des Systems) -------------------------------------- */
/* Das SVG skaliert ueber die viewBox mit. Auf schmalen Schirmen darf es
   waagerecht rollen, statt die Beschriftungen unlesbar zu stauchen — der
   Rollbereich bleibt dabei im Kasten, die Seite selbst scrollt nicht. */
/* Zwei Fassungen, eine sichtbar — dieselbe Regel wie beim Wirbelbild. Die
   weite behaelt ihre Mindestbreite, damit die Schrift am Rechner nicht unter
   die Lesegroesse rutscht; unterhalb von 760px uebernimmt die schmale, die
   ohne Mindestbreite auskommt und deshalb nirgends abgeschnitten wird. */
.agentenbaum { margin: 0; }
.agentenbaum--weit { overflow-x: auto; }
.agentenbaum svg { width: 100%; height: auto; }
.agentenbaum--weit svg { min-width: 640px; }
.agentenbaum--schmal { display: none; }
/* In einer halben Spalte hilft die Fensterbreite nicht weiter: Dort ist immer
   die gedrungene Fassung richtig, auch auf einem breiten Bildschirm. Die
   Umschaltung haengt sonst am Fenster und nicht am verfuegbaren Platz. */
.spalte-eng .agentenbaum--weit { display: none; }
.spalte-eng .agentenbaum--schmal { display: block; }
@media (max-width: 760px) {
  .agentenbaum--weit { display: none; }
  .agentenbaum--schmal { display: block; }
}

/* --- Weltenkette ----------------------------------------------------------- */
/* Dieselbe Umschaltung wie beim Agentenbaum: sieben Stationen nebeneinander
   brauchen Breite, sonst steht in jeder Kachel keine lesbare Beschriftung mehr.
   Unterhalb der Mindestbreite uebernimmt die Fassung untereinander. */
.welten { margin: 0; }
.welten--weit { overflow-x: auto; }
.welten svg { width: 100%; height: auto; }
.welten--weit svg { min-width: 860px; }
.welten--schmal { display: none; }
.welten--schmal svg { max-width: 360px; margin-inline: auto; display: block; }
.spalte-eng .welten--weit { display: none; }
.spalte-eng .welten--schmal { display: block; }
@media (max-width: 900px) {
  .welten--weit { display: none; }
  .welten--schmal { display: block; }
}

/* --- Zahlen ---------------------------------------------------------------- */
.zahl { text-align: center; padding: 26px 20px; }
.zahl b { display: block; font-size: clamp(2rem, 4vw, 2.7rem); line-height: 1;
  font-weight: 700; letter-spacing: -.03em; color: var(--green-ink); }
.zahl span { display: block; margin-top: 10px; font-size: 13.5px; line-height: 1.45; color: var(--ink-2); }

/* --- Prozesskette (statt Fließtext) --------------------------------------- */
.chain { display: flex; flex-wrap: wrap; align-items: stretch; gap: 10px; margin-top: 24px; }
.chain-step { flex: 1 1 156px; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 16px; box-shadow: var(--sh-1); }
.chain-step .ico-tile { width: 38px; height: 38px; margin: 0 0 12px; border-radius: 11px; }
.chain-step .ico-tile svg { width: 19px; height: 19px; }
.chain-step b { display: block; font-size: 14.5px; }
/* Gleicher Fall wie bei .contact-line: die Kachel ist ein <span> und würde von
   dieser Regel plattgemacht. */
.chain-step span:not(.ico-tile) { display: block; margin-top: 5px; font-size: 13px; color: var(--muted); line-height: 1.5; }
.chain-arrow { align-self: center; flex: 0 0 auto; color: var(--muted); }
.chain-arrow svg { width: 18px; height: 18px; }
.chain-back { display: flex; align-items: center; gap: 10px; margin-top: 10px; padding: 10px 16px;
  background: var(--card-2); border-radius: var(--pill); font-size: 13px; color: var(--ink-2); font-weight: 600; }
.chain-back svg { width: 16px; height: 16px; flex: 0 0 auto; }
@media (max-width: 760px) {
  .chain-step { flex: 1 1 100%; }
  .chain-arrow { align-self: center; transform: rotate(90deg); }
}

/* --- Produkthinweis innerhalb einer Leistung ------------------------------- */
.prodlink { display: grid; grid-template-columns: 52px minmax(0,1fr) auto; gap: 18px;
  align-items: center; margin-top: 24px; }
.prodlink .prod-mark { width: 52px; height: 52px; border-radius: 14px; font-size: 16px; }
.prodlink b { display: block; font-size: 16.5px; }
.prodlink p { margin: 4px 0 0; font-size: 14px; color: var(--muted); line-height: 1.55; }
@media (max-width: 760px) { .prodlink { grid-template-columns: minmax(0,1fr); } }
/* --- Wirbelbild: Technologie-Ebene und Produktebene ----------------------- */
/* Jeder Wirbel ist eine Schaltflaeche. Ein Kreis in einem Bild sieht nach
   nichts aus, deshalb zwei Signale beim Ueberfahren: der Saum nimmt Gruen an,
   und unter dem Namen erscheint eine Lupe. Die verlaessliche Tuer bleibt der
   Knopf darunter. */
.wirbel-block { display: flex; flex-direction: column; align-items: center; gap: 16px; }
/* Der Hinweis steht unter dem Bild und sagt geradeheraus, was möglich ist.
   Eine Gestaltung, die man erst erraten muss, ist keine. */
.wirbel-tipp { display: inline-flex; align-items: center; gap: 10px; margin: 0;
  padding: 9px 16px; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--pill); font-size: 14px; color: var(--ink-2); text-align: left; }
.wirbel-tipp svg { width: 17px; height: 17px; flex: 0 0 auto; color: var(--green-deep); }
/* 700 statt 780: die Zeichnung ist von 620 auf 560 Einheiten geschrumpft, weil
   die Beschriftungen jetzt umbrechen und die Kreise dadurch kleiner sein
   duerfen. Ohne die kleinere Buehne waere die Schrift im selben Zug groesser
   geworden — gewollt war das Gegenteil: kleinere Kreise, mehr Luft dazwischen. */
.wirbel-buehne { width: 100%; max-width: 700px; margin: 0; }
.wirbel-buehne svg { width: 100%; height: auto; display: block; }
.wirbel-buehne--weit { display: block; }
.wirbel-buehne--schmal { display: none; }
/* Auf schmalen Geraeten uebernimmt die gedrungene Fassung und tritt dabei aus
   dem Spaltenpolster heraus. Beides zusammen bringt die Beschriftung von acht
   auf elf Pixel: die Zeichnung ist kleiner geraten (400 statt 620 Einheiten),
   die Schrift darin aber kaum. */
@media (max-width: 760px) {
  .wirbel-buehne--weit { display: none; }
  .wirbel-buehne--schmal { display: block; width: 100vw;
    margin-inline: calc(50% - 50vw); max-width: none; }
}

/* Drei Bewegungen. transform-box: view-box, damit sich die Mittelpunkte auf
   das Koordinatensystem der Zeichnung beziehen und nicht auf die Objektbox. */
.umlauf, .halt, .dreh { transform-box: view-box; transform-origin: var(--mitte);
  animation: wirbeldreh var(--dauer) linear infinite; }
.dreh { animation-direction: var(--richtung); }
/* Gleiche Dauer, Gegenrichtung: die Position wandert, die Schrift bleibt aufrecht. */
.halt { animation-direction: reverse; }
@keyframes wirbeldreh { to { transform: rotate(360deg); } }

/* Bewusst keine Bremse beim Ueberfahren: die Kreise sind gross genug, um sie
   auch in Bewegung zu treffen, und ein Wirbel, der unter dem Zeiger anhaelt,
   verliert genau das, wofuer er da ist. */
.wirbel { cursor: pointer; }
.wirbel:focus { outline: none; }
.saum { transition: stroke .2s ease, stroke-width .2s ease; }
.wirbel:hover .saum, .wirbel:focus-visible .saum { stroke: var(--green); stroke-width: 2.8; }
/* Die Lupe war bis zum Überfahren unsichtbar. Auf dem Telefon gibt es kein
   Überfahren — dort war also nie zu erkennen, dass die Kreise Schaltflächen
   sind, und auch am Rechner musste man es erst zufällig herausfinden. Sie steht
   deshalb dauerhaft, nur gedämpft, und wird beim Überfahren voll und größer.
   Das ist die verlässlichere Lösung als ein eingeblendeter Mauszeiger: Ein
   Zeiger, den es auf dem Gerät gar nicht gibt, erklärt nichts. */
.wirbel-lupe { opacity: .42; transform-box: fill-box; transform-origin: center;
  transition: opacity .25s ease, transform .25s ease; }
.wirbel:hover .wirbel-lupe, .wirbel:focus-visible .wirbel-lupe { opacity: 1; transform: scale(1.14); }

/* Das Detail als modaler Dialog. Die Hoehe deckelt 86vh, der Leib scrollt —
   sonst waechst der Dialog mit den zwoelf Rollen aus dem Bildschirm heraus. */
.wdlg { width: min(940px, calc(100vw - 28px)); max-height: 86vh; padding: 0;
  border: 1px solid var(--line); border-radius: 18px; background: var(--card);
  color: var(--ink); overflow: hidden; }
.wdlg::backdrop { background: rgba(6, 11, 20, .74); }
.wdlg-kopf { display: flex; align-items: center; gap: 16px;
  padding: 18px 20px 14px; border-bottom: 1px solid var(--line); }
.wdlg-kopf h3 { margin: 0; }
.wdlg-zu { flex: none; margin-left: auto; width: 38px; height: 38px; display: grid;
  place-items: center; border: 1px solid var(--line); border-radius: 50%;
  background: transparent; color: var(--ink-2); cursor: pointer;
  transition: background .2s, color .2s, border-color .2s; }
.wdlg-zu svg { width: 19px; height: 19px; }
.wdlg-zu:hover { background: var(--green); border-color: var(--green); color: var(--on-green); }
/* overflow-x ausdruecklich setzen: sobald eine Achse nicht `visible` ist, hebt
   CSS die andere von `visible` auf `auto` an. Der Koerper haette sonst auch
   waagerecht einen Scrollbereich — und in den schwingt das drehende Rondell
   hinein, sobald ein Chip die Seitenlage erreicht. Der Balken taucht dann erst
   nach ein paar Sekunden auf, was die Ursache gut versteckt. */
/* scrollbar-gutter haelt den Platz frei: taucht doch einmal ein Balken auf,
   ruckt der Inhalt nicht seitlich weg. */
/* Licht statt Flaeche: Der Dialogkoerper ist gross und war eine einzige, ebene
   Farbe — dagegen sah selbst ein drehendes Rondell aufgeklebt aus. Zwei sehr
   weiche Lichter geben ihm eine Tiefe, ohne dass ein Verlauf als solcher
   auffaellt: eines von oben in der Mitte, wo der Kern steht, und ein zweites,
   gruen getoentes, tief unten. Beide bleiben unter fuenf Prozent Deckung; alles
   darueber wird zum sichtbaren Streifen, sobald der Koerper scrollt.
   Die Voreinstellung `background-attachment: scroll` ist hier die richtige: Sie
   haengt das Licht an den Kasten, nicht an den Inhalt — beim Scrollen bleibt es
   also stehen, statt mitzuwandern und sich als Bild zu verraten. */
.wdlg-leib { padding: 18px 20px 22px; overflow-y: auto; overflow-x: hidden;
  scrollbar-gutter: stable; max-height: calc(86vh - 72px);
  background:
    radial-gradient(60% 42% at 50% 8%, rgba(255,255,255,.045), rgba(255,255,255,0) 70%),
    radial-gradient(52% 40% at 50% 104%, rgba(127,203,40,.05), rgba(127,203,40,0) 72%); }
.wdlg-leib > .lead { margin-top: 0; }
.wdlg-leib .agentenbaum { margin: 0; }
/* Das Rondell im Dialog darf groesser sein als in der Seitenspalte: hier hat es
   die ganze Breite fuer sich. */
/* Die Rondellgroesse folgt hier auch der Fensterhoehe, nicht nur der Breite:
   sonst steht der Dialogkoerper genau auf seiner Inhaltshoehe, und die wenigen
   Pixel, um die ein zweizeiliger Chip in der Hoch- oder Tieflage weiter
   hinausragt als ein einzeiliger, lassen den Scrollbalken bei jeder Ringdrehung
   erscheinen und wieder verschwinden.

   Der Ringradius haengt an der Rondellgroesse statt an eigenen Grenzwerten.
   Damit gilt die Bedingung Radius + halbe Chiphoehe < halbe Rondellgroesse bei
   jeder Fenstergroesse von selbst: 0,33 · W + 48px < 0,5 · W ab W = 282px.
   Darunter greift die schmale Ansicht, in der die Chips nur ihr Symbol tragen
   und entsprechend flach sind. */
/* Die Untergrenze haelt neun Chips auseinander: unter 500px reicht die
     Bogenlaenge nicht mehr. Auf niedrigen Fenstern scrollt dann lieber der
     Dialogkoerper — das ist stabil, weil kein Chip aus dem Rondell ragt. */
.wdlg-leib .brad { --w: min(560px, 100vw - 83px, max(500px, 62vh)); }
.wdlg-leib .brad-legend { justify-content: center; margin-top: 18px; }
/* Auf dem Telefon randlos: der Dialog gibt seinen Rahmen auf, damit das
   Rondell die volle Geraetebreite bekommt. Auf 348px statt 288px passt der
   Unterschied zwischen beschrifteten und nackten Chips. */
@media (max-width: 560px) {
  .wdlg { width: 100vw; max-width: none; max-height: 92vh; border-radius: 0; border: 0; }
  .wdlg-kopf { padding: 14px 12px 12px; }
  .wdlg-kopf h3 { font-size: 17px; }
  .wdlg-leib { padding: 10px 8px 16px; max-height: calc(92vh - 66px); }
  .wdlg-leib .brad { --w: min(400px, 100vw - 31px, 56vh); }
}

/* Nur fuer Vorlesegeraete: die Langbeschreibung des Wirbelbildes. Sie liegt
   nicht im aria-label des SVG, weil ein role="img" dessen Schaltflaechen
   verdecken wuerde — und die sind hier der Sinn der Sache. */
.nur-vorlesen { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* Bewegung ist fuer manche Menschen keine Zierde, sondern ein Problem. */
@media (prefers-reduced-motion: reduce) {
  .umlauf, .halt, .dreh { animation: none; }
  .saum, .wirbel-lupe, .wdlg-zu { transition: none; }
}

/* Verweise auf die Marken-Domains der Produkte (Kachel und Produktseite) */
.prod-aktion { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 20px; margin-top: 24px; }
.prod-domain { font-size: 12px; line-height: 1.4; color: var(--muted); text-decoration: underline;
  text-underline-offset: 3px; text-decoration-color: var(--line); }
.prod-domain:hover, .prod-domain:focus-visible { color: var(--green-ink); text-decoration-color: currentColor; }
.prod-eigen { margin: -6px 0 14px; font-size: 13.5px; color: var(--muted); }
.prod-eigen a { color: var(--green-ink); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
/* Punkt und Kanal brechen gemeinsam um, sonst bleibt der Punkt allein am Zeilenende. */
.prod-eigen .prod-kanal { white-space: nowrap; }
.prod-eigen .trenner { margin: 0 8px; }
.prod-eigen .li-link { gap: 5px; vertical-align: -2px; }

/* LinkedIn-Verweis mit Zeichen (Fußzeilen, Gründerprofil) */
.li-link { display: inline-flex; align-items: center; gap: 8px; }
.li-ico { flex: none; width: 17px; height: 17px; }
.foot a.li-link { display: flex; }
.li-link--text { color: var(--green-ink); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
