Bildstapel-Intro (Stapel flippt durch und verteilt sich ins Layout)
Sechs Studien-Deckel einer Würzburger Kanzlei flackern als Stapel durch und verteilen sich per Flip ins Insights-Raster, zur Hero oder an den runden Tisch.
In der Bildschirmmitte liegt ein kleiner Stapel Bilder in Karten- oder Polaroidgröße. Die Bilder wechseln schnell hintereinander wie ein Daumenkino. Das ist die Ladephase. Danach löst sich der Stapel auf: Die Bilder fliegen per Flip an ihre Plätze im Raster, ordnen sich im Kreis an, oder ein Bild wächst zur Hero, während die anderen das Bild verlassen. Zuletzt erscheinen Headline und Navigation.
In zwei Sekunden sieht man die Bandbreite der Arbeit, und das Intro mündet direkt in die Navigation. Loader und Inhalt sind dasselbe Material. Deshalb fühlt sich nichts wie Warten an.
Wann einsetzen
Bei Foto-, Design- und Architektur-Portfolios und überall, wo die Startseite ein Bild-Raster hat. Auch bei inhaltsgetriebenen Seiten, deren Publikationen eigene Deckel haben (Studien, Magazine, Berichte).
Wann nicht
Bei Seiten ohne starkes Bildmaterial. Und wenn das Intro bei jedem Besuch erneut läuft: dann nur einmal pro Sitzung zeigen.
Varianten
- Stapel wird zum Raster (Flip)
- Stapel wird zum Kreis (Codrops 2024)
- Stapel wird zur Hero: ein Bild wächst, die anderen verlassen nach oben und unten das Bild (Bisous)
- Hover-Motion-Grid mit Intro (Codrops 2024)
- Image-Trail als Intro (Codrops 2022)
Umsetzung
Die Bilder stehen im finalen Layout im DOM. Zum Start in einen zentrierten Stapel-Container hängen (übereinander, absolut). Flackern: eine gsap.timeline mit zwölf Aufrufen im Abstand von 2/12 s, die jeweils zIndex und autoAlpha des nächsten Bildes setzen. Auflösen: const state = Flip.getState(bilder); Bilder zurück an ihre Plätze hängen; Flip.from(state, { absolute: true, duration: 1, ease: 'expo.out', stagger: i => Math.floor(i / 2) * 0.05 }). Innenbild dabei von scale 1.5 auf 1. Variante Hero: das eine Bild mit 1.8 s expo.inOut wachsen lassen, die übrigen abwechselnd um ±Index × Viewporthöhe verschieben (1 s expo.out). Vorher die Bilder dekodieren: Promise.all(imgs.map(i => i.decode())) mit Timeout als Rückfall. Fallstrick: Ist ein Bild LCP-Kandidat, darf es nicht unsichtbar warten. Ein Bild des Stapels sofort sichtbar lassen.
Robust umsetzen
Telefon. Kleinere Bildvarianten per srcset. Den Stapel auf etwa halbe Bildschirmbreite setzen und in eine oder zwei Spalten oder in eine Hero auflösen.
Ohne Bewegung. Kein Flackern, kein Stapel. Das Layout ist sofort da, höchstens mit kurzem Fade (250 ms).
Barrierefrei. Das Flackern ist ein Blitz-Risiko (WCAG 2.3.1). Der gemessene Takt von rund 167 ms liegt über drei Wechseln pro Sekunde. Das ist nur vertretbar, wenn die flackernde Fläche klein bleibt (WCAG-Richtwert: kleiner als 341 × 256 px bei 1024 × 768). Sonst langsamer takten oder weich überblenden. Überspringen per Klick und Taste anbieten. Während des Intros den Inhalt mit aria-busy markieren und den Stapel per aria-hidden ausblenden.
Code
<!DOCTYPE html>
<!--
Bildstapel-Intro (Stapel flippt durch und verteilt sich ins Layout)
Fundus · Preloader & Intro · https://cecodesign.de/lab/fundus/preloader-intro/bildstapel-intro/
Eigenständige Datei. Bilder liegen hier unter bilder/ – eigene einsetzen.
-->
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bildstapel-Intro · Fundus-Demo</title>
<script>document.documentElement.classList.add('js');if(matchMedia('(prefers-reduced-motion: reduce)').matches)document.documentElement.classList.add('reduziert')</script>
<style>
@font-face { font-family: 'Newsreader'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/newsreader:vf@latest/latin-opsz-normal.woff2') format('woff2-variations'); font-weight: 200 800; font-style: normal; font-display: swap; }
@font-face { font-family: 'Newsreader'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/newsreader:vf@latest/latin-opsz-italic.woff2') format('woff2-variations'); font-weight: 200 800; font-style: italic; font-display: swap; }
@font-face { font-family: 'Schibsted Grotesk'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/schibsted-grotesk:vf@latest/latin-wght-normal.woff2') format('woff2-variations'); font-weight: 400 900; font-style: normal; font-display: swap; }
@font-face { font-family: 'Geist Mono'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/geist-mono:vf@latest/latin-wght-normal.woff2') format('woff2-variations'); font-weight: 100 900; font-display: swap; }
/* Seubert Kilger, Rechtsanwälte und Steuerberater, Würzburg · Rezept „Kanzlei & Beratung“:
Newsreader nur für Überschriften und Deckeltitel, Schibsted Grotesk 400/500 für alles andere,
Nachtblau als einziger Markenton auf warmen Graus, Cyan nur für Fokus und Links. */
:root {
--grund: #f9f8f8; --flaeche: #efebeb; --linie: #d2cdc7; --marke: #1e1e50; --text: #212529; --meta: #736458; --akzent: #00bee6;
--kurve: cubic-bezier(0.16, 1, 0.3, 1); /* expo.out, Messwert Verteilen */
--ui: cubic-bezier(0.4, 0, 0.22, 1); /* Rezept-Kurve für Bedienelemente */
--pult: 58px;
--gx: clamp(20px, 3.2vw, 48px);
}
* { box-sizing: border-box; margin: 0; }
html { background: var(--grund); color: var(--text); font-family: 'Schibsted Grotesk', system-ui, sans-serif; font-size: 16px; -webkit-font-smoothing: antialiased; }
html:has(.buehne[data-zustand='laden']), html:has(.buehne[data-zustand='uebergabe']) { overflow: hidden; }
a { color: inherit; text-decoration: none; }
a:focus-visible, button:focus-visible { outline: 2px solid var(--akzent); outline-offset: 3px; }
.mono { font: 400 11px/1.45 'Geist Mono', ui-monospace, monospace; letter-spacing: .14em; text-transform: uppercase; color: var(--meta); }
.meta { font-size: .8125rem; line-height: 1.4; color: var(--meta); font-variant-numeric: tabular-nums; }
.serif { font-family: 'Newsreader', Georgia, serif; font-weight: 400; }
/* ── Bühne ── */
.buehne { position: relative; height: calc(100svh - var(--pult)); min-height: 560px; display: grid; grid-template-rows: auto minmax(0, 1fr); }
.buehne.blende { animation: einblenden 250ms linear both; }
@keyframes einblenden { from { opacity: 0; } }
.kopf { display: flex; align-items: center; justify-content: space-between; gap: 24px; padding: 18px var(--gx); border-bottom: 1px solid var(--linie); }
.marke { display: grid; gap: 3px; color: var(--marke); }
.marke b { font: 400 24px/1 'Newsreader', Georgia, serif; letter-spacing: -.01em; }
.marke span { font-size: 11px; line-height: 1; letter-spacing: .04em; color: var(--meta); }
.kopf nav ul { display: flex; gap: clamp(18px, 2.2vw, 34px); list-style: none; padding: 0; font-size: 15px; font-weight: 500; }
.kopf nav a { color: var(--text); background: linear-gradient(currentColor 0 0) 0 100% / 0 1px no-repeat; padding-bottom: 3px; transition: background-size 125ms var(--ui); }
.kopf nav a:hover, .kopf nav a[aria-current] { background-size: 100% 1px; }
.kopf nav a[aria-current] { color: var(--marke); }
.portal { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 500; color: var(--marke); border: 1px solid var(--marke); padding: 9px 14px; transition: background 125ms var(--ui), color 125ms var(--ui); }
.portal:hover { background: var(--marke); color: var(--grund); }
.portal svg { width: 12px; height: 12px; }
.menue { display: none; font-size: 15px; font-weight: 500; }
#inhalt { display: grid; min-height: 0; }
.ansicht { display: none; min-height: 0; }
.buehne[data-variante='raster'] .a-raster, .buehne[data-variante='held'] .a-held, .buehne[data-variante='kreis'] .a-kreis { display: grid; }
h1, h2 { font-family: 'Newsreader', Georgia, serif; font-weight: 400; color: var(--marke); letter-spacing: -.01em; text-wrap: balance; }
h1 { font-size: clamp(2rem, 1.3rem + 2.6vw, 3.5rem); line-height: 1.1; }
h1 i { font-style: italic; }
.lead { font-size: 1.0625rem; line-height: 1.6; max-width: 46ch; text-wrap: pretty; }
.augenbraue { display: flex; gap: 6px 18px; flex-wrap: wrap; font-size: .8125rem; font-weight: 500; color: var(--meta); font-variant-numeric: tabular-nums; }
.augenbraue span + span::before { content: ''; display: inline-block; width: 18px; height: 1px; background: var(--linie); vertical-align: middle; margin-right: 18px; }
.mehr { justify-self: start; font-size: 15px; font-weight: 500; color: var(--marke); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 5px; text-decoration-color: var(--linie); transition: text-decoration-color 125ms var(--ui); }
.mehr:hover { text-decoration-color: currentColor; }
/* Ansicht 1: Insights-Raster */
.a-raster { grid-template-rows: auto minmax(0, 1fr); gap: clamp(20px, 3.4vh, 40px); padding: clamp(24px, 4.4vh, 52px) var(--gx) clamp(18px, 3vh, 32px); }
.a-raster .oben { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 20px clamp(32px, 5vw, 80px); align-items: end; }
.a-raster .oben > div { display: grid; gap: 16px; }
.a-raster .rechts { gap: 14px; padding-bottom: 6px; }
.raster { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 0 clamp(12px, 1.4vw, 22px); align-content: end; list-style: none; padding: 0; }
.raster li { display: grid; gap: 12px; align-content: start; }
.fach { aspect-ratio: 4 / 5; position: relative; }
.raster figcaption { display: grid; gap: 4px; padding-top: 10px; border-top: 1px solid var(--linie); }
.raster figcaption b { font-size: 14.5px; line-height: 1.35; font-weight: 500; color: var(--text); text-wrap: pretty; }
.raster li:hover figcaption b { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.raster figure { display: grid; gap: 12px; }
/* Ansicht 2: Studie als Hero */
.a-held { grid-template-columns: minmax(0, 1fr) auto; gap: clamp(32px, 5vw, 80px); padding: clamp(24px, 4.4vh, 52px) var(--gx) clamp(18px, 3vh, 32px); }
.a-held .text { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: 24px; }
.a-held .kern { align-self: center; display: grid; gap: 20px; }
.a-held h1 { font-size: clamp(2.25rem, 1.3rem + 3.2vw, 4rem); line-height: 1.05; }
.weitere { list-style: none; padding: 0; border-top: 1px solid var(--linie); }
.weitere li { display: grid; grid-template-columns: 7.5em 9em minmax(0, 1fr); gap: 16px; padding: 11px 0; border-bottom: 1px solid var(--linie); font-size: 14.5px; line-height: 1.35; align-items: baseline; }
.weitere li span { color: var(--meta); font-size: .8125rem; font-variant-numeric: tabular-nums; }
.weitere li b { font-weight: 500; }
.heldfach { height: 100%; aspect-ratio: 4 / 5; position: relative; justify-self: end; }
/* Ansicht 3: runder Tisch */
.a-kreis { position: relative; place-items: center; padding: clamp(24px, 4vh, 48px) var(--gx); }
.ring { position: absolute; inset: clamp(24px, 4vh, 48px) var(--gx); list-style: none; padding: 0; --kw: clamp(84px, min(10vw, 16vh), 168px); }
.ring li { position: absolute; width: var(--kw); aspect-ratio: 4 / 5; left: calc(50% + 41% * cos(var(--w))); top: calc(50% + 37% * sin(var(--w))); translate: -50% -50%; }
.ring li:nth-child(1) { --w: -60deg; } .ring li:nth-child(2) { --w: 0deg; } .ring li:nth-child(3) { --w: 60deg; }
.ring li:nth-child(4) { --w: 120deg; } .ring li:nth-child(5) { --w: 180deg; } .ring li:nth-child(6) { --w: 240deg; }
.mitte { position: relative; display: grid; gap: 18px; justify-items: center; text-align: center; max-width: 30rem; }
.mitte .lead { max-width: 40ch; }
.mitte .mehr { justify-self: center; }
/* ── Deckel: Mandantenbriefe, Studien, Leitfäden ── */
.akte { position: relative; width: 100%; height: 100%; overflow: hidden; container-type: inline-size; background: var(--d-grund); color: var(--d-text); transition: box-shadow 600ms var(--kurve); }
.d-innen { position: absolute; inset: 0; display: grid; grid-template-rows: auto minmax(0, 1fr) auto auto; padding: 7cqi 7cqi 6cqi; }
.akte[data-ton='nacht'] { --d-grund: var(--marke); --d-text: #f9f8f8; --d-meta: rgba(249, 248, 248, .62); --d-strich: rgba(249, 248, 248, .58); }
.akte[data-ton='hell'] { --d-grund: #fcfbfb; --d-text: var(--marke); --d-meta: var(--meta); --d-strich: rgba(30, 30, 80, .72); box-shadow: inset 0 0 0 1px var(--linie); }
.akte[data-ton='stein'] { --d-grund: var(--linie); --d-text: var(--marke); --d-meta: rgba(30, 30, 80, .62); --d-strich: rgba(30, 30, 80, .62); }
.akte[data-ton='sand'] { --d-grund: var(--flaeche); --d-text: var(--marke); --d-meta: var(--meta); --d-strich: var(--meta); }
/* Maske hält Kopf- und Titelzone frei, auch wenn das Innenbild im Stapel auf 1,5 vergrößert ist */
.motiv { position: absolute; inset: 0; color: var(--d-strich); -webkit-mask-image: linear-gradient(transparent 10.5%, #000 13.5%, #000 60%, transparent 66%); mask-image: linear-gradient(transparent 10.5%, #000 13.5%, #000 60%, transparent 66%); }
.motiv svg { width: 100%; height: 100%; display: block; transform-origin: 50% 40%; }
.d-kopf, .d-fuss { position: relative; display: flex; justify-content: space-between; gap: 4cqi; font-size: clamp(6px, 4.4cqi, 14px); line-height: 1.2; font-weight: 500; letter-spacing: .06em; text-transform: uppercase; color: var(--d-meta); font-variant-numeric: tabular-nums; }
.d-titel { position: relative; grid-row: 3; font: 400 10.6cqi/1.04 'Newsreader', Georgia, serif; letter-spacing: -.01em; color: var(--d-text); margin-bottom: 6cqi; text-wrap: balance; hyphens: manual; }
.d-titel i { font-style: italic; }
.d-fuss { grid-row: 4; padding-top: 3.4cqi; border-top: 1px solid color-mix(in srgb, var(--d-meta) 40%, transparent); letter-spacing: .02em; text-transform: none; }
/* ── Vorspann: Stapel, Marke, Zähler ── */
.vorspann { display: none; position: absolute; top: 0; left: 0; right: 0; height: min(100%, 100svh); z-index: 10; grid-template-rows: minmax(0, 1fr) auto auto auto minmax(0, 1fr); justify-items: center; gap: 22px; padding: 24px; cursor: pointer; }
.buehne[data-zustand='laden'] .vorspann, .buehne[data-zustand='uebergabe'] .vorspann { display: grid; }
.buehne[data-zustand='uebergabe'] .vorspann { pointer-events: none; }
.v-marke { grid-row: 2; font: 400 clamp(26px, 2.4vw, 34px)/1 'Newsreader', Georgia, serif; color: var(--marke); letter-spacing: -.01em; white-space: pre; }
.v-marke span { display: inline-block; }
.stapel { grid-row: 3; position: relative; width: clamp(150px, 15vw, 224px); aspect-ratio: 4 / 5; }
.stapel .akte { position: absolute; inset: 0; box-shadow: 0 1px 2px rgba(30, 30, 80, .1), 0 14px 26px -20px rgba(30, 30, 80, .34); }
.stapel .akte[data-ton='hell'] { box-shadow: inset 0 0 0 1px var(--linie), 0 14px 26px -20px rgba(30, 30, 80, .34); }
.v-zeile { grid-row: 4; display: flex; gap: 20px; align-items: baseline; font-variant-numeric: tabular-nums; }
.v-zeile b { color: var(--marke); font-weight: 400; }
.ueberspringen { position: absolute; bottom: 22px; left: 50%; translate: -50% 0; font: inherit; font-size: 13px; font-weight: 500; color: var(--meta); background: none; border: 0; padding: 8px 10px; cursor: pointer; transition: color 125ms var(--ui); }
.ueberspringen:hover { color: var(--marke); }
.ueberspringen kbd { font: 400 10px/1 'Geist Mono', monospace; letter-spacing: .08em; border: 1px solid var(--linie); padding: 3px 5px; margin-left: 6px; }
.ablage { display: none; }
/* ── Pult: Varianten und Werte ── */
.pult { height: var(--pult); display: flex; align-items: center; justify-content: space-between; gap: 10px 28px; white-space: nowrap; padding: 0 var(--gx); border-top: 1px solid var(--linie); }
.modi { display: flex; gap: 4px; flex-wrap: wrap; align-items: center; flex-shrink: 0; }
.modi > span { margin-right: 8px; }
.modi button { font: inherit; letter-spacing: inherit; text-transform: inherit; color: var(--meta); background: none; border: 1px solid var(--linie); border-radius: 2px; height: 28px; padding: 0 11px; cursor: pointer; transition: background 150ms var(--ui), color 150ms var(--ui), border-color 150ms var(--ui); }
.modi button:hover { color: var(--marke); border-color: var(--meta); }
.modi button[aria-pressed='true'] { background: var(--marke); color: var(--grund); border-color: var(--marke); }
.modi .nochmal { border-color: transparent; }
.werte { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 2px 14px; font-size: 10px; min-width: 0; }
.werte b { color: var(--marke); font-weight: 400; }
/* Reduzierte Bewegung: kein Stapel, kein Flackern, Layout steht nach 250 ms Fade */
.reduziert .vorspann { display: none !important; }
.reduziert .akte, .reduziert .modi button, .reduziert .kopf nav a, .reduziert .portal, .reduziert .mehr { transition: none; }
/* Vorschau: nur die Bühne */
.vorschau body { overflow: hidden; }
.vorschau .pult, .vorschau .ueberspringen { display: none; }
html.vorschau { --pult: 0px; }
@media (max-width: 1240px) {
:root { --pult: 86px; }
.pult { flex-direction: column; align-items: flex-start; justify-content: center; gap: 8px; }
.werte { justify-content: flex-start; }
.kopf nav li:nth-child(n+5) { display: none; }
}
@media (max-width: 1080px) {
.raster figcaption b { font-size: 13px; }
.weitere li { grid-template-columns: 6.5em minmax(0, 1fr); }
.weitere li span:nth-child(2) { display: none; }
}
@media (max-width: 860px) {
.kopf nav { display: none; }
.menue { display: inline; }
.portal { display: none; }
}
@media (max-width: 760px) {
.buehne { height: auto; min-height: 100svh; grid-template-rows: auto minmax(0, 1fr); }
.a-raster .oben { grid-template-columns: 1fr; }
.raster { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 26px 14px; }
.a-held { grid-template-columns: 1fr; gap: 28px; }
.a-held .text { display: contents; }
.a-held .kern { order: 1; }
.heldfach { order: 2; height: auto; width: 100%; }
.a-held .weitere { order: 3; }
.a-kreis { place-items: stretch; gap: 28px; }
.ring { position: relative; inset: auto; aspect-ratio: 1; order: 2; --kw: 23vw; }
.ring li { left: calc(50% + 37% * cos(var(--w))); top: calc(50% + 37% * sin(var(--w))); }
.mitte { order: 1; padding-top: 8px; }
.stapel { width: 46vw; }
.pult { height: auto; padding-top: 12px; padding-bottom: 14px; }
.werte { display: none; }
}
@media (hover: none) {
.modi button:hover { color: var(--meta); border-color: var(--linie); }
.modi button[aria-pressed='true']:hover { color: var(--grund); border-color: var(--marke); }
.kopf nav a:hover:not([aria-current]) { background-size: 0 1px; }
.raster li:hover figcaption b { text-decoration: none; }
.ueberspringen { padding: 12px 14px; }
.ueberspringen kbd { display: none; }
}
@media (forced-colors: active) { button, [role=button], [role=tab], [role=switch] { border: 1px solid ButtonText !important; } }
</style>
</head>
<body>
<div class="buehne" data-zustand="fertig" data-variante="raster">
<header class="kopf">
<a class="marke" href="#" data-ein><b>Seubert Kilger</b><span>Rechtsanwälte · Steuerberater · Würzburg</span></a>
<nav aria-label="Hauptnavigation" data-ein>
<ul>
<li><a href="#">Leistungen</a></li>
<li><a href="#">Branchen</a></li>
<li><a href="#">Köpfe</a></li>
<li><a href="#" aria-current="page">Insights</a></li>
<li><a href="#">Karriere</a></li>
<li><a href="#">Kontakt</a></li>
</ul>
</nav>
<a class="portal" href="#" data-ein>Mandantenportal <svg viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.3" aria-hidden="true"><path d="M3 9 9 3M4 3h5v5"/></svg></a>
<span class="menue" data-ein>Menü</span>
</header>
<main id="inhalt">
<!-- Ansicht 1: Stapel wird zum Raster -->
<section class="ansicht a-raster" aria-labelledby="t-raster">
<div class="oben">
<div>
<p class="augenbraue" data-ein><span>Insights</span><span>Herbst 2026</span></p>
<h1 id="t-raster" data-ein>Was Unternehmen in Mainfranken jetzt <i>wissen</i> sollten.</h1>
</div>
<div class="rechts">
<p class="lead" data-ein>Studien, Mandantenbriefe und Checklisten aus unserer Praxis. Geschrieben von den Anwältinnen und Steuerberatern, die Ihre Fragen auch im Mandat beantworten.</p>
<a class="mehr" href="#" data-ein>Alle Beiträge und Newsletter</a>
</div>
</div>
<ol class="raster">
<li><figure><div class="fach" data-platz="raster"></div><figcaption data-ein><span class="meta">Studie · 28.10.2026</span><b>Unternehmensnachfolge in Mainfranken: Wer übergibt, wer übernimmt?</b></figcaption></figure></li>
<li><figure><div class="fach" data-platz="raster"></div><figcaption data-ein><span class="meta">Mandantenbrief · 21.10.2026</span><b>Erbschaftsteuer im Familienunternehmen: Verschonung richtig planen</b></figcaption></figure></li>
<li><figure><div class="fach" data-platz="raster"></div><figcaption data-ein><span class="meta">Briefing · 14.10.2026</span><b>Arbeitszeiterfassung: Was der Mittelstand dokumentieren muss</b></figcaption></figure></li>
<li><figure><div class="fach" data-platz="raster"></div><figcaption data-ein><span class="meta">Checkliste · 07.10.2026</span><b>E-Rechnung: Ausstellungspflicht ab 1. Januar 2027</b></figcaption></figure></li>
<li><figure><div class="fach" data-platz="raster"></div><figcaption data-ein><span class="meta">Leitfaden · 30.09.2026</span><b>Hofübergabe im Weinbau: Pacht, Steuern, Pflichtteil</b></figcaption></figure></li>
<li><figure><div class="fach" data-platz="raster"></div><figcaption data-ein><span class="meta">Insight · 23.09.2026</span><b>Hinweisgeberschutz: die Meldestelle im kleinen Betrieb</b></figcaption></figure></li>
</ol>
</section>
<!-- Ansicht 2: ein Deckel wächst zur Hero -->
<section class="ansicht a-held" aria-labelledby="t-held">
<div class="text">
<p class="augenbraue" data-ein><span>Studie 2026</span><span>Erschienen am 28.10.2026</span></p>
<div class="kern">
<h1 id="t-held" data-ein>Wer übernimmt? <i>Nachfolge</i> im Mittelstand Mainfrankens.</h1>
<p class="lead" data-ein>Wir haben mit Inhaberinnen und Inhabern aus Handwerk, Weinbau und Industrie gesprochen. Über Zeitpläne, Familie, Steuern und die Frage, wann man loslässt.</p>
<a class="mehr" href="#" data-ein>Studie lesen · PDF, 48 Seiten</a>
</div>
<ul class="weitere" data-ein>
<li><span>21.10.2026</span><span>Mandantenbrief</span><b>Erbschaftsteuer im Familienunternehmen</b></li>
<li><span>14.10.2026</span><span>Briefing</span><b>Arbeitszeiterfassung im Mittelstand</b></li>
<li><span>07.10.2026</span><span>Checkliste</span><b>E-Rechnung ab 1. Januar 2027</b></li>
</ul>
</div>
<div class="heldfach" data-platz="held"></div>
</section>
<!-- Ansicht 3: Stapel wird zum Kreis, der runde Tisch -->
<section class="ansicht a-kreis" aria-labelledby="t-kreis">
<ol class="ring">
<li data-platz="kreis"></li><li data-platz="kreis"></li><li data-platz="kreis"></li>
<li data-platz="kreis"></li><li data-platz="kreis"></li><li data-platz="kreis"></li>
</ol>
<div class="mitte">
<p class="augenbraue" data-ein><span>Recht</span><span>Steuern</span><span>Seit 1994</span></p>
<h1 id="t-kreis" data-ein>Recht und Steuern an <i>einem</i> Tisch.</h1>
<p class="lead" data-ein>Anwälte und Steuerberater arbeiten bei uns am selben Mandat. Sie haben einen Ansprechpartner und eine Akte.</p>
<a class="mehr" href="#" data-ein>Erstgespräch vereinbaren</a>
</div>
</section>
</main>
<div class="vorspann" aria-hidden="true">
<p class="v-marke">Seubert Kilger</p>
<div class="stapel"></div>
<p class="v-zeile mono"><span>Insights 2026</span><b data-zaehler>01 / 06</b></p>
<button type="button" class="ueberspringen" tabindex="-1">Intro überspringen<kbd>Esc</kbd></button>
</div>
<div class="ablage"></div>
<!-- Die sechs Deckel: im HTML in den Raster-Fächern, das Skript legt sie zum Stapel zusammen -->
<template id="deckel">
<article class="akte" data-ton="nacht" aria-label="Studie 2026: Unternehmensnachfolge in Mainfranken">
<div class="motiv" aria-hidden="true"><svg viewBox="0 0 400 500" preserveAspectRatio="xMidYMid slice" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round">
<!-- Marienberg über dem Main, davor die Alte Mainbrücke -->
<g transform="translate(30 -14) scale(.85)">
<path d="M-10 214 C 60 196 110 162 170 156 S 280 168 330 196 S 390 214 410 214"/>
<path d="M150 158 V134 H170 V124 H198 V112 H210 V124 H236 V136 H258 V166" />
<path d="M198 112 Q204 98 210 112 M176 134 V158 M226 136 V160 M186 144 h6 M214 146 h6 M240 148 h6"/>
<path d="M-10 246 H410 M-10 254 H410"/>
<path d="M2 300 A36 36 0 0 1 74 300 M86 300 A36 36 0 0 1 158 300 M170 300 A36 36 0 0 1 242 300 M254 300 A36 36 0 0 1 326 300 M338 300 A36 36 0 0 1 410 300"/>
<path d="M80 254 V300 M164 254 V300 M248 254 V300 M332 254 V300"/>
<path d="M80 246 V230 M164 246 V228 M248 246 V230 M332 246 V229"/>
<circle cx="80" cy="226" r="3.5"/><circle cx="164" cy="224" r="3.5"/><circle cx="248" cy="226" r="3.5"/><circle cx="332" cy="225" r="3.5"/>
</g></svg></div>
<div class="d-innen"><p class="d-kopf"><span>Studie</span><span>2026</span></p>
<p class="d-titel">Unternehmens­nachfolge in <i>Mainfranken</i></p>
<p class="d-fuss"><span>Seubert Kilger</span><span>Nr. 14</span></p></div>
</article>
<article class="akte" data-ton="hell" aria-label="Mandantenbrief: Erbschaftsteuer im Familienunternehmen">
<div class="motiv" aria-hidden="true"><svg viewBox="0 0 400 500" preserveAspectRatio="xMidYMid slice" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round">
<!-- barocke Fassade mit Mittelrisalit -->
<g transform="translate(0 -46)">
<path d="M30 300 H370 M30 296 H370 M40 204 H360 M40 296 V204 M360 296 V204"/>
<path d="M150 204 V170 H250 V204 M144 170 H256 M150 170 L200 138 L250 170"/>
<circle cx="200" cy="158" r="7"/>
<path d="M40 204 L56 190 H344 L360 204"/>
<path d="M188 296 V262 A12 12 0 0 1 212 262 V296"/>
<g stroke-width="1.2">
<path d="M58 222 h12 v20 h-12z M86 222 h12 v20 h-12z M114 222 h12 v20 h-12z M274 222 h12 v20 h-12z M302 222 h12 v20 h-12z M330 222 h12 v20 h-12z"/>
<path d="M58 260 h12 v22 h-12z M86 260 h12 v22 h-12z M114 260 h12 v22 h-12z M274 260 h12 v22 h-12z M302 260 h12 v22 h-12z M330 260 h12 v22 h-12z"/>
<path d="M164 214 h12 v24 h-12z M194 214 h12 v24 h-12z M224 214 h12 v24 h-12z M164 262 h12 v22 h-12z M224 262 h12 v22 h-12z"/>
<path d="M140 204 V296 M260 204 V296 M150 204 V296 M250 204 V296" opacity=".6"/>
</g>
</g></svg></div>
<div class="d-innen"><p class="d-kopf"><span>Mandantenbrief</span><span>10 / 26</span></p>
<p class="d-titel">Erbschaft­steuer im <i>Familien­unternehmen</i></p>
<p class="d-fuss"><span>Seubert Kilger</span><span>Nr. 13</span></p></div>
</article>
<article class="akte" data-ton="stein" aria-label="Briefing: Arbeitszeiterfassung">
<div class="motiv" aria-hidden="true"><svg viewBox="0 0 400 500" preserveAspectRatio="xMidYMid slice" fill="none" stroke="currentColor" stroke-width="1.2">
<!-- Wochenplan: Arbeitsblöcke, Pausen -->
<g transform="translate(0 -20)">
<path d="M60 120 H340 M60 150 H340 M60 180 H340 M60 210 H340 M60 240 H340 M60 270 H340 M60 300 H340" opacity=".35"/>
<g fill="currentColor" stroke="none">
<rect x="78" y="126" width="30" height="58"/><rect x="78" y="196" width="30" height="72"/>
<rect x="132" y="132" width="30" height="64"/><rect x="132" y="208" width="30" height="50"/>
<rect x="186" y="122" width="30" height="72"/><rect x="186" y="204" width="30" height="80"/>
<rect x="240" y="138" width="30" height="52"/><rect x="240" y="200" width="30" height="62"/>
<rect x="294" y="126" width="30" height="66"/><rect x="294" y="204" width="30" height="34" opacity=".45"/>
</g>
<g fill="currentColor" stroke="none" font-family="Schibsted Grotesk, sans-serif" font-size="13" font-weight="500" text-anchor="middle">
<text x="93" y="104">Mo</text><text x="147" y="104">Di</text><text x="201" y="104">Mi</text><text x="255" y="104">Do</text><text x="309" y="104">Fr</text>
</g>
</g></svg></div>
<div class="d-innen"><p class="d-kopf"><span>Briefing</span><span>Arbeitsrecht</span></p>
<p class="d-titel">Arbeitszeit­erfassung im <i>Mittelstand</i></p>
<p class="d-fuss"><span>Seubert Kilger</span><span>Nr. 12</span></p></div>
</article>
<article class="akte" data-ton="nacht" aria-label="Checkliste: E-Rechnung ab 2027">
<div class="motiv" aria-hidden="true"><svg viewBox="0 0 400 500" preserveAspectRatio="xMidYMid slice" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round">
<!-- drei Belege, versetzt gestapelt -->
<g transform="translate(0 -24)">
<path d="M150 98 H286 V284 H150Z" opacity=".35"/>
<path d="M134 112 H270 V298 H134Z" opacity=".6"/>
<path d="M118 126 H254 V312 H118Z"/>
<path d="M136 150 H200 M136 164 H172 M136 192 H236 M136 206 H236 M136 220 H214 M136 234 H236 M136 248 H190"/>
<path d="M184 282 H236" stroke-width="2.4"/>
<path d="M200 150 L236 150" opacity=".5"/>
<circle cx="222" cy="168" r="11"/><path d="M216 168 l4 4 l8 -8"/>
</g></svg></div>
<div class="d-innen"><p class="d-kopf"><span>Checkliste</span><span>Umsatzsteuer</span></p>
<p class="d-titel">E-Rechnung: Pflichten ab <i>2027</i></p>
<p class="d-fuss"><span>Seubert Kilger</span><span>Nr. 11</span></p></div>
</article>
<article class="akte" data-ton="sand" aria-label="Leitfaden: Hofübergabe im Weinbau">
<div class="motiv" aria-hidden="true"><svg viewBox="0 0 400 500" preserveAspectRatio="xMidYMid slice" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round">
<!-- Weinberg am Hang, Weinbergshäuschen, Sonne -->
<circle cx="300" cy="118" r="26"/>
<path d="M-10 312 C 80 300 170 230 250 170 S 380 120 410 116"/>
<path d="M222 182 v-20 l12 -10 l12 10 v20" />
<g opacity=".85">
<path d="M10 312 L74 270"/><path d="M40 312 L112 246"/><path d="M72 312 L148 222"/><path d="M106 312 L184 200"/>
<path d="M142 312 L216 186"/><path d="M180 312 L254 170"/><path d="M220 312 L288 152"/><path d="M262 312 L322 136"/>
<path d="M306 312 L356 124"/><path d="M350 312 L392 118"/>
</g>
<path d="M-10 312 H410" opacity=".5"/>
</svg></div>
<div class="d-innen"><p class="d-kopf"><span>Leitfaden</span><span>Agrarrecht</span></p>
<p class="d-titel">Hof­übergabe im <i>Weinbau</i></p>
<p class="d-fuss"><span>Seubert Kilger</span><span>Nr. 10</span></p></div>
</article>
<article class="akte" data-ton="hell" aria-label="Insight: Hinweisgeberschutz">
<div class="motiv" aria-hidden="true"><svg viewBox="0 0 400 500" preserveAspectRatio="xMidYMid slice" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round">
<!-- verschlossener Umschlag, Signalbögen -->
<path d="M110 180 H290 V290 H110Z M110 180 L200 244 L290 180"/>
<path d="M110 290 L176 228 M290 290 L224 228" opacity=".6"/>
<circle cx="200" cy="244" r="9"/>
<path d="M150 150 A70 70 0 0 1 250 150 M128 128 A100 100 0 0 1 272 128 M106 106 A130 130 0 0 1 294 106" opacity=".7"/>
</svg></div>
<div class="d-innen"><p class="d-kopf"><span>Insight</span><span>Compliance</span></p>
<p class="d-titel">Die Melde­stelle im <i>kleinen</i> Betrieb</p>
<p class="d-fuss"><span>Seubert Kilger</span><span>Nr. 09</span></p></div>
</article>
</template>
</div>
<div class="pult">
<div class="modi mono" role="group" aria-label="Auflösung des Stapels">
<span>Stapel wird</span>
<button type="button" data-v="raster" aria-pressed="true">Raster</button>
<button type="button" data-v="held" aria-pressed="false">Hero</button>
<button type="button" data-v="kreis" aria-pressed="false">Kreis</button>
<button type="button" class="nochmal" data-nochmal>↻ Nochmal</button>
</div>
<p class="werte mono" data-werte></p>
</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/Flip.min.js"></script>
<script>
(() => {
const html = document.documentElement;
const reduziert = () => html.classList.contains('reduziert');
const $ = s => document.querySelector(s), $$ = s => [...document.querySelectorAll(s)];
const buehne = $('.buehne'), main = $('#inhalt'), stapel = $('.stapel'), ablage = $('.ablage');
const vorspann = $('.vorspann'), vMarke = $('.v-marke'), vZeile = $('.v-zeile'), zaehler = $('[data-zaehler]'), skip = $('.ueberspringen');
// Deckel aus dem Template holen; Grundzustand: im Raster (so steht die Seite auch ohne JS-Bibliotheken)
const KARTEN = [...$('#deckel').content.children].map(k => k.cloneNode(true));
const MOTIVE = KARTEN.map(k => k.querySelector('.motiv svg'));
const PLAETZE = { raster: $$('[data-platz="raster"]'), kreis: $$('[data-platz="kreis"]'), held: $('[data-platz="held"]') };
function platzieren(v) {
KARTEN.forEach((k, i) => (v === 'held' ? (i === 0 ? PLAETZE.held : ablage) : PLAETZE[v][i]).appendChild(k));
}
platzieren('raster');
// Marke im Vorspann in Zeichen zerlegen (Zeichen erscheinen mit Versatz 100 ms, zufällige Reihenfolge)
vMarke.innerHTML = [...vMarke.textContent].map(z => `<span>${z}</span>`).join('');
const ZEICHEN = [...vMarke.children];
/* Messwerte (Bisous, app.714b3b.js): Flicker 12 Wechsel in 2000 ms (≈ 167 ms);
Verteilen expo.out 1000 ms, Versatz 50 ms; Wachsen expo.inOut 1800 ms, Innenbild 1,5 → 1;
Rest y ±Index × Höhe; Zeichen stagger .1 from random. */
const WECHSEL = 2 / 12, START = .2, HALTEN = .15;
const FOLGE = [5, 4, 3, 2, 1, 0, 5, 4, 3, 2, 1, 0]; // zuletzt oben: die Studie
const V = {
raster: { name: 'Raster', dauer: 1.0, ease: 'expo.out' },
held: { name: 'Hero', dauer: 1.8, ease: 'expo.inOut' },
kreis: { name: 'Kreis', dauer: 1.0, ease: 'expo.out' },
};
const paar = i => Math.floor(i / 2) * .05; // Versatz 50 ms je Paar
let variante = 'raster', tl = null, folge = null, vorfuehrung = false, bereit = false;
const einblendbar = () => [...$$('.kopf [data-ein]'), ...$$(`.a-${variante} [data-ein]`)];
function werteZeigen() {
const el = $('[data-werte]');
if (reduziert()) { el.innerHTML = '<span>Reduziert: <b>kein Stapel, kein Flackern</b> · Layout steht · Fade <b>250 ms</b></span>'; return; }
const kern = variante === 'held'
? '<span>Wachsen <b>expo.inOut 1800 ms</b> · Innenbild <b>1,5 → 1</b></span><span>Rest <b>y ±n × Höhe · expo.out 1000 ms · 50 ms</b></span>'
: `<span>${variante === 'kreis' ? 'Kreis' : 'Raster'} <b>Flip expo.out 1000 ms</b> · <b>50 ms je Paar</b> · Innenbild <b>1,5 → 1</b></span>`;
el.innerHTML = `<span>Flicker <b>12 × 167 ms</b></span>${kern}<span>Text <b>y 16 px · expo.out 900 ms · 60 ms</b></span>`;
}
function aufraeumen() {
if (tl) tl.kill(); if (folge) folge.kill();
tl = folge = null;
const alle = [...KARTEN, ...MOTIVE, ...ZEICHEN, vZeile, skip, ...$$('[data-ein]')];
gsap.killTweensOf(alle);
gsap.set(alle, { clearProps: 'all' });
buehne.classList.remove('blende');
main.removeAttribute('aria-busy');
}
function blende() { buehne.classList.remove('blende'); void buehne.offsetWidth; buehne.classList.add('blende'); }
function neustart() {
if (!bereit) return;
aufraeumen();
werteZeigen();
buehne.dataset.variante = variante;
if (reduziert()) { // Endzustand sofort, nur kurzer Fade
platzieren(variante);
buehne.dataset.zustand = 'fertig';
blende();
if (vorfuehrung) folge = gsap.delayedCall(4, naechste);
return;
}
scrollTo(0, 0);
main.setAttribute('aria-busy', 'true');
buehne.dataset.zustand = 'laden';
KARTEN.forEach(k => stapel.appendChild(k));
gsap.set(KARTEN, { autoAlpha: 0, zIndex: 0 });
gsap.set(MOTIVE, { scale: 1.5 });
gsap.set(einblendbar(), { autoAlpha: 0, y: 16 });
gsap.set(ZEICHEN, { autoAlpha: 0 });
zaehler.textContent = '00 / 06';
tl = gsap.timeline();
tl.to(ZEICHEN, { autoAlpha: 1, duration: .5, ease: 'expo.out', stagger: { each: .1, from: 'random' } }, 0);
FOLGE.forEach((idx, n) => tl.call(() => {
gsap.set(KARTEN[idx], { autoAlpha: 1, zIndex: n + 1 });
zaehler.textContent = `0${idx + 1} / 06`;
}, null, START + n * WECHSEL));
tl.call(uebergabe, null, START + FOLGE.length * WECHSEL + HALTEN);
}
function uebergabe() {
const v = variante, d = V[v].dauer, ease = V[v].ease;
const stand = Flip.getState(KARTEN);
buehne.dataset.zustand = 'uebergabe';
const t = gsap.timeline({ onComplete: fertig });
t.to([vMarke, vZeile, skip], { autoAlpha: 0, duration: .25, ease: 'none' }, 0);
let textAb;
if (v === 'held') {
const [studie, ...rest] = KARTEN;
PLAETZE.held.appendChild(studie);
gsap.set(studie, { zIndex: 20 });
t.add(Flip.from(stand, { targets: studie, duration: d, ease, absolute: true, zIndex: 20 }), 0)
.to(MOTIVE[0], { scale: 1, duration: d, ease }, 0)
// Rest verteilt sich abwechselnd nach unten und oben aus dem Bild (Bisous: y ±Index × Höhe)
.to(rest, { y: i => (i % 2 ? -1 : 1) * (Math.floor(i / 2) + 1) * innerHeight, duration: 1, ease: 'expo.out', stagger: .05 }, 0);
textAb = d * .5;
} else {
KARTEN.forEach((k, i) => PLAETZE[v][i].appendChild(k));
t.add(Flip.from(stand, { duration: d, ease, absolute: true, stagger: paar }), 0)
.to(MOTIVE, { scale: 1, duration: d, ease, stagger: paar }, 0);
textAb = .35;
}
t.to(einblendbar(), { autoAlpha: 1, y: 0, duration: .9, ease: 'expo.out', stagger: .06 }, textAb);
folge = t;
}
function fertig() {
if (variante === 'held') KARTEN.slice(1).forEach(k => ablage.appendChild(k));
gsap.set([...KARTEN, ...MOTIVE], { clearProps: 'all' });
buehne.dataset.zustand = 'fertig';
main.removeAttribute('aria-busy');
folge = vorfuehrung ? gsap.delayedCall(2.4, naechste) : null;
}
// Überspringen: Klick auf den Vorspann, Knopf oder Taste. Layout sofort, 250 ms Fade.
function ueberspringen() {
if (buehne.dataset.zustand !== 'laden' && buehne.dataset.zustand !== 'uebergabe') return;
vorfuehrung = false;
aufraeumen();
platzieren(variante);
buehne.dataset.zustand = 'fertig';
blende();
}
vorspann.addEventListener('click', ueberspringen);
addEventListener('keydown', e => { if (e.key !== 'Tab' && !e.metaKey && !e.ctrlKey) ueberspringen(); });
function setzen(v) {
variante = v;
$$('[data-v]').forEach(b => b.setAttribute('aria-pressed', String(b.dataset.v === v)));
}
function naechste() {
const reihe = Object.keys(V);
setzen(reihe[(reihe.indexOf(variante) + 1) % reihe.length]);
neustart();
}
$$('[data-v]').forEach(b => b.addEventListener('click', () => { vorfuehrung = false; setzen(b.dataset.v); neustart(); }));
$('[data-nochmal]').addEventListener('click', () => { vorfuehrung = false; neustart(); });
function vorfuehren() { vorfuehrung = true; gsap.globalTimeline.resume(); neustart(); }
function pause() { gsap.globalTimeline.pause(); }
function weiter() { gsap.globalTimeline.resume(); }
werteZeigen();
if (!window.gsap || !window.Flip) return; // ohne GSAP bleibt das Raster einfach stehen
gsap.registerPlugin(Flip);
// Echte Seite: hier zusätzlich Promise.all(imgs.map(i => i.decode())) mit Timeout
Promise.race([document.fonts.ready, new Promise(r => setTimeout(r, 1500))]).then(() => { bereit = true; neustart(); });
})();
</script>
</body>
</html>