/* Blog pagination (paginate_links list output). */
.blog-pagination { margin-top: 42px; }
.blog-pagination .page-numbers {
	display: flex;
	gap: 8px;
	justify-content: center;
	list-style: none;
	margin: 0;
	padding: 0;
}
.blog-pagination .page-numbers li a,
.blog-pagination .page-numbers li span {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 38px;
	height: 38px;
	padding: 0 10px;
	border-radius: 10px;
	border: 1px solid rgba(10, 25, 80, 0.14);
	color: inherit;
	text-decoration: none;
	font-weight: 600;
	font-size: 14px;
}
.blog-pagination .page-numbers li span.current {
	background: var(--dunkelblau, #0a1950);
	border-color: var(--dunkelblau, #0a1950);
	color: #fff;
}

/* Filled media state: hide the placeholder chrome, let the real media fill the frame. */
.media-ph.is-filled { background: none; border: 0; }
.media-ph.is-filled::before,
.media-ph.is-filled::after { display: none !important; content: none !important; }
.media-ph.is-filled > img,
.media-ph.is-filled > video {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* ---- Footer: Legal Entity nach Besucherland ----
   Alle Varianten liegen im Markup, nur eine ist sichtbar (hidden-Attribut).
   [hidden] muss hier explizit gesetzt werden, weil address per display:flex
   die Browser-Voreinstellung sonst überschreibt. */
.footer-entity { margin-top: 26px; }
.footer-entity [hidden] { display: none; }
.fe-card { display: flex; flex-direction: column; gap: 3px; font-style: normal;
  font-size: 13px; line-height: 1.6; color: rgba(255,255,255,0.50); }
.fe-name { font-weight: 700; color: rgba(255,255,255,0.75); }
.fe-contact { display: flex; flex-wrap: wrap; gap: 4px 18px; margin-top: 2px; }
.fe-contact a { color: rgba(255,255,255,0.50); transition: color 0.2s ease; }
.fe-contact a:hover { color: var(--gelb); }

/* Eyebrow als Block-Absatz.
   Im Prototyp ist .eyebrow ein <span>. Als core/paragraph rendert es ein <p>
   und verliert font-size und color an Regeln wie `.two-col p` — eine Klasse
   plus Element (0,1,1) schlägt die Klasse allein (0,1,0). Betroffen war das
   Eyebrow der Intro-Sektion auf allen migrierten Seiten (Startseite,
   BeyonityHELLO, Navigator, Living Configurator, Realtime Tour): es rendert
   in Textgrösse und Grau statt 11px in Markenblau.
   Diese Datei wird nach styles.css geladen, die Deklarationen gewinnen daher
   den Spezifitäts-Gleichstand gegen `.two-col p`. */
p.eyebrow { font-size: 11px; line-height: inherit; color: var(--blau); }
p.eyebrow.eyebrow-light { color: var(--gelb); }

/* Wertezeilen auf /ueber-uns/: die Nummer ist im Prototyp ein <div>. Als
   Block-Absatz greift zwar `.value-row .vnum` (zwei Klassen schlagen
   Klasse+Element), aber `.value-row p` setzt zusätzlich line-height 1.7 —
   im Prototyp erbt die Nummer 1.6 vom body. Nur das wird zurückgeholt. */
.value-row p.vnum { line-height: inherit; }

/* Staffelung der Reveal-Animation als Klasse.
   styles.css staffelt über `.reveal[data-delay="1"]`. Core-Blöcke (Gruppe,
   Absatz) können kein data-Attribut tragen, nur Klassen — deshalb dieselben
   Verzögerungen zusätzlich als `.delay-1|2|3`. Werte identisch zu styles.css. */
.reveal.delay-1 { transition-delay: 0.08s; }
.reveal.delay-2 { transition-delay: 0.16s; }
.reveal.delay-3 { transition-delay: 0.24s; }

/* Team-Avatar, Variante „Ganzes Bild“ (.is-plain).
   Die Mitarbeiterfotos von beyonity.com sind freigestellt und bringen ihre
   Form selbst mit: hellblaue Scheibe, bei den acht Vertriebspersonen zusätzlich
   der eingebackene „Book a Demo“-Ring und das gelbe Kalender-Icon an der Ecke.
   Der runde Rahmen des Prototyps (84px, overflow:hidden, scale 0.94) würde
   genau diese Ecken abschneiden — deshalb hier quadratisch, transparent,
   unbeschnitten und in der Grösse der Produktivseite (dort 215px). */
.team-avatar.is-plain {
  width: 100%;
  max-width: 200px;
  height: auto;
  aspect-ratio: 1 / 1;
  border-radius: 0;
  background: none;
  box-shadow: none;
  overflow: visible;
  margin: 0 auto 18px;
}
.team-avatar.is-plain img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Unten ausgerichtet, nicht zentriert. 42 der 43 Fotos sind quadratisch und
     füllen das Feld — für die ändert das nichts. Eines ist es nicht
     (Mattia Rüfenacht, 768×714): bei `contain` wird es auf 200×186 gerechnet
     und zentriert, also sass es 7px höher als seine Nachbarn und die Unterkante
     der Reihe war krumm. Unten ausgerichtet stehen alle Porträts auf derselben
     Linie. `cover` wäre hier falsch: die acht Vertriebsfotos haben den
     Kalender-Ring in der Ecke eingebacken, den würde ein Beschnitt abschneiden.
     Die eigentliche Lösung bleibt ein quadratischer Export der einen Datei. */
  object-position: bottom;
  transform: none;
}

/* Core-Tabellenblock in der Optik von `.data-table`.
   Zwei Dinge stehen dem im Weg:
   1. Der Block legt seine Klassen auf das umgebende <figure>, nicht auf die
      <table> — `.data-table { width:100%; border-collapse:collapse }` aus
      styles.css greift damit am falschen Element.
   2. Das Core-Stylesheet bringt eigene Zellrahmen mit:
      `.wp-block-table td, .wp-block-table th { border: 1px solid; padding: .5em }`.
      Gleiche Spezifität wie unsere Regel, aber sie setzt alle vier Seiten —
      unsere nur border-bottom. Ergebnis war ein volles Rahmengitter.
   Beides hier mit einer Klasse mehr Spezifität korrigiert: volle Breite,
   nur waagrechte Linien, Werte identisch zu `.data-table` in styles.css. */
.wp-block-table.data-table { width: 100%; }
.wp-block-table.data-table table { width: 100%; border-collapse: collapse; }
.wp-block-table.data-table td,
.wp-block-table.data-table th {
  border: 0;
  border-bottom: 1px solid var(--linie);
  padding: 12px 14px;
  text-align: left;
  vertical-align: top;
}
/* Der Prototyp setzt die erste Spalte als <th>; der Core-Block kennt nur
   <td> — deshalb die th-Optik über die Spaltenposition. */
.wp-block-table.data-table td:first-child {
  font-weight: 700;
  color: var(--dunkelblau);
  opacity: 1;
  width: 32%;
}

/* Der Zeitstempel-Pill im Navigator-SDK-Ausblick ist im Prototyp ein <span>,
   als Block-Absatz wird er ein <p> — und dann greift `.wsi-next p`
   (Klasse+Element, 0-1-1) stärker als `.wsi-when` (0-1-0) und überschreibt
   Schriftgrösse und Farbe. Hier zurückgeholt, Werte identisch zu styles.css.
   max-width entfällt, weil der Pill nicht umbrechen soll. */
.wsi-next p.wsi-when {
  font-size: 12px;
  color: var(--dunkelblau);
  max-width: none;
}

/* Der Hinweiskasten der Datenschutzerklärung ist im Prototyp ein <div>, als
   Block-Absatz wird er ein <p> — dann greift `.prose p` (0-1-1) stärker als
   `.legal-note` (0-1-0) und überschreibt Abstand und Deckkraft. Nur das
   zurückgeholt, Werte identisch zu styles.css. */
.prose p.legal-note { opacity: 1; margin-bottom: 36px; }

/* Projekte-Übersicht — Übersetzung der Inline-Styles und ein Guard.
   Die Seite ist ein Archiv-Template, hat also keinen Slug, über den eine
   assets/<slug>.css geladen würde; deshalb stehen die vier Regeln hier. */

/* Der Case-Tag ist im Prototyp ein <span>, als Block-Absatz wird er ein <p> —
   und `.case-feature-visual p` (0-1-1) überschreibt Schriftgrösse und Farbe
   der Klasse `.case-tag` (0-1-0). Werte identisch zu styles.css. */
.case-feature-visual p.case-tag { font-size: 10px; color: var(--gelb); }

/* Prototyp: <p style="margin-top:18px;color:rgba(255,255,255,.85);font-weight:600"> */
.case-feature-visual p.case-feature-quote {
  margin-top: 18px;
  color: rgba(255, 255, 255, 0.85);
  font-weight: 600;
}

/* Prototyp: <a class="btn-outline-white" style="margin-top:26px"> */
.case-feature-visual .case-feature-cta { margin-top: 26px; }

/* Prototyp: <p class="reveal" style="margin-top:28px;font-size:13px;color:var(--text-muted)"> */
.case-grid-note { margin-top: 28px; font-size: 13px; color: var(--text-muted); }

/* Projekt-Detailseite — Übersetzung der Inline-Styles und ein Guard.
   Die Seite ist eine Projekt-Detailseite (CPT), hat also keinen Seiten-Slug,
   über den eine assets/<slug>.css geladen würde. */

/* Prototyp: <div class="proj-results" style="margin-top:44px"> */
.proj-results { margin-top: 44px; }

/* Prototyp: erstes <div class="proj-chapter" style="margin-top:56px">.
   Zwischen zwei Kapiteln bleiben die 88px aus styles.css (0-2-0 gewinnt). */
.proj-chapter { margin-top: 56px; }

/* Prototyp: <div class="proj-gallery" style="margin-top:40px"> */
.proj-gallery { margin-top: 40px; }

/* Die Kapitel-Marke („Ausgangslage") ist im Prototyp ein <span>. Als
   Block-Absatz wird sie ein <p>, und `.proj-chapter p` (0-1-1) überschreibt
   Schriftgrösse und Farbe von `.proj-chapter-num` (0-1-0). */
.proj-chapter p.proj-chapter-num {
  font-size: 11px;
  line-height: inherit;
  color: var(--blau);
}

/* ------------------------------------------------------------------
   Formularseiten (Demo buchen, Kontakt, Angebot anfragen)

   Der Prototyp setzt hier fast alles inline. Als Block-Markup geht das
   nicht: der Editor wirft unbekannte style-Attribute beim Speichern weg.
   Die Werte stehen deshalb hier — Zeile für Zeile dieselben wie im
   Prototyp, nur als Klasse.
   ------------------------------------------------------------------ */

/* Prototyp: <div class="two-col" style="gap:56px"> */
.form-two-col { gap: 56px; }

/* Prototyp: <h2 class="section-title" style="font-size:clamp(26px,3vw,38px)"> */
.section-title-sm { font-size: clamp(26px, 3vw, 38px); }

/* Prototyp: <a style="color:var(--blau);font-weight:700"> im Lead über dem
   Formular. Global gilt `a { color: inherit }`, deshalb hier gesetzt. */
.form-intro .section-lead a { color: var(--blau); font-weight: 700; }

/* Die drei Zusicherungen neben dem Formular. */
.assurance-list { margin-top: 32px; display: flex; flex-direction: column; gap: 18px; }
.assurance-row { display: flex; gap: 14px; align-items: flex-start; }
.assurance-icon {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: var(--hellblau);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--blau);
}
.assurance-title { display: block; color: var(--dunkelblau); font-size: 15px; }
.assurance-text { font-size: 13px; color: var(--text-muted); }

/* Prototyp: <div style="margin-top:24px;display:flex;align-items:center;
   gap:16px;flex-wrap:wrap"> um den Submit-Button. */
.form-actions { margin-top: 24px; display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }

/* Honeypot: für Menschen unsichtbar, für Screenreader ausgeblendet
   (aria-hidden am Wrapper), für Bots ein verlockendes Feld. */
.form-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Die Meldung unter dem Formular bleibt auch leer stehen — im Prototyp
   genauso, und ihre 18px margin-top gehoeren zum Abstand unter dem Button.
   Ausserdem muss der aria-live-Bereich schon im DOM sein, damit
   Screenreader die spaetere Meldung ueberhaupt vorlesen. */
.form-note.err { color: #b3261e; }

/* Während des Sendens ist der Button blockiert. */
.form-card button[type="submit"][disabled] { opacity: 0.6; cursor: progress; }

/* Zwischen-Überschriften und Mehrfachauswahl im Formularblock.
   Der Prototyp kennt beides nicht — das echte Angebotsformular gruppiert
   seine Felder aber, und die Gruppenmarke folgt derselben Typografie wie
   `.eyebrow` im Design-System. */
.form-section-title {
  grid-column: span 2;
  margin-top: 10px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blau);
}
.form-grid > .form-section-title:first-child { margin-top: 0; }
.form-checks { display: flex; flex-wrap: wrap; gap: 10px 22px; padding-top: 2px; }
.form-check-inline { display: flex; gap: 8px; align-items: center; font-size: 14px; color: var(--dunkelblau); }

/* Turnstile sitzt zwischen Feldern und Button. */
.form-turnstile { margin-top: 20px; }

/* ------------------------------------------------------------------
   Kampagnen-Landingpages (/requirements…)

   Die alten Seiten haben bewusst keinen Ausgang: keine Navigation, kein
   Footer, beim Laden null Links. Bei bezahltem Traffic ist das Absicht —
   wer wegklickt, füllt das Formular nicht aus. Deshalb ein eigenes
   Template mit Logo und einer Zeile Pflichtangaben statt der Site-Chrome.
   ------------------------------------------------------------------ */
.lp-header {
  background: var(--dunkelblau);
  padding: 20px 0;
  color: var(--weiss);
}
/* Die Logo-Regeln in components.css greifen nur in .site-header und
   .site-footer. Ohne diese Zeilen hat der Fallback-SVG keine Höhe, und weil
   er `currentColor` nutzt, wäre er dunkelblau auf dunkelblau — also
   unsichtbar. Ein hochgeladenes Farblogo wird wie im Footer aufgehellt. */
.lp-header .wp-block-site-logo { line-height: 0; margin: 0; }
.lp-header .wp-block-site-logo a.custom-logo-link,
.lp-header .wp-block-site-logo a {
  display: inline-flex;
  align-items: center;
  padding: 0;
  margin: 0;
  color: var(--weiss);
}
.lp-header .wp-block-site-logo svg {
  height: 24px;
  width: auto;
  max-height: 24px;
  display: block;
}
.lp-header .wp-block-site-logo img {
  height: 24px;
  width: auto;
  max-height: 24px;
  display: block;
  filter: brightness(0) invert(1);
}

.lp-footer {
  background: var(--dunkelblau);
  padding: 22px 0;
  margin-top: 0;
}
.lp-footer p.lp-legal {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
  margin: 0;
}
.lp-footer a { color: rgba(255, 255, 255, 0.72); }
.lp-footer a:hover { color: var(--gelb); }

/* Auf diesen Seiten steht nichts neben dem Inhalt, was die 1240px der
   normalen Seitenbreite füllen würde. Deshalb eine eigene, schmalere und
   zentrierte Spalte — nur hier, über die Klasse am <main>. */
.lp-main .container { max-width: 940px; }

.lp-intro { max-width: none; }
.lp-intro p.section-lead { margin-top: 14px; }

/* Formular und Kontaktkarten sitzen mittig in der Spalte. */
.lp-form {
  max-width: 840px;
  margin: 36px auto 0;
}

/* Die Danke-Seiten nennen einen oder zwei Ansprechpartner. Das vierspaltige
   Team-Raster von /ueber-uns/ würde die Karten auf ein Viertel quetschen.
   Hier behalten sie ihre Breite und sitzen mittig: eine Karte bleibt 300px,
   zwei stehen nebeneinander, darunter rutschen sie ohne Extra-Regel
   untereinander, weil auto-fit das schon leistet. */
.team-grid-lp {
  grid-template-columns: repeat(auto-fit, minmax(240px, 300px));
  justify-content: center;
  max-width: 100%;
}
.lp-kontakt { margin-top: 40px; text-align: center; }

/* Auf schmalen Schirmen darf die Karte die volle Breite nehmen. */
@media (max-width: 560px) {
  .team-grid-lp { grid-template-columns: minmax(0, 1fr); }
}

/* Der Headline-Block schreibt die Core-Konvention `has-text-align-…` in die
   Klasse, das Design-System des Prototyps kennt aber nur `.center`. Ohne
   diese beiden Regeln bleibt die Ausrichtung in der Seitenleiste ohne
   Wirkung — aufgefallen beim Zentrieren der Landingpages, betrifft aber
   jeden Einsatz des Blocks. */
.section-title.has-text-align-center {
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}
.section-title.has-text-align-right { text-align: right; }

/* Echtes Video im Video-Block: kein Platzhalter-Abzeichen, kein Gitter.
   Der Block war bisher nur als Platzhalter im Einsatz, deshalb ist das erst
   mit dem Navigator-Mockup der Danke-Seiten aufgefallen. */
.media-ph.has-media::before,
.media-ph.has-media::after { content: none; display: none; }
.media-ph.has-media > video {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Ist ein <video> direktes Kind, richtet sich der Rahmen nach dem Video —
   kein Beschnitt durch ein festes aspect-ratio.
   Ohne <video>-Kind bleibt das feste Verhaeltnis: der Platzhalter hat kein
   Kind, das eine Hoehe mitbringt, sonst faellt sein Rahmen im Backend auf
   die Hoehe des Textes zusammen.
   Beide Varianten (.is-filled, .has-media) im Selektor mitgefuehrt, damit
   die Spezifitaet die aelteren `.is-filled > video` (0,2,1) und
   `.has-media > video` (0,2,1) sicher schlaegt (hier 0,2,2). */
.media-ph[data-ratio]:has(> video),
.media-ph.is-filled:has(> video),
.media-ph.has-media:has(> video) { aspect-ratio: auto; }
.media-ph:has(> video) > video,
.media-ph.is-filled:has(> video) > video,
.media-ph.has-media:has(> video) > video {
  position: static; inset: auto;
  width: 100%; height: auto;
  object-fit: initial;
  display: block;
}

/* Navigator-Mockup auf den Danke-Seiten: sitzt zwischen Danke-Text und
   Ansprechpartnern, mittig. Auf CH/DE/ES ein PNG (wp:image), auf
   MENA/Africa derselbe Mockup als stummer Loop — genau wie auf der
   Altseite. Das Motiv steht frei, deshalb kein Kartenrahmen.

   Die Masse sind an der Altseite abgemessen: dort ist das Bild 512 px
   breit, also seine Originalgroesse, und das quadratische Video (1080er
   Datei) sitzt in einem 625 px breiten 16:9-Ausschnitt. Deshalb 625 px
   Deckel und `width: auto` am Bild — so wird das PNG nie hochskaliert
   (bei 720 px war es sichtbar weich), schrumpft auf schmalen Schirmen
   aber mit. Der 16:9-Ausschnitt des Videos bleibt bewusst stehen: er
   kommt aus dem Block und entspricht der Altseite. */
.lp-main .lp-mockup {
  max-width: 625px;
  margin: 32px auto 0;
}
.lp-main .lp-mockup img {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  margin-inline: auto;
}
.lp-main .lp-mockup .media-ph {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

/* Der Hero-Badge im Prototyp ist ein <div> mit einem <span class="dot">.
   Als Gutenberg-Absatz wird daraus <p class="page-hero-badge"> — ein Span mit
   Klasse übersteht den Absatz-Editor nicht. Deshalb setzt CSS den Punkt, aber
   nur wenn keiner im Markup steht: der handgebaute Hero von /beyonityhello/
   bringt seinen eigenen mit und bekäme sonst zwei. Dazu margin-top: 0, weil
   die Klasse im Prototyp nur margin-bottom setzt und ein <p> vom Browser
   zusätzlich einen oberen Abstand erbt. */
p.page-hero-badge { margin-top: 0; }
.page-hero-badge:not(:has(.dot))::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--gelb);
  box-shadow: 0 0 10px var(--gelb);
  flex: none;
}

/* Der Hero-Lead ist bisher der einzige im Repo, der Links enthält (nur
   /kontakt/). styles.css:175 setzt die Absatzfarbe, aber keine Link-Regel.
   Ohne die hier würden Links die Erb-Farbe rgba(255,255,255,0.72) tragen
   und im dunkelblauen Hero gerade noch lesbar sein. Der Prototyp gibt den
   Zielwert: gelb, fett. Kein text-decoration, kein Prototyp-Wert dafür. */
.page-hero .lead a { color: var(--gelb); font-weight: 700; }

/* HELLO-OS-Seite: zwei Elemente, die vorher im rohen HTML der Raster steckten
   und jetzt eigene Blöcke sind.

   1. Die Quellenzeile unter den Kennzahl-Karten trug ihre Gestaltung als
      Inline-Style. Als Absatz-Block braucht sie eine Klasse.
   2. Das Banner darunter: `.win-banner-label` setzt 10px, gelb, gesperrt —
      aber `.win-banner p` (0,1,1) schlägt `.win-banner-label` (0,1,0), sobald
      die Beschriftung ein Absatz statt eines <span> ist. Der Guard mit
      `p.win-banner-label` hebt die Spezifität und stellt den Prototyp-Stand
      wieder her. Dieselbe Falle wie bei .eyebrow und .section-lead. */
p.ai-stats-source {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 16px;
  line-height: 1.5;
}
.win-banner-body {
  flex: 1;
  min-width: 260px;
}
.win-banner p.win-banner-label {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gelb);
  display: block;
  margin-top: 0;
  margin-bottom: 6px;
}

/* ---------------------------------------------------------------
   Echte Projektseiten (Neptun, Seepalais, Trump Tower)
   --------------------------------------------------------------- */

/* Im Prototyp ist .hero-figure ein <figure>. Als Blockgruppe wird es ein
   <div>, das ein echtes Core-Bild enthaelt — und figure.wp-block-image bringt
   den Core-Aussenabstand `margin: 0 0 1em` mit. Der muss weg, sonst haengt
   das Header-Rendering schief im Hero-Raster. */
.hero-figure figure.wp-block-image { margin: 0; }
.hero-figure figure.wp-block-image img { border-radius: var(--r-500); }

/* Renderings-Galerie: der Prototyp legt .proj-gallery als 3-Spalten-Raster
   an (styles.css). Die Core-Regel `.wp-block-gallery.has-nested-images`
   (0-2-0) schlaegt `.proj-gallery` (0-1-0) und macht daraus wieder ein
   Flex-Layout mit flex-grow. Deshalb hier mit drei Klassen nachziehen — das
   gewinnt unabhaengig davon, in welcher Reihenfolge Core-Blockstile und
   Theme-CSS im Head landen. */
.wp-block-gallery.has-nested-images.proj-gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}
.wp-block-gallery.has-nested-images.proj-gallery figure.wp-block-image {
  width: auto;
  margin: 0;
  flex: none;
}
.wp-block-gallery.has-nested-images.proj-gallery figure.wp-block-image img {
  display: block;
  width: 100%;
  height: 100%;
  /* 16:9, weil die Renderings so vorliegen: von 13 importierten Bildern
     sind 9 exakt 16:9 (1200 x 675). Bei 4:3 waeren die neun am linken und
     rechten Rand um je 12 % beschnitten worden; so bleiben sie unangetastet.
     Beschnitten werden nur die drei Ausreisser — ein 5:4-Bild bei Neptun,
     ein 3:2 und ein Panorama (3:1) bei Trump Tower. */
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--r-400);
}
@media (max-width: 760px) {
  .wp-block-gallery.has-nested-images.proj-gallery { grid-template-columns: 1fr; }
}

/* LOU-Seite (A12 Teil 5 Nachtrag 3): Kapitelbilder und Galerie sind
   einzelne Core-wp:image-Bloecke in einer Blockgruppe, keine wp:gallery
   — so bleibt im Backend jedes Bild einzeln tauschbar.
   figure.wp-block-image bringt Cores `margin: 0 0 1em` mit; im Raster
   muss der weg, sonst haengt das Bild neben dem Text nach unten.
   Drei Begruendungen, die NICHT neu hergeleitet werden sollen:
   (1) 16/9 statt 4/3: 12 der 14 LOU-Dateien sind exakt 16:9
       (1920x1080) und bleiben in einer 16/9-Box unbeschnitten. Die
       zwei Aussenbilder sind 16:10 (1920x1200), cover in 16/9
       schneidet oben und unten um je 5 %. Bei 4:3 waeren die zwoelf
       Innenbilder links/rechts um je 12,5 % beschnitten.
   (2) height:100% NUR in .proj-gallery: dort fuellen die Bilder die
       Rasterzeilenhoehe. Im .proj-chapter ist das Bild ein
       einzelnes Rasterfeld mit align-items:center; height:100%
       loest dort gegen automatische Hoehe auf und hilft nichts.
   (3) contentSize-Verengung greift NICHT: A17 hat
       --wp--style--global--content-size an .container auf 1240px
       gesetzt. Bei 1440px Viewport ist die Kapitel-Spalte rund
       590px breit — die WP-Regel verengt nichts, weil das Kind
       schmaler ist als der Container-Wert. Nicht erneut herleiten
       und nichts dagegen schreiben. */
.proj-chapter > figure.wp-block-image { margin: 0; }
.proj-chapter > figure.wp-block-image img {
  display: block; width: 100%;
  aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--r-400);
}
.proj-gallery > figure.wp-block-image { margin: 0; }
.proj-gallery > figure.wp-block-image img {
  display: block; width: 100%; height: 100%;
  aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--r-400);
}

/* ---------------------------------------------------------------
   Auftraggeber-Logo: Plakette auf der Projektkarte und im Kopf der
   Detailseite. Markup aus beyonity_projekt_logo_markup().

   Der Prototyp hat den Platz auf der Karte vorgesehen
   (.case-card-top .case-card-logo in styles.css: Position oben links,
   Glasflaeche, 13px hohe SVG-Marke). Dort steckt die Positionierung,
   hier die Flaeche und die zwei Polaritaeten — die Logos liegen gemischt
   vor: UBS und Instone sind schwarze Marken, DarGlobal eine weisse. Ein
   festes Farbschema wuerde immer die Haelfte unsichtbar machen.
   --------------------------------------------------------------- */
.proj-logo {
  display: inline-flex;
  align-items: center;
  padding: 7px 11px;
  border-radius: 8px;
  background: rgba(255,255,255,0.94);
  border: 1px solid rgba(255,255,255,0.7);
  box-shadow: 0 2px 10px rgba(0,26,100,0.18);
  backdrop-filter: blur(6px);
}
/* Beide Polaritaeten mit zwei Klassen ausschreiben, nicht nur die dunkle.
   Sonst kam die helle Flaeche allein aus `.proj-logo` (eine Klasse) und
   verlor gegen die Prototyp-Regel `.case-card-top .case-card-logo` (zwei
   Klassen) — die zwang jedes Logo auf Dunkelblau, und die schwarzen Marken
   von UBS und Instone waren damit unsichtbar. Auf der Box nachgemessen:
   is-hell rendert mit rgba(0,26,100,0.55), also dem Prototyp-Wert. */
.proj-logo.is-hell {
  background: rgba(255,255,255,0.94);
  border-color: rgba(255,255,255,0.7);
}
.proj-logo.is-dunkel {
  background: rgba(0,26,100,0.62);
  border-color: rgba(255,255,255,0.24);
  box-shadow: none;
}
/* object-fit: contain, weil die Logo-PNGs der Altseite 300 x 200 sind und
   die Marke darin frei steht — ohne contain wuerde sie verzerrt. */
/* Hoehe = Markenhoehe, weil der transparente Rand beim Import geschnitten
   wird (beyonity_projreal_trim_png im Seed-Skript). Vorher waren von 26 px
   Box nur 12 px Marke uebrig und im Kopf der Detailseite 7 — die Logos der
   Altseite sind 300 x 200 mit der Marke frei in der Mitte, und bei
   object-fit: contain bemisst sich die Darstellung an der Dateikante. */
.proj-logo .proj-logo-img,
.proj-logo img,
.proj-logo svg {
  display: block;
  height: 26px;
  width: auto;
  max-width: 150px;
  object-fit: contain;
}
.proj-logo .proj-logo-text {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--dunkelblau);
  white-space: nowrap;
}
.proj-logo.is-dunkel .proj-logo-text { color: var(--weiss); }

/* Auf der Karte steht die Plakette rechts in der Kennzahlenzeile, nicht mehr
   oben links auf dem Foto: dort war sie 14 px hoch, lag ueber wechselndem
   Bildinhalt und wurde von der Prototyp-Regel auf Dunkelblau gezwungen.
   .case-card-stats ist ein Flexrow mit `justify-content: flex-start`, also
   schiebt margin-left: auto die Plakette an den rechten Rand. */
.case-card-stats .proj-logo {
  margin-left: auto;
  align-self: center;
  flex: none;
}
/* Auf Weiss braucht eine dunkle Marke keine Plakette — nur Luft. Die weisse
   Marke behaelt ihre dunkle Flaeche, sonst waere sie auf Weiss unsichtbar;
   das faellt weg, sobald von dem Kunden auch die dunkle Version da ist. */
.case-card-stats .proj-logo.is-hell {
  background: none;
  border-color: transparent;
  box-shadow: none;
  backdrop-filter: none;
  padding: 0;
}
.case-card-stats .proj-logo .proj-logo-img,
.case-card-stats .proj-logo svg { height: 32px; max-width: 140px; }
@media (max-width: 420px) {
  .case-card-stats .proj-logo .proj-logo-img,
  .case-card-stats .proj-logo svg { height: 26px; max-width: 112px; }
}

/* Kopf der Detailseite: dieselbe Plakette auf dem Header-Rendering.
   .hero-figure ist position: relative, das Bild liegt auf z-index 1. */
.hero-figure .proj-logo-hero {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 2;
  padding: 10px 14px;
  border-radius: var(--r-300);
}
.hero-figure .proj-logo-hero .proj-logo-img,
.hero-figure .proj-logo-hero svg { height: 28px; max-width: 150px; }
@media (max-width: 620px) {
  .hero-figure .proj-logo-hero { top: 10px; left: 10px; padding: 8px 11px; }
  .hero-figure .proj-logo-hero .proj-logo-img,
  .hero-figure .proj-logo-hero svg { height: 20px; max-width: 116px; }
}

/* Auftraggeber unter dem Ort auf der Karte — auf der Altseite stand beides
   uebereinander. Etwas leiser als der Ort, damit die Zeile nicht kippt. */
.case-card-top .loc.case-card-kunde {
  margin-top: 2px;
  font-size: 11px;
  color: rgba(255,255,255,0.42);
}

/* ---------------------------------------------------------------
   Objektart-Tags im Projektkopf.

   Ersetzt das page-hero-badge mit Leuchtpunkt. Der Punkt ist ein
   Live-Zeichen (er traegt einen Glow und steht sonst an Zaehlern wie
   "347 Interessenten online") und hat an einer Objektart nichts zu
   suchen. Stattdessen zwei Pillen: die Vermarktungsart im Akzent, die
   Entwicklungsart neutral.

   `.proj-tags p.proj-tag` und nicht `.proj-tag`: als Block-Absatz wird
   aus dem Element ein <p>, und jede Regel der Form `X p` (0-1-1) schlaegt
   eine einzelne Klasse (0-1-0). Dieselbe Falle hat in diesem Projekt schon
   .win-banner-label und .proj-chapter-num erwischt.
   --------------------------------------------------------------- */
.proj-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 28px;
}
.proj-tags p.proj-tag {
  display: inline-flex;
  align-items: center;
  margin: 0;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--weiss);
  padding: 7px 15px;
  border-radius: 100px;
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--linie-w);
}
.proj-tags p.proj-tag.is-akzent {
  color: var(--gelb);
  background: rgba(248,255,118,0.07);
  border-color: rgba(248,255,118,0.32);
}

/* ---------------------------------------------------------------
   Blaetterleiste: vorheriges / naechstes Projekt.
   Markup aus src/blocks/projekt-pager/render.php, liegt im Template
   hinter dem Inhalt — also hinter dem Abschluss-CTA, wie auf der
   Altseite.
   --------------------------------------------------------------- */
.proj-pager {
  background: var(--weiss);
  border-top: 1px solid var(--linie);
  padding: 26px 0;
}
.proj-pager-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 20px;
}
.proj-pager-link {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  text-decoration: none;
  color: var(--dunkelblau);
  padding: 8px 4px;
  border-radius: var(--r-300);
}
.proj-pager-link.is-next { justify-self: end; text-align: right; }
.proj-pager-link.is-leer { pointer-events: none; }
.proj-pager-arrow {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--linie);
  color: var(--blau);
  transition: border-color 0.2s ease, background 0.2s ease;
}
.proj-pager-arrow svg { width: 16px; height: 16px; display: block; }
.proj-pager-link:hover .proj-pager-arrow { border-color: var(--blau); background: var(--blau-soft); }
.proj-pager-text { display: block; min-width: 0; }
.proj-pager-label {
  display: block;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.proj-pager-title {
  display: block;
  margin-top: 3px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--dunkelblau);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.proj-pager-link:hover .proj-pager-title { color: var(--blau); }
.proj-pager-all {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  text-decoration: none;
  padding: 8px 14px;
  border-radius: 100px;
  border: 1px solid var(--linie);
  white-space: nowrap;
}
.proj-pager-all:hover { color: var(--blau); border-color: var(--blau); }
@media (max-width: 720px) {
  .proj-pager-row { grid-template-columns: 1fr 1fr; row-gap: 14px; }
  .proj-pager-all { grid-column: 1 / -1; justify-self: center; order: 3; }
  .proj-pager-title { font-size: 14px; }
}

/* ---------------------------------------------------------------
   Kontaktzeilen in der Karte (/maerkte/, Sektion "Standorte").

   Global gilt `a { color: inherit; text-decoration: none }` — richtig fuer
   Navigation und Karten-Titel, falsch fuer eine mailto- oder tel-Zeile in
   einer Stichpunktliste: die saehe dann wie Text aus und niemand klickt sie.
   Deshalb hier eine Unterlinie, gedeckt statt hart, und der Akzent auf Hover.

   Zwei Polaritaeten, weil die Karte in zwei Faerbungen vorkommt: hell auf
   Weiss und dunkel als `.price-card.is-lead` auf Dunkelblau. Auf der dunklen
   Karte ist der Hover gelb, auf der hellen blau — auf der jeweils anderen
   Flaeche waere die Farbe nicht lesbar. Die is-lead-Regel traegt zwei
   Klassen (0-2-0) und schlaegt damit die einfache darueber.
   --------------------------------------------------------------- */
.price-card li a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: rgba(0,26,100,0.30);
  transition: color 0.2s ease, text-decoration-color 0.2s ease;
}
.price-card li a:hover,
.price-card li a:focus-visible {
  color: var(--blau);
  text-decoration-color: currentColor;
}
.price-card.is-lead li a { text-decoration-color: rgba(255,255,255,0.36); }
.price-card.is-lead li a:hover,
.price-card.is-lead li a:focus-visible {
  color: var(--gelb);
  text-decoration-color: currentColor;
}

/* ---------------------------------------------------------------
   Hero-Verlauf auf /maerkte/.

   `.hero-figure::before` legt einen blauen Radial-Verlauf hinter das
   Hero-Visual (rgba(60,87,225,0.45)). Auf den Produktseiten sitzt dort ein
   Geraet- oder Panel-Mockup, das den Verlauf ueberdeckt; die Kartenkachel
   der Maerkte-Seite ist schmaler als ihre Spalte, deshalb stand der Verlauf
   als hellblauer Fleck um sie herum. Die Startseite hat ihn nicht — ihr
   c2c-Stepper ist kein hero-figure. Gewuenscht war die Optik der
   Startseite: nur der gelbe Schimmer unten links aus `.hero-split::before`.

   Geschrieben mit :has(.mkx), damit die Regel sich selbst begrenzt — sie
   greift genau dort, wo die Maerkte-Szene steht, und laesst Navigator,
   HELLO OS, Realtime Tour und die uebrigen hero-figure-Seiten unberuehrt.
   Kein Body-Klassenname noetig (WordPress gibt Seiten nur page-id-<n>, und
   eine ID im Stylesheet waere nach jeder Neumigration falsch).
   --------------------------------------------------------------- */
.hero-figure:has(.mkx)::before { display: none; }

/* ---------------------------------------------------------------
   Tag als gelbe Plakette (price-card, Schalter „Tag als gelbe Plakette").

   Der Tag ist im Prototyp eine schlichte blaue Zeile. Auf /maerkte/ soll das
   HQ auffallen, ohne die ganze Karte umzufaerben — also dieselbe Pille, die
   das Design-System fuer Auszeichnungen benutzt: gelb gefuellt, Text in
   Dunkelblau.

   `.price-card .pc-tag.is-accent` und nicht `.pc-tag.is-accent`: die
   Grundregel steht als `.price-card .pc-tag` (0-2-0) in styles.css. Eine
   Regel mit einer Klasse und einer Pseudo-Klasse weniger verliert dagegen —
   dieselbe Falle wie bei den Projektlogos.

   Auf der dunklen is-lead-Karte bleibt es gelb, dort ist der normale Tag
   ohnehin schon gelb; die Plakette dreht das Verhaeltnis um (gefuellt statt
   nur farbiger Text) und bleibt dadurch unterscheidbar.
   --------------------------------------------------------------- */
.price-card .pc-tag.is-accent {
  /* .price-card ist eine Spalten-Flexbox. Ein Kind darin ist ein Flex-Item
     und streckt sich quer zur Achse auf die volle Breite — display:
     inline-block aendert daran nichts, das gilt nur ausserhalb von Flex.
     Ohne Hintergrund fiel das nie auf; die gefuellte Plakette lief dadurch
     ueber die ganze Karte. align-self holt sie auf ihre Inhaltsbreite
     zurueck. Nur an .is-accent, damit /preise/ unberuehrt bleibt. */
  align-self: flex-start;
  background: var(--gelb);
  color: var(--dunkelblau);
  padding: 4px 11px;
  border-radius: 100px;
  font-weight: 800;
  letter-spacing: 0.1em;
  box-shadow: 0 0 0 1px rgba(248,255,118,0.55), 0 6px 14px rgba(0,26,100,0.10);
}
.price-card.is-lead .pc-tag.is-accent {
  color: var(--dunkelblau);
  box-shadow: 0 0 0 1px rgba(248,255,118,0.55), 0 6px 18px rgba(0,0,0,0.28);
}

/* ---------------------------------------------------------------
   Testimonials-Slider: horizontale Karte statt mittigem Zitat.

   WARUM. Der Prototyp stellte das Zitat mittig, auf 24 Zeichen
   Zeilenbreite, mit einer kleinen Personenzeile darunter. Gemessen: bei
   34 px Schrift brach das Zitat in fuenf Zeilen und wurde 214 px hoch,
   waehrend die Person 88 px belegte. Das Zitat erdrueckte alles andere,
   und links und rechts stand die halbe Sektion leer.

   Jetzt eine Karte mit zwei Spalten: Zitat, Name und Logo links, das
   Portrait rechts. Dieselbe Schrift laeuft auf 46 Zeichen in drei Zeilen
   (106 px), das Portrait wiegt mit 220 px gleich viel. Die Karte ist
   dieselbe Huelle, die auch die Hero-Visuals benutzen — halbtransparentes
   Weiss, feine Linie, Radius 24, Blur.

   NUR DER SLIDER. Das Raster derselben Klassen auf /projekte/ sitzt in
   kleinen Karten; jede Regel hier ist auf .testi-slide bzw. .testi-slider
   eingeschraenkt.
   --------------------------------------------------------------- */

.testi-card-wide {
  display: grid;
  grid-template-columns: 1fr 220px;
  gap: 48px;
  align-items: center;
  background: rgba(255,255,255,0.05);
  border: 1px solid var(--linie-w);
  border-radius: var(--r-600);
  padding: 44px 48px;
  backdrop-filter: blur(12px);
  box-shadow: var(--elev-500);
}
.testi-card-body { min-width: 0; }

/* Das dekorative Anfuehrungszeichen. Gelb, aber stark zurueckgenommen —
   es soll den Blick anwerfen, nicht mitlesen. */
.testi-mark {
  display: block;
  font-size: 64px;
  line-height: 0.7;
  font-weight: 800;
  color: var(--gelb);
  opacity: 0.32;
  margin-bottom: 12px;
}

/* Zitat: linksbuendig, kleiner als vorher, dafuer breiter. 46ch ist die
   Grenze, an der es in drei Zeilen laeuft. */
.testi-slide blockquote {
  font-size: clamp(19px, 1.7vw, 25px);
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: -0.01em;
  color: var(--weiss);
  text-align: left;
  max-width: 46ch;
  margin: 0 0 26px;
}

/* Namenszeile und Logo in einer Reihe, LINKSBUENDIG beieinander mit einer
   feinen Trennlinie dazwischen.

   Erst stand das Logo per space-between am rechten Ende der Textspalte.
   Gemessen lagen dann 603 px Leerraum zwischen Namen und Logo, und das
   Logo klebte am Portrait — es sah aus, als gehoere es zum Bild statt zur
   Person. Nebeneinander mit Trennlinie ist eindeutig: beides beschreibt
   dieselbe Person. */
.testi-slide .testi-person {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 26px;
  flex-wrap: wrap;
  margin-top: 0;
}
.testi-ident { min-width: 0; }
.testi-slide .testi-name { font-size: 16px; }
.testi-slide .testi-role { font-size: 13px; margin-top: 3px; }
.testi-slide .testi-role span { opacity: 0.5; margin: 0 2px; }

/* Portrait. Gross und rund, mit feinem Ring. Der Zuschnitt kommt hier
   ueber object-position statt ueber den scale(1.5)-Zoom des Prototyps:
   bei 220 px schneidet der Zoom zu weit in das Gesicht hinein. */
.testi-slide .testi-avatar {
  width: 220px;
  height: 220px;
  box-shadow: 0 0 0 3px rgba(255,255,255,0.18), 0 18px 40px rgba(0,0,0,0.34);
}
.testi-slide .testi-avatar img {
  transform: none;
  object-position: 50% 22%;
}

/* Firmenlogo, weisse Fassung.

   ZWEI DECKEL, nicht einer. Die Logos haben sehr unterschiedliche
   Seitenverhaeltnisse: Privera 5,2:1 und Previs 3,5:1 sind breite
   Wortmarken, First Projects ist mit 89 x 107 hoeher als breit. Ein
   reiner Hoehendeckel behandelt die gleich und macht aus der
   quadratischen Marke einen Fleck, in dem nichts zu erkennen ist —
   gemessen, nicht geschaetzt. Mit beiden Deckeln entscheidet der Browser
   je Logo, welcher greift. Fuer First Projects waere ein einzeiliges
   Logo die eigentliche Loesung. */
.testi-slide .testi-logo {
  flex: none;
  padding-left: 26px;
  border-left: 1px solid var(--linie-w);
}
.testi-slide .testi-logo img {
  max-height: 38px;
  max-width: 150px;
  width: auto;
  height: auto;
  opacity: 0.85;
}
/* Im Raster auf /projekte/ sitzt das Logo unten in der Karte, die
   schmaler ist — dieselbe Logik, eine Stufe kleiner. */
.testi-card .testi-logo { margin-top: 18px; }
.testi-card .testi-logo img { max-height: 34px; max-width: 130px; width: auto; height: auto; opacity: 0.8; }

/* Bedienzeile: linksbuendig unter der Karte, weil die Karte selbst
   linksbuendig liest. Die Punkte brauchen Abstand voneinander —
   .testi-dots ist der Behaelter, den app.js fuellt, und hatte im
   Design-System gar keine Regel: die Punkte lagen aneinander. */
.testi-dots {
  display: inline-flex;
  align-items: center;
  gap: 9px;
}
.testi-slider .testi-controls {
  justify-content: flex-start;
  gap: 28px;
  margin-top: 40px;
}

@media (max-width: 820px) {
  .testi-card-wide {
    grid-template-columns: 1fr;
    gap: 28px;
    padding: 32px 26px 34px;
  }
  /* Portrait zuerst: auf dem Handy fuehrt das Gesicht ins Zitat. */
  .testi-slide .testi-avatar { width: 120px; height: 120px; order: -1; }
  .testi-mark { font-size: 52px; }
  .testi-slide blockquote { font-size: 18px; max-width: none; margin-bottom: 22px; }
  .testi-slide .testi-person { gap: 16px; }
  /* Bricht die Zeile um, stuende die Trennlinie am Zeilenanfang statt
     zwischen den beiden Angaben. Dann lieber ohne. */
  .testi-slide .testi-logo { padding-left: 0; border-left: 0; }
  .testi-slide .testi-logo img { max-height: 32px; max-width: 130px; }
  .testi-slider .testi-controls { gap: 18px; margin-top: 30px; }
}

/* ---------- LOGO-WAND: KATEGORIEN ALS FILTER ----------
   Im Prototyp sind die Kategorien reine Textchips (.logo-cat, uppercase,
   gedeckt). Als Filter werden daraus <button> — die Typografie bleibt
   genau dieselbe, damit die Sektion aussieht wie im Original; nur der
   Zustand kommt hinzu. Der aktive Zustand ist dunkelblauer Text mit
   gelber Unterstreichung: Gelb als Textfarbe ist auf Weiss unleserlich,
   als Linie ist es die Akzentfarbe der Marke.
   Beide Polaritäten stehen hier, weil .logo-cat aus styles.css kommt und
   ein Button eigene Browser-Vorgaben mitbringt (Rahmen, Grund, Schrift). */
.logo-cats button.logo-cat {
  border: 0; background: none; padding: 2px 0 6px; margin: 0;
  font-family: inherit; font-size: 12px; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-muted); cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: color 0.2s ease, border-color 0.2s ease;
}
.logo-cats button.logo-cat:hover { color: var(--dunkelblau); border-bottom-color: var(--linie); }
.logo-cats button.logo-cat.is-active { color: var(--dunkelblau); border-bottom-color: var(--gelb); }
.logo-cats button.logo-cat:focus-visible { outline: 2px solid var(--blau); outline-offset: 3px; }

/* Ausgeblendete Logos: .logo-ph ist inline-flex, das gewinnt gegen die
   Browser-Vorgabe für [hidden]. Ohne diese Zeile filtert der Knopf
   sichtbar nichts. */
.logo-wall [hidden] { display: none !important; }

/* Kategorie ohne freigegebene Logos (Verwaltungen) — ohne diesen Hinweis
   wäre die Wand nach dem Klick einfach leer und der Filter sähe kaputt
   aus. */
.logo-wall .logo-wall-leer {
  width: 100%; margin: 0; padding: 26px 0; text-align: center;
  font-size: 14px; color: var(--text-muted);
}

/* ---------- LOGO-WAND: EINHEITLICHE LOGOGROESSE ----------
   Die Kundenlogos tragen sehr verschiedene Eigengroessen im SVG: UBS ist
   43x16, Instone 1549x550 — Faktor 36. Die Prototyp-Regel
   `.logo-ph-real img { width: auto; max-width: 138px; max-height: 40px }`
   deckelt nur nach oben, also rendert UBS mit 43x16 und AXA mit 138x39 in
   derselben Reihe. Gemessen, nicht geschaetzt.

   Darum in der Wand ein FESTER Rahmen und object-fit: contain — jedes Logo
   wird in 138x40 eingepasst, kleine hoch, grosse herunter, Seitenverhaeltnis
   bleibt. Nur auf .logo-wall eingegrenzt: die Trust-Bar und die
   Partnerzeilen (.logo-ph-row) behalten ihre eigenen Groessen. */
.logo-wall .logo-ph-real img {
  width: 138px; height: 40px; max-width: none; max-height: none;
  object-fit: contain; object-position: center;
}

/* ---------- TRUST-BAR: EINHEITLICHE LOGOGROESSE ----------
   Die Prototyp-Regel ist `.trust-bar-logos img { width: 72px; height: auto }`.
   Sie stammt aus der Zeit, als dort ausschliesslich der Platzhalter stand —
   ein Bild mit festem Seitenverhaeltnis. Mit echten Logos bestimmt die
   Eigenform die Hoehe: AXA ist 25x25, wird also 72x72, First Projects ist
   89x107 und wird 72x87. Gemessen: die Leiste wuchs damit von 79 auf
   140 Pixel und die beiden Marken ueberragten alle anderen.

   Darum auch hier ein fester Rahmen mit object-fit — dieselbe Loesung wie
   in der Logo-Wand, nur kleiner. Breite und Hoehe muessen beide gesetzt
   sein, sonst wirkt object-fit nicht. */
.trust-bar-logos img {
  width: 92px; height: 28px; max-width: none; max-height: none;
  object-fit: contain; object-position: center;
}
@media (max-width: 768px) {
  .trust-bar-logos img { width: 72px; height: 24px; }
}

/* ---------- HOCHKANTE UND QUADRATISCHE LOGOS KLEINER ----------
   Ein Logo wird in einen festen, breiten Rahmen eingepasst. Eine hochkante
   oder quadratische Marke fuellt dessen Hoehe ganz aus und wirkt dadurch
   schwerer als eine breite Wortmarke daneben — bei einer Plakette
   (gefuellte Flaeche mit ausgestanzter Schrift) besonders deutlich.

   Solche Logos bekommen darum drei Viertel der Rahmenhoehe. Welche das
   sind, entscheidet render.php anhand der Datei (Grenze 1.35 Breite/Hoehe,
   gemessen: von 86 Dateien liegen 10 zwischen 0.72 und 1.34, dann klafft
   eine Luecke bis 1.40) — es steht also keine Markenliste im CSS.

   Die Selektoren tragen eine Klasse mehr als die Grundregeln darueber,
   damit sie gewinnen. */
.logo-wall .logo-ph-real.logo-ph-hochkant img {
  width: 104px; height: 30px;
}
.trust-bar-logos span.is-hochkant img {
  width: 70px; height: 21px;
}
@media (max-width: 768px) {
  .trust-bar-logos span.is-hochkant img { width: 54px; height: 18px; }
}

/* ---------- TRUST-BAR: FILTER NACH QUELLPOLARITAET ----------
   Die Prototyp-Regel faerbt jedes Logo der Leiste flach weiss:
   `filter: brightness(0) invert(1)`. Das ist richtig, solange die Quelle
   eine weisse Fassung ist — dann bleibt weiss weiss.

   Bei einer DUNKLEN oder FARBIGEN Quelle geht es schief, und zwar
   unsichtbar: brightness(0) macht Flaeche UND Schrift gleich schwarz,
   invert macht beides weiss. Aus AXA (blaue Flaeche #00008f, weisse
   Buchstaben #fff) wurde so ein voellig leerer weisser Block — gemessen
   und im Browser nachgesehen.

   Fuer solche Quellen darum entsaettigen und umkehren statt ausflachen:
   die dunkle Flaeche wird hell, die weisse Schrift dunkel, die Zeichnung
   bleibt lesbar. render.php setzt die Klasse anhand der geladenen
   Fassung — es steht keine Markenliste im CSS. */
.trust-bar-logos span.quelle-dunkel img {
  filter: grayscale(1) invert(1);
}

/* ---------- CHIPS: FEATURE UND ADD-ON ----------
   Beyonity fuehrt sein Chip-System selbst, als Musterblatt:
   Desktop/Beyonity_brand/Products/Product_system/Features Logos.svg.
   Nachgemessen darin (nicht geschaetzt): Pille 17 Einheiten hoch,
   rx 8.5 — also voll gerundet —, 1px Kontur #F0F0F0, und zwei Fuellungen,
   die die Art trennen:

     #FFFFC8  blassgelb   -> Feature
     #FBFCFF  fast weiss  -> Add-on

   Die GEOMETRIE kommt weiter aus dem Prototyp (.proj-stack: 11/18
   Innenabstand, 14px, radius 100px) — der ist fuer die Website
   verbindlich. Von hier kommt nur die Farbe, und zwar ueber die drei
   Variablen, die styles.css dafuer vorsieht: --chip-flaeche,
   --chip-farbe, --chip-icon. Eine Variable am Element gilt immer, ganz
   egal wie spezifisch die Grundregel ist — darum kein !important und
   keine Reihenfolgenfalle.

   Wichtig: das blassgelbe #ffffc8 ist NICHT --gelb (#f8ff76). --gelb ist
   der Akzent fuer Buttons und Eyebrows, deutlich greller. Das
   Musterblatt nutzt einen eigenen, blassen Gelbton; darum ein eigenes
   Token statt einer Umdeutung des Akzents. */
:root {
  --gelb-blass: #ffffc8;   /* Feature-Chips, aus dem Musterblatt   */
  --weiss-blau: #fbfcff;   /* Add-on-Chips, aus dem Musterblatt    */
  --grau-400:   #aaaaaa;   /* geplant: Schriftfarbe im Musterblatt */
}
.chip-feature { --chip-flaeche: var(--gelb-blass); }
.chip-addon   { --chip-flaeche: var(--weiss-blau); }

/* „geplant" heisst: im Musterblatt ausgegraut. Genau fuenf Add-ons sind
   dort so gesetzt (Unique Objects, PixelStreaming, Self Furnishing,
   Waiting List, Chatbot). render.php nimmt solchen Chips auch den Link,
   denn dahinter liegt noch keine Seite. */
.ist-geplant {
  --chip-flaeche: var(--weiss);
  --chip-farbe:   var(--grau-400);
  --chip-icon:    var(--grau-400);
}

/* Die Produkt-Icons sind quadratisch (enge, quadratische viewBox), damit
   sie in einer festen Box optisch gleich gross wirken. .proj-stack setzt
   18px selbst; in einer anderen Klassenfamilie — etwa .sol-chips — sonst
   nicht, und ein SVG ohne Groesse wird 300px breit. */
.chip-feature svg,
.chip-addon svg {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  color: var(--chip-icon, var(--blau));
}

/* A10: [hidden] muss die display-Regel der Karten schlagen. .product-card
   (styles.css) und .post-card (blog.css) setzen display:flex mit derselben
   Spezifitaet wie [hidden] und gewinnen durch die Reihenfolge — gemessen am
   10.09. auf /blog/: alle sechs Karten sichtbar, obwohl drei das
   hidden-Attribut trugen, und der Knopf stand darunter. Dieselbe Falle wie
   bei .logo-wall (Zeile 1062); dort ist sie schon so geloest. Ueber das
   Datenattribut, damit beide Raster erfasst sind. */
[data-mehr-laden] > [hidden] { display: none !important; }

/* Der embed-facade ist nie fuer die volle Breite gedacht — er hat kein
   align-Attribut und sitzt im Hausmuster in .container. Auf der LOU-Seite
   lag er nach einer Backend-Bearbeitung als Geschwister NEBEN dem
   container derselben Sektion; gemessen am 10.09. bei innerWidth 1440:
   figure 1440 px breit, der container daneben 1240 px, die Bildunterschrift
   klebte am Fensterrand.

   Die Begrenzung greift nur, wenn die figure direktes Kind einer section
   ist — also genau dann, wenn sie ausserhalb des containers haengt. Liegt
   sie richtig, ist die Regel wirkungslos.

   Die drei Werte sind dieselben wie bei .container (styles.css): 1240px,
   zentriert, 32px seitlich. Wer sie dort aendert, muss sie hier mitziehen —
   eine Variable hilft nicht, weil --wp--style--global--content-size laut
   A17 auf .container sitzt und ausserhalb nicht gilt. */
section > .embed-figure {
  max-width: 1240px;
  margin-inline: auto;
  padding-inline: 32px;
}


/* Vorschau mit Blur: bei autoload steht das iframe schon dahinter, die
   Vorschaltflaeche liegt durchscheinend darauf — der Besucher sieht, was ihn
   erwartet, und ein Klick gibt es frei (Paulo am 10.09.: "statt blau ginge
   auch transparent mit blur"). Die Stapelung kommt aus der DOM-Reihenfolge in
   render.php: iframe zuerst, Flaeche danach.

   Das Rasterbild der Flaeche (styles.css: .embed-facade::before) wuerde ueber
   dem Blur zu unruhig, darum stark gedimmt.

   Ohne backdrop-filter — aeltere Browser, und Firefox bis vor kurzem hinter
   einem Schalter — waere die Flaeche nur eine helle Scheibe ohne Weichzeichnung
   und der Text darauf schlecht lesbar. Deshalb deckt der Fallback staerker ab.
   Er ist keine Zierde: ohne ihn haengt die Lesbarkeit an einer Eigenschaft,
   die nicht ueberall greift. */
.embed-vorschau .embed-facade {
  background: rgba(3, 12, 48, 0.42);
  backdrop-filter: blur(7px) saturate(1.05);
  -webkit-backdrop-filter: blur(7px) saturate(1.05);
}
.embed-vorschau .embed-facade::before { opacity: 0.3; }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .embed-vorschau .embed-facade { background: rgba(3, 12, 48, 0.74); }
}


/* Produkt-Icon im Add-On-Chip. Die Dateien in assets/produkt-icons/ haben
   verschiedene viewBox-Werte (aus dem Markenmaterial uebernommen), deshalb
   feste Groesse statt em — sonst erscheinen sie unterschiedlich gross.
   18px ist derselbe Wert wie bei .chip-feature svg weiter oben. */
.addon-chip-produkt {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  margin-inline-end: 2px;
}


/* „Alle N angezeigt." unter Projekt- und Beitragsraster. Paulo will die
   Meldung nicht sehen — sie erscheint ohnehin nur in der Endstellung und
   liest sich wie eine Systemmeldung. Geloescht wird sie trotzdem nicht:
   der Absatz ist die role="status"-Live-Region, ueber die ein Screenreader
   nach dem Klick auf „Weitere laden" ueberhaupt erfaehrt, dass jetzt alles
   da ist. Ohne ihn meldet der Knopf sein Verschwinden stumm. Also optisch
   weg, fuer die Vorlesefunktion da — dieselbe Technik wie .sr-only in
   styles.css:70. */
.grid-more-status {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* --------------------------------------------------------------------
   .case-feature-kompakt — Fassung der Case-Feature-Karte, die zusammen
   mit ihrem Sektionskopf auf einen Bildschirm passt.

   Die Grundfassung .case-feature (styles.css:1393) staffelt im dunklen
   Panel Tag, Bild, Titel, Text und Knopf untereinander und kommt damit
   auf rund 740 px; mit Kopf und Sektionspolster waren es 922 px. Unter
   einer 73 px hohen Kopfzeile bleiben auf 1440x900 aber nur 827 px.
   Gemessen im Browser, nicht geschaetzt: die Fassung hier liegt bei
   828 px, die Karte bei 492 px.

   Gekuerzt wird an den Stellen, die Hoehe kosten, ohne dass etwas
   wegfaellt: Innenabstand, Bildhoehe, Schriftgroessen.

   DAS BILD BEKOMMT EINE FESTE HOEHE MIT object-fit: cover, nicht eine
   kleinere Breite. Sonst schrumpft die Karte mit und das Rendering wird
   zur Briefmarke neben den Zahlen. object-position haelt den Baukoerper
   im Ausschnitt — ohne sie schneidet der Mittelschnitt Himmel und
   Strasse heraus und laesst das Gebaeude als Streifen uebrig.

   Der Abstand unter dem Bild steht bewusst auf 24 px: bei 18 px klebte
   "LOU Luzern" am Foto.
   -------------------------------------------------------------------- */
.case-feature-kompakt .case-feature-visual { padding: 36px 40px; }
.case-feature-kompakt .case-feature-metrics { padding: 36px 40px; gap: 24px 28px; }

.case-feature-kompakt .case-feature-visual .wp-block-image { margin: 0 0 24px; }
.case-feature-kompakt .case-feature-visual .wp-block-image img {
  display: block; width: 100%; height: 172px;
  object-fit: cover; object-position: center 42%;
}

.case-feature-kompakt .case-feature-visual p.case-tag { margin-bottom: 16px; }
.case-feature-kompakt .case-feature-visual h3 { font-size: clamp(20px, 2.1vw, 26px); margin-bottom: 10px; }
.case-feature-kompakt .case-feature-visual p { font-size: 14px; line-height: 1.55; }
.case-feature-kompakt .case-feature-cta { margin-top: 18px; }
.case-feature-kompakt .case-feature-cta .btn-outline-white { padding: 12px 26px; font-size: 14px; }

.case-feature-kompakt .case-metric .num { font-size: clamp(28px, 3vw, 38px); }
.case-feature-kompakt .case-metric .lbl { font-size: 12.5px; margin-top: 6px; }

/* Einspaltig ist Hoehe kein Problem mehr — dort darf das Bild wieder
   mehr vom Gebaeude zeigen. */
@media (max-width: 880px) {
  .case-feature-kompakt .case-feature-visual .wp-block-image img { height: 200px; }
}

/* Grenze zwischen zwei gleichfarbigen Sektionen. Zwei Sektionen mit je
   80 px Polster haben Abstand genug, er liest sich nur nicht als
   Grenze — eine Haarlinie kostet 1 px statt weiterer 100. */
.section-trenner { border-top: 1px solid var(--linie); }

/* Die Zahlenhaelfte steht in der Grundfassung auf var(--grau) — auf einer
   grauen Sektion ist das dieselbe Flaeche, die Karte hoerte rechts optisch
   auf. Weiss plus eine leichte Erhebung macht aus beiden Haelften wieder
   einen Koerper.

   --elev-100 und nicht --shadow-card: --shadow-card ist im Haus der
   HOVER-Wert der Projektkarten (.case-card:hover), im Ruhezustand tragen
   die gar keinen Schatten. Diese Karte ist nicht anklickbar — nur der
   Knopf darin ist es. Ein Hover-schwerer Schatten auf einer Flaeche, die
   auf Klick nicht reagiert, verspricht etwas, das nicht kommt.
   --elev-100 ist derselbe Ruhewert, den .product-card traegt. */
.case-feature-kompakt { box-shadow: var(--elev-100); }
.case-feature-kompakt .case-feature-metrics { background: var(--weiss); }

/* Hover wie bei den Projektkarten oben (.case-card:hover, styles.css:1407
   und 1423): Karte hebt 4 px, Schatten geht auf den Kartenwert, Bild zoomt
   auf 1.045. Der Ruhezustand bleibt --elev-100, damit die Karte auch ohne
   Maus als Koerper lesbar ist — anders als .case-card, die auf weissem
   Grund steht und ohne Schatten auskommt.

   Der Bildrahmen bekommt overflow: hidden. Ohne ihn waechst das Bild beim
   Zoom ueber seine Ecken hinaus in den Innenabstand des dunklen Panels;
   .case-card faellt das nicht auf, weil dort .case-card-top schon clippt.

   prefers-reduced-motion schaltet beide Bewegungen ab — dieselbe Regel wie
   fuer .case-card-img in styles.css:1440. */
.case-feature-kompakt { position: relative; transition: transform 0.3s ease, box-shadow 0.3s ease; }
.case-feature-kompakt:hover { box-shadow: var(--shadow-card); transform: translateY(-4px); }
.case-feature-kompakt .case-feature-visual .wp-block-image { overflow: hidden; border-radius: 14px; }
.case-feature-kompakt .case-feature-visual .wp-block-image img { transition: transform 0.3s ease; }
.case-feature-kompakt:hover .case-feature-visual .wp-block-image img { transform: scale(1.045); }

@media (prefers-reduced-motion: reduce) {
  .case-feature-kompakt, .case-feature-kompakt:hover,
  .case-feature-kompakt .case-feature-visual .wp-block-image img,
  .case-feature-kompakt:hover .case-feature-visual .wp-block-image img {
    transition: none; transform: none;
  }
}

/* ---------- LOGOWAND: KEIN FARBWECHSEL BEIM DARUEBERFAHREN ----------
   styles.css:1899/1901 legt einen Graufilter auf jedes Logo und nimmt ihn
   beim Hover weg. Das stammt aus der Platzhalterzeit und funktioniert nur,
   wenn von JEDER Marke eine farbige Fassung vorliegt. Das ist nicht der
   Fall: die Wand fuehrt 62 Marken, viele davon als einfarbig schwarze
   Datei. Beim Darueberfahren werden also einzelne Kacheln bunt und die
   daneben bleiben schwarz — der Wechsel sieht nach Fehler aus, nicht nach
   Absicht.

   Der Graufilter bleibt darum auch im Hover stehen. Nur .logo-wall, damit
   Trust-Bar und Partnerzeilen unberuehrt bleiben; die haben eigene Filter
   (brightness/invert) und eigene Regeln. */
.logo-wall .logo-ph:hover img { filter: grayscale(1); }

/* Zwischenstufe in der Brotkrume — eine Menuegruppe ohne eigene Seite.
   "Ressourcen" buendelt Blog, FAQ, Preise, Integrationen und InfoSec, hat
   aber keine Seite: /ressourcen/ ist gemessen ein 404. Darum kein <a>, das
   ins Leere fuehrt.

   Aber auch kein blosses <span>: styles.css:425 faerbt jedes span in der
   Brotkrume auf 0.78 und markiert damit die AKTUELLE Seite. Zwei helle
   Stufen nebeneinander lesen sich wie zwei aktuelle Seiten. Die Gruppe
   bekommt darum die Farbe der uebrigen Stufen. */
.breadcrumb .crumb-gruppe { color: rgba(255, 255, 255, 0.45); }

/* ---------- 404 ----------
   Die alte Seite war ein blaues Feld mit einer riesigen weissen 404 und
   drei gelben Pillen. Der Aufbau war richtig (Zahl, ein Satz, drei Wege),
   die Mittel sind es nicht mehr: gelb ist im neuen System Akzent, nicht
   Flaeche, und drei gleich grosse Primary-Buttons nebeneinander gibt es
   auf keiner anderen Seite. Also dieselbe Dramaturgie in den Bauteilen,
   die der Rest der Site benutzt: dunkelblaue Sektion mit dem Farbverlauf
   der final-cta, Zahl in Gelb, section-title, drei Karten. */
.fehler-404 {
	background: var(--dunkelblau);
	color: var(--weiss);
	text-align: center;
	position: relative;
	overflow: hidden;
	padding: clamp(72px, 12vh, 132px) 0;
}
.fehler-404::before {
	content: '';
	position: absolute;
	inset: 0;
	background:
		radial-gradient(circle at 20% 0%, rgba(255,255,255,0.08) 0%, transparent 45%),
		radial-gradient(circle at 80% 100%, rgba(248,255,118,0.10) 0%, transparent 45%);
}
.fehler-404 .container { position: relative; z-index: 2; }
.fehler-404-zahl {
	display: block;
	font-size: clamp(88px, 17vw, 190px);
	font-weight: 800;
	line-height: 0.88;
	letter-spacing: -0.045em;
	color: var(--gelb);
	margin-bottom: 20px;
}
.fehler-404 .section-title { color: var(--weiss); }
.fehler-404-wege {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 16px;
	margin-top: 46px;
	text-align: left;
}
@media (max-width: 860px) { .fehler-404-wege { grid-template-columns: 1fr; } }
.fehler-404-weg {
	display: flex;
	flex-direction: column;
	gap: 7px;
	padding: 24px 26px;
	border-radius: var(--r-400);
	border: 1px solid var(--linie-w);
	background: rgba(255,255,255,0.05);
	color: var(--weiss) !important;
	transition: border-color 0.2s ease, background 0.2s ease;
}
.fehler-404-weg:hover {
	border-color: rgba(248,255,118,0.55);
	background: rgba(255,255,255,0.09);
}
.fehler-404-weg-titel {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-size: 17px;
	font-weight: 800;
}
.fehler-404-weg-titel .arrow { transition: transform 0.2s ease; }
.fehler-404-weg:hover .arrow { transform: translateX(4px); }
.fehler-404-weg-text {
	font-size: 14px;
	line-height: 1.55;
	color: rgba(255,255,255,0.68);
}
.fehler-404-hilfe {
	margin-top: 36px;
	font-size: 15px;
	color: rgba(255,255,255,0.62);
}
.fehler-404-hilfe a {
	color: var(--gelb);
	text-decoration: underline;
	text-underline-offset: 3px;
}
/* Wer Bewegung abbestellt hat, bekommt den Pfeil ohne Sprung. */
@media (prefers-reduced-motion: reduce) {
	.fehler-404-weg-titel .arrow { transition: none; }
	.fehler-404-weg:hover .arrow { transform: none; }
}
