/* ==========================================================================
   FW Blocks — Frontend-Raster (vom BlockRenderer ausgegeben).

   Prinzip:
   - CSS-Grid mit --bg-cols Spalten; Zellen sind QUADRATISCH:
     Zeilenhöhe = (Containerbreite − Gaps) / Spalten (Container-Query-Einheit).
   - minmax(…, auto): Text, der höher ist als seine Zellen, dehnt die Zeile,
     statt abgeschnitten zu werden.
   - Mobile (<720px): Grid wird zum Stapel in DOM-Reihenfolge (Renderer
     sortiert nach y,x) — kein JavaScript nötig.
   ========================================================================== */

html { overflow-x: clip; } /* 100vw-Breakouts ohne horizontale Scrollbar */

/* 🪁 Mitschweben (anim.follow): weiches Nachziehen beim Scrollen */
.fw-follow { will-change: transform; transition: transform .25s cubic-bezier(.2, .8, .3, 1); }
@media (prefers-reduced-motion: reduce) { .fw-follow { transition: none; } }

/* 🪄 Import-Reveal-Rettung: macht JS-abhängig versteckte Importe sichtbar
   (mit sanftem Fade-In). --force neutralisiert zusätzlich versetzende
   Transforms, falls die Original-CSS-Reveal-Klassen nicht greifen. */
.fw-imported .fw-revealed {
  opacity: 1 !important; visibility: visible !important;
  transition: opacity .6s ease, transform .6s ease !important;
}
.fw-imported .fw-revealed--force { transform: none !important; animation: none !important; }
@media (prefers-reduced-motion: reduce) {
  .fw-imported .fw-revealed { transition: none !important; }
}

.fw-blocks {
  container-type: inline-size;
  margin: 1.5rem auto;
}
/* 📱 WebKit-Bug: position:sticky INNERHALB eines Container-Query-Containers
   pinnt auf iOS nicht (Inhalt scrollt einfach weiter). Auf kleinen Screens
   braucht das Raster die Container-Einheiten ohnehin nicht (<720px stapelt
   es als Liste; 720–820px degradiert cqw sauber zur Viewport-Näherung wie
   im @supports-Fallback) → Containment dort abschalten, Sticky lebt. */
@media (max-width: 820px) {
  .fw-blocks { container-type: normal; }
}

/* Vollseiten-Kontexte (Home-Templates: #content, Import: .fw-imported): Das
   Raster IST die Seite — der Außenabstand würde als heller Streifen zwischen
   Header und erster Sektion (bzw. vor dem Footer) durchscheinen. Sektionen
   bringen ihre Abstände selbst mit.                                          */
#content > .fw-blocks,
.fw-imported > .fw-blocks {
  margin-top: 0;
  margin-bottom: 0;
}

/* Schmale/linksbündige Text-Wrapper (Lesebreite wie .content.prose mit
   max-width:72ch) neutralisieren, sobald sie ein Raster enthalten: Der
   vw-Breakout rechnet von der ELTERN-Mitte — sitzt der Wrapper nicht in der
   Bildschirmmitte, hängt „Volle Breite" weit links aus dem Bild.            */
.content:has(> .fw-blocks),
.prose:has(> .fw-blocks),
.about-text:has(> .fw-blocks) {
  max-width: none !important;
  width: 100%;
  margin-left: 0 !important;
  margin-right: 0 !important;
}

/* ---- Breiten-Modi ----------------------------------------------------------
   „Container": zentrierte Inhaltsbreite — auch wenn der Eltern-Wrapper
   (Home-Templates: #content, Import: .fw-imported) vollbreit ist.            */
.fw-blocks--container {
  width: 100%;
  max-width: var(--container, 1140px);
  margin-left: auto; margin-right: auto;
}

/* vw-Breakout für Seiten, deren Template den Inhalt in einen schmalen
   .container steckt (Standard-/Fokus-Templates etc.).                        */
.fw-blocks--full   { width: 100vw;     margin-left: calc(50% - 50vw); }
.fw-blocks--w75    { width: 75vw;      margin-left: calc(50% - 37.5vw); }
.fw-blocks--w66    { width: 66.666vw;  margin-left: calc(50% - 33.333vw); }
.fw-blocks--custom { width: calc(var(--bg-pagew, 80) * 1vw); margin-left: calc(50% - var(--bg-pagew, 80) * .5vw); }

/* In ohnehin VOLLBREITEN Wrappern ist der vw-Breakout falsch (Scrollbar-
   Versatz: links raus, rechts fehlt ein Stück) → dort einfache Prozente.     */
#content > .fw-blocks--full,   .fw-imported > .fw-blocks--full   { width: 100%; margin-left: 0; }
#content > .fw-blocks--w75,    .fw-imported > .fw-blocks--w75    { width: 75%;     margin-left: auto; margin-right: auto; }
#content > .fw-blocks--w66,    .fw-imported > .fw-blocks--w66    { width: 66.666%; margin-left: auto; margin-right: auto; }
#content > .fw-blocks--custom, .fw-imported > .fw-blocks--custom { width: calc(var(--bg-pagew, 80) * 1%); margin-left: auto; margin-right: auto; }

@media (max-width: 900px) {
  /* Auf kleineren Screens sind schmale Modi kontraproduktiv → volle Breite */
  .fw-blocks--w75, .fw-blocks--w66, .fw-blocks--custom { width: 100% !important; margin-left: 0 !important; margin-right: 0 !important; }
}

.fw-blocks__grid {
  /* Quadrat-Zellhöhe als Variable — auch der Renderer nutzt sie, wenn er bei
     „Lücken kürzen" ein explizites grid-template-rows inline ausgibt. */
  --bg-cell: calc((100cqw - (var(--bg-cols, 11) - 1) * var(--bg-gap, 12px)) / var(--bg-cols, 11));
  display: grid;
  grid-template-columns: repeat(var(--bg-cols, 11), 1fr);
  /* ❗️FESTE Zeilenhöhe (Modulator 2.0). Mit `minmax(cell, auto)` dehnte ein
     Block mit viel Inhalt seine Zeile — gemessen 84, 88 und 248 px auf einer
     Seite, das Gitter war keins. Hier liegt der eigentliche Hebel: seit
     „Lücken kürzen" weg ist, gibt der Renderer gar kein grid-template-rows
     mehr aus, ALLE Zeilen kommen also von hier.
     Blöcke dürfen trotzdem länger sein als ihre Zeilen — dafür sorgt
     `align-self:start` weiter unten. */
  grid-auto-rows: var(--bg-cell);
  gap: var(--bg-gap, 12px);
}
@supports not (width: 1cqw) {
  /* Fallback für ältere Browser: vw-Näherung (etwas zu groß in Containern, nie clippend) */
  .fw-blocks__grid {
    --bg-cell: calc((100vw - (var(--bg-cols, 11) - 1) * var(--bg-gap, 12px)) / var(--bg-cols, 11));
  }
}

.fw-block { min-width: 0; position: relative; }
.fw-block__inner { height: 100%; min-width: 0; overflow-wrap: break-word; }

/* ❗️MODULATOR 2.0: Der Block beginnt an seiner Rasterlinie und endet an seinem
   INHALT — er wird weder auf seine Spuren gestreckt noch von ihnen begrenzt.
   Nur Oberkante, linke und rechte Kante richten sich am Gitter aus; die Länge
   ist davon unabhängig. Genau deshalb ist das Anhängen an die Unterkante eines
   Blocks sinnvoll: die endet fast nie auf einer Linie.
   `align-self:start` verhindert das Strecken, `grid-row: auto` NICHT mehr
   nötig — die Zeile kommt vom Renderer und darf überschritten werden. */
.fw-block--flow { align-self: start; }
/* ❗️DER BLOCK BESTIMMT DIE BREITE, NICHT DAS MODUL (Ansage 2026-10-05: „die
   Box ist breit gezogen, es passt sich dem aber nicht an"). Die Module stammen
   aus der Zeit, in der sie mitten im Fliesstext standen, und bringen dafür
   eine Höchstbreite mit (Wunschformular 560 px, Kontakt 720 px, Öffnungszeiten
   560 px …). Im Raster zieht man den Block auf die gewünschte Breite; was darin
   steht, füllt sie. Nur die OBERSTE Ebene: Grenzen innerhalb eines Moduls
   (ein Mengenfeld, eine Bildspalte) bleiben, wie sie sind. */
.fw-block--shortcode > .fw-block__inner > * { max-width: none; }
/* ❗️Und dieselbe oberste Ebene bringt Aussenabstände für den Fliesstext mit
   (Wunschformular 32 px oben und unten, der Hinweis „leer" 24 px). Im Raster
   setzt das Raster die Abstände; mit ihnen war der Rahmen eines Moduls 64 px
   höher als das Modul (gemeldet 2026-10-05: „Box ist etwas länger, als das
   Modul wirklich ist"). Der Block beginnt und endet jetzt am Modul. */
.fw-block--shortcode > .fw-block__inner > :first-child { margin-top: 0; }
.fw-block--shortcode > .fw-block__inner > :last-child { margin-bottom: 0; }
/* ❗️TRENNER „OBEN": der Block endet an seiner Linie (gemessen vorher 84 px
   Hitbox für eine 1-px-Linie). Gewünscht ist ausdrücklich das Gegenteil:
   „bei oben ist die Hitbox sehr dünn". */
.fw-block--divider:has(.fw-divider[data-lage="oben"]) { align-self: start; min-height: 0 !important; }
.fw-block--divider:has(.fw-divider[data-lage="oben"]) > .fw-block__inner { height: auto; }
/* ❗️ANKER-KETTE (Modulator 2.0): Hülle über ALLE Spalten, innen ein SUBGRID.
   Damit liegen die Spalten der Kette exakt auf denen des Hauptrasters — jeder
   angehängte Block behält sein eigenes `grid-column` und ist genau so breit,
   wie er gezeichnet ist. (Vorher stand er als Kind IM Kasten seines Ankers und
   erbte dessen Breite; an einem breiteren Anker schob er sich über seine
   Nachbarn.)
   Senkrecht bekommt jedes Glied eine eigene Zeile bei `row-gap: 0` — Zeile 1
   ist genau so hoch wie der Kopf, also IST dessen Unterkante die Oberkante des
   nächsten. Keine gerechnete Höhe, nirgends.
   `align-self: start`, damit die Kette nicht auf ihre Rasterspur gestreckt
   wird, sondern an ihrem Inhalt endet — dieselbe Regel wie für Blöcke. */
.fw-kette {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  grid-auto-rows: auto;
  row-gap: 0;
  column-gap: var(--bg-gap, 12px);
  align-self: start;
  min-width: 0;
}
@supports not (grid-template-columns: subgrid) {
  /* Ohne Subgrid dieselben Spuren nachbauen: Die Hülle spannt über die volle
     Rasterbreite, `repeat(N, 1fr)` + gleicher Abstand ergibt deckungsgleiche
     Spalten. Nur für alte Browser — Ergebnis ist identisch. */
  .fw-kette { grid-template-columns: repeat(var(--bg-cols, 11), 1fr); }
}
/* Angehängter Block: eigene Spalten, eigene Zeile in der Hülle. Ausdrücklich
   KEINE Breitenangabe — die Breite kommt allein aus `grid-column`. */
.fw-block--angehaengt { position: relative; }
.fw-block--flow .fw-block__inner { height: auto; }

/* 🪜 Versetzter Block („Lücken kürzen" + gezeichnete Überlappung): sitzt in
   der Zeile NACH seinem Anker-Block und zieht sich um --fw-lift gezeichnete
   Zeilenhöhen über dessen Inhaltsende — Überlappung bleibt exakt so groß wie
   im Editor gezeichnet, egal wie hoch der Inhalt darüber real ist. */
.fw-blocks__grid > .fw-block--lifted {
  margin-top: calc(var(--fw-lift, 0) * (var(--bg-cell) + var(--bg-gap, 12px)) * -1);
}
@media (max-width: 719.98px) {
  /* Mobile-Stapel: kein Hochziehen — Blöcke folgen normal aufeinander */
  .fw-blocks__grid > .fw-block--lifted { margin-top: 0; }
}

/* Sandbox-HTML mit Viewport-Inhalt (vh/sticky/fixed): echte Bildschirmhöhe,
   scrollt intern — so ist „vh" = ein Bildschirm und Sticky-Effekte funktionieren.
   (Auto-Höhe wäre hier fatal: iframe-Höhe × vh = Rückkopplung → riesige Lücken.) */
.fw-html-sandbox--viewport { height: 100vh !important; }

/* Voll randloser Einzel-Block (nur wenn er alle Spalten überspannt) */
.fw-block--bleed > .fw-block__inner { width: 100vw; margin-left: calc(50% - 50vw); }

/* Endet die Seite mit einem randlosen Band, schliesst sie buendig ab: der
   Abstand der umgebenden Sektion wuerde sonst als weisser Streifen zwischen
   dem farbigen Band und dem Fussbereich stehen. Siehe BlockRenderer::endetRandlos(). */
.fw-blocks--randlos-unten { margin-bottom: 0 }
.page-section:has(.fw-blocks--randlos-unten),
.fw-imported:has(.fw-blocks--randlos-unten) { padding-bottom: 0 }
/* ❗️Und der Abstand ÜBER dem Fuss. Er kommt aus seite.css
   (.site-footer{margin-top:5rem}) und blieb nach dem Wegfall der anderen beiden
   als 80 px weisser Streifen stehen, am Desktop wie am Handy (#1820, gemessen). */
main:has(.fw-blocks--randlos-unten) ~ .site-footer { margin-top: 0 }
/* ✦ DIE SEITE ENDET AM RASTER, nicht nur nach einem randlosen Band (Ansage
   2026-10-05: „warum ist da unten eine Lücke, das endet doch perfekt am Ende
   des Rasters"). Die Regel oben griff nur, wenn der tiefste Block randlos war;
   endete die Seite mit einer Farbfläche im Raster oder mit Text, blieben die
   80 px aus seite.css stehen. In 2.0 bestimmt das Raster die Seite, also auch
   ihr Ende: wer unten Luft will, sieht sie im Raster (ein höherer Block oder
   ein Abstand-Block) und nicht als Rand, den man nirgends anfassen kann.
   Seiten ohne Raster (die eigene Seite eines Moduls) behalten ihren Abstand. */
main:has(.fw-blocks__grid) ~ .site-footer { margin-top: 0 }
main:has(.fw-blocks__grid) .fw-blocks { margin-bottom: 0 }
.page-section:has(.fw-blocks__grid),
.fw-imported:has(.fw-blocks__grid) { padding-bottom: 0 }

/* Text-Prose: erbt Theme-Typografie über .content/.prose; Grundabstand zähmen */
.fw-block__prose > :first-child { margin-top: 0; }
.fw-block__prose > :last-child  { margin-bottom: 0; }
/* Themes begrenzen .content.prose auf Lesebreite (z. B. max-width: 72ch).
   Im Raster bestimmt der BLOCK die Breite — ein vollbreiter Text+-Block
   soll wirklich von links nach rechts laufen. */
.fw-blocks .fw-block__prose.content.prose { max-width: none; margin-left: 0; margin-right: 0; }

/* Buttons füllen ihre Blockfläche (Breite × Höhe frei einstellbar) */
.fw-block--button .fw-block__inner { display: flex; }
.fw-block--button .fw-btn {
  flex: 1; display: inline-flex; align-items: center; justify-content: center;
  text-align: center; text-decoration: none; border-radius: 10px;
  background: var(--color-primary, #1e5693); color: #fff; font-weight: 600;
  padding: .6rem 1.2rem; transition: filter .15s ease, transform .15s ease;
}
.fw-block--button .fw-btn:hover { filter: brightness(1.08); transform: translateY(-1px); }
.fw-btn--secondary { background: #6b7280 !important; }
.fw-btn--outline {
  background: transparent !important;
  color: var(--color-primary-text, var(--color-primary, #1e5693)) !important;
  border: 2px solid var(--color-primary, #1e5693);
}
.fw-btn--s { font-size: .85rem; }
.fw-btn--l { font-size: 1.15rem; }

/* Spacer ist bewusst leer */
.fw-block--spacer .fw-block__inner { min-height: 100%; }

/* Video/Bild füllen die Blockfläche */
.fw-block--video .fw-block__inner,
.fw-block--image .fw-block__inner { height: 100%; }

/* ---- Mobile: Stapel in Leserichtung -------------------------------------- */
@media (max-width: 719.98px) {
  /* ❗️Eine Spalte in LESEFOLGE, nicht in Markup-Folge. Der Renderer gibt
     jedem Block seinen Platz mit (--fw-reihe, BlockRenderer::lesefolge);
     sonst stand eine Kette an der Stelle ihres Kopfs, also ein an eine
     Farbfläche gehängtes Modul vor dem Text auf dieser Fläche (2026-10-06).
     Flex statt Block, weil nur so `order` wirkt; die Blöcke haben nur einen
     Abstand nach unten, ein Zusammenfallen der Ränder fehlt also nicht.
     ❗️`gap: 0`: das Raster trägt `row-gap`. Im Block-Stapel war es wirkungslos,
     in der Flex-Spalte käme es zum Aussenabstand dazu (24 statt 12 px), und
     die Farbbänder, die nur die halbe Lücke überbrücken, rissen auf. */
  .fw-blocks__grid { display: flex; flex-direction: column; gap: 0; }
  /* `align-self: start` gilt im Raster der Höhe; in einer Flex-Spalte hiesse
     es „links, so schmal wie der Inhalt". Am Handy also strecken. */
  .fw-blocks__grid .fw-block { order: var(--fw-reihe, 0); align-self: stretch !important; }
  /* Sprungmarken hinter dem letzten Block bleiben am Ende. */
  .fw-blocks__grid > .fw-anchor { order: 2147483000; }
  /* ❗️Anker-Kette am Handy AUFLÖSEN. Bliebe die Hülle ein Grid, während ihr
     Elternteil `display:block` ist, wäre `subgrid` ungültig (kein Grid-Vater)
     und die inneren `grid-column: 6 / span 3` erzeugten IMPLIZITE Spalten —
     die Kette stünde quer neben der Seite. Mit `display: contents` werden die
     Glieder selbst Teil der Spalte und stehen an ihrem Platz in der
     Lesefolge (--fw-reihe), nicht gesammelt an der Stelle des Kopfs.
     `!important`, weil die Angaben inline am Element stehen. */
  .fw-kette { display: contents; }
  .fw-kette > .fw-block { grid-column: auto !important; grid-row: auto !important;
                          min-height: 0 !important; }
  .fw-blocks__grid > .fw-block,
  .fw-kette > .fw-block { margin-bottom: var(--bg-gap, 12px); }
  .fw-blocks__grid > .fw-block:last-child,
  .fw-blocks__grid > :last-child > .fw-block:last-child { margin-bottom: 0; }
  .fw-block--hide-mobile { display: none !important; }

  /* Feste Block-Höhen loslassen — Inhalt bestimmt die Höhe */
  .fw-block--image .fw-block__inner,
  .fw-block--video .fw-block__inner { height: auto; }
  /* Sandbox-HTML meldet seine Inhaltshöhe per postMessage und wächst exakt mit
     (auch auf Mobile) — nur eine Mindesthöhe als Fallback, bis die Messung da ist.
     KEINE feste Höhe/!important, sonst überschriebe es die gemeldete Höhe. */
  .fw-html-sandbox { min-height: 200px; }
  .fw-block--image img { height: auto !important; max-height: 70vh; object-fit: cover; }
  .fw-block--video iframe, .fw-block--video video { aspect-ratio: 16 / 9; height: auto !important; }
  .fw-block--spacer { display: none; } /* leere Abstände stapeln sich nicht sinnvoll */

  /* ❗️FARBIGE BÄNDER (#1820). Am Desktop liegt ein Band als leere Fläche
     UNTER seinem Inhalt, beide auf denselben Rasterzeilen. Im Stapel stand die
     Fläche allein und 0 px hoch da, und helle Schrift, die für den dunklen
     Grund gedacht war, stand auf Weiss. Der Renderer gibt jedem Block, der
     ganz auf einem Band liegt, dessen Farbe mit (--fw-band, siehe
     BlockRenderer::handyBaender); hier malt jeder dieser Blöcke den Grund über
     die volle Breite hinter sich, samt der halben Lücke zu seinen Nachbarn.
     So entsteht wieder EIN durchgehender Streifen. Die leere Fläche selbst
     fällt weg, sie hätte nur einen Abstand ohne Inhalt beigetragen. */
  .fw-blocks__grid > .fw-block--band { display: none; }
  /* Dasselbe für eine Fläche, die Kopf einer Kette ist. Seit die Kette am
     Handy aufgelöst wird (display: contents), stand sie dort sonst als
     leerer dunkler Streifen über ihrem eigenen Inhalt. */
  .fw-kette > .fw-block--band { display: none; }
  /* flow-root (#1941): ohne eigenen Formatierungskontext fiel der Aussenabstand
     des ersten/letzten Kindes (etwa ein Modul-Block mit margin am <section>)
     DURCH den Block hindurch. Die Luecke wurde 19 statt 12 px, der Streifen
     unten deckt aber nur die halbe Luecke; der Rest blieb als heller Strich
     in der Seitenfarbe stehen. So bleibt der Abstand im Block, auf dem Band. */
  .fw-block--aufband { isolation: isolate; display: flow-root; }
  .fw-block--aufband::before {
    content: ""; position: absolute; z-index: -1; pointer-events: none;
    left: 50%; width: 100vw; transform: translateX(-50%);
    top: calc(var(--bg-gap, 12px) / -2); bottom: calc(var(--bg-gap, 12px) / -2);
    background: var(--fw-band); opacity: var(--fw-band-deck, 1);
  }
  /* Innenabstand des Bandes oben und unten, statt der Rasterzeilen Luft. */
  .fw-block--band-erst { padding-top: 32px; }
  .fw-block--band-erst::before { top: 0; }
  .fw-block--band-letzt { padding-bottom: 32px; }
  .fw-block--band-letzt::before { bottom: 0; }
  .fw-block--band-anschluss::before { top: calc(var(--bg-gap, 12px) * -1); }
  .fw-block--button .fw-btn { padding: .9rem 1.2rem; }
}

/* ---- Desktop/PC: einzelne Blöcke ausblenden (Gegenstück zu hide-mobile) ---- */
@media (min-width: 720px) {
  .fw-block--hide-desktop { display: none !important; }
}

/* ==========================================================================
   Block-Animationen (Tab „Animation" im Editor)
   Einschweben nutzt die vorhandene Scroll-Reveal-Runtime (fw-animate--…).
   ========================================================================== */

/* Hover-Effekte */
.fw-hov { transition: transform .25s ease, box-shadow .25s ease, opacity .25s ease, filter .25s ease; }
.fw-hov--lift:hover   { transform: translateY(-8px); box-shadow: 0 14px 30px rgba(0,0,0,.16); }
.fw-hov--grow:hover   { transform: scale(1.05); }
.fw-hov--shrink:hover { transform: scale(.95); }
.fw-hov--glow:hover   { box-shadow: 0 0 22px 4px var(--fw-hov-col, rgba(37,99,235,.55)); }
.fw-hov--rotate:hover { transform: rotate(3deg) scale(1.02); }
.fw-hov--fade:hover   { opacity: .55; }
.fw-hov--color .fw-block__inner { transition: background-color .25s ease, color .25s ease; }
.fw-hov--color:hover .fw-block__inner { background-color: var(--fw-hov-col, #2563eb); color: #fff; border-radius: 10px; }
.fw-hov--color:hover .fw-block__inner * { color: inherit; }

/* Dauerschleifen */
@keyframes fwPulse  { 0%,100% { transform: scale(1); } 50% { transform: scale(1.05); } }
@keyframes fwFloat  { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }
@keyframes fwSpin   { to { transform: rotate(360deg); } }
@keyframes fwBlink  { 0%,100% { opacity: 1; } 50% { opacity: .25; } }
@keyframes fwGrad   { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } }
.fw-loop--pulse  { animation: fwPulse 2.2s ease-in-out infinite; }
.fw-loop--float  { animation: fwFloat 3.2s ease-in-out infinite; }
.fw-loop--spin   { animation: fwSpin 6s linear infinite; }
.fw-loop--blink  { animation: fwBlink 1.6s ease-in-out infinite; }
.fw-loop--gradient > .fw-block__inner,
.fw-loop--gradient > :first-child {
  background-image: linear-gradient(120deg, var(--fw-grad-a, #ff7eb3), var(--fw-grad-b, #65d6ce), var(--fw-grad-a, #ff7eb3));
  background-size: 220% 220%;
  animation: fwGrad 5s ease infinite;
  border-radius: 10px;
}

/* Zeitgesteuertes Ausblenden (data-fw-hide-after, Mini-Runtime im Renderer) */
[data-fw-hide-after] { transition: opacity .6s ease, transform .6s ease; }
.fw-block--hidden { opacity: 0 !important; transform: scale(.96); pointer-events: none; }

/* Reduzierte Bewegung respektieren */
@media (prefers-reduced-motion: reduce) {
  .fw-block--button .fw-btn { transition: none; }
  .fw-loop--pulse, .fw-loop--float, .fw-loop--spin, .fw-loop--blink,
  .fw-loop--gradient > .fw-block__inner { animation: none; }
  .fw-hov, .fw-hov--color .fw-block__inner { transition: none; }
}

/* ✦ AUSRICHTUNG EINES MODUL-BAUSTEINS (settings.align am Kürzel-Block,
   Ansage 2026-10-06: „ich will das auch zentriert oder rechts anordnen
   können"). Gerückt wird, was um den Inhalt herum steht: Überschrift, Satz,
   Knöpfe, Abzeichen und Kästen mit eigener Breite.
   ❗️Karten, Listeneinträge, Aufklapper, Tabellen und Formulare behalten
      ihre eigene Ausrichtung. Zentrierter Fliesstext in einer Karte und
      zentrierte Beschriftungen über Eingabefeldern lesen sich schlechter.
   ❗️Als Ganzes gerückt wird nur die OBERSTE Ebene des Moduls. Eine Ebene
      tiefer sitzen oft Flex-Kinder (Rechner: Formular und Preis), und dort
      verschöben automatische Ränder den Aufbau. */
.fw-block--ausrichten-center > .fw-block__inner { text-align: center; }
.fw-block--ausrichten-right > .fw-block__inner { text-align: right; }
:is(.fw-block--ausrichten-center, .fw-block--ausrichten-right)
  :is(article, li, details, table, form, [class*="card"]) { text-align: start; }
.fw-block--ausrichten-center > .fw-block__inner > * { margin-inline: auto; }
.fw-block--ausrichten-right > .fw-block__inner > * { margin-inline: auto 0; }
/* Kopfzeilen aus Titel und „Alle …"-Link sind Flex-Reihen, ebenso die
   Kontakt-Knöpfe und das Siegel-Band: dort richtet justify-content. */
.fw-block--ausrichten-center :is([class$="-block__head"], .fw-cbar-reihe, .certs-band__row) { justify-content: center; }
.fw-block--ausrichten-right :is([class$="-block__head"], .fw-cbar-reihe, .certs-band__row) { justify-content: flex-end; }
