Split-Screen mit Sticky-Seite (eine Seite steht, andere scrollt)
Eine Spalte bleibt stehen, die andere scrollt vorbei; der Inhalt der stehenden Spalte wechselt synchron mit dem Block in der Bildschirmmitte.
Leistungen, Prozessschritte oder Case-Study-Kapitel mit je einem starken Bild: Studio, Hotel (Restaurant, Bar, Spa), Kampagne, Kurs-Hero. Ein Gedanke, ein Bild, die Nummer rollt mit.
Die Sektion wird in zwei Spalten geteilt, 50/50 oder 5/7 im 12er-Raster. Eine Spalte ist position: sticky und bleibt im Viewport stehen. Das ist meist ein Titel, eine Kapitelnummer, ein Bild oder ein Video. Die andere Spalte scrollt mit mehreren Inhaltsblöcken vorbei. Läuft ein Block durch die Bildschirmmitte, wechselt der Inhalt der stehenden Spalte synchron: Bild-Crossfade, Clip-Reveal, eine Zahl rollt weiter, ein Eintrag wird hervorgehoben. Am Ende der Sektion löst sich die Sticky-Spalte und scrollt mit weg.
Der feste Anker gibt Orientierung, während die Details vorbeiziehen. Die Synchronisation erzeugt einen Erzählrhythmus wie bei einer Präsentation: ein Gedanke, ein Bild.
Wann einsetzen
Leistungen mit drei bis sechs Punkten, Prozessschritte, Abschnitte einer Case Study (Bild steht, Text erklärt), Produktfeatures mit Screenshot, Projektlisten mit fester Vorschau.
Wann nicht
Wenn die stehende Spalte höher ist als der Viewport. Bei mobil geprägten Seiten mit sehr viel Inhalt. Wenn der Wechsel keinen inhaltlichen Bezug zum Text hat.
Varianten
- Sticky-Titel links, Karten scrollen rechts
- Sticky-Medium (Bild oder Video) mit Wechsel pro Textblock
- Split-Screen-Hero: zwei Hälften mit unterschiedlichen Inhalten und Farben
- Horizontaler Split: oben steht, unten scrollt
- Archiv: Liste scrollt, Vorschau steht fest
Umsetzung
Grid mit zwei Spalten. Sticky-Spalte: position: sticky; top: 0; height: 100svh, oder mit Abstand nach oben (top: 8em) und align-self: start. Kein overflow: hidden auf einem Vorfahren, das bricht sticky. Den aktiven Block bestimmt ein IntersectionObserver mit rootMargin '-50% 0px -50% 0px' oder eine CSS view-timeline mit timeline-scope. Medien wechseln per opacity oder clip-path. Für den festgeklebten Zustand (z. B. Schatten) gibt es seit Chrome 133 @container scroll-state(stuck: top).
Robust umsetzen
Telefon. Spalten stapeln. Das Sticky-Medium wird ein kleiner Sticky-Streifen oben oder ein Inline-Bild direkt über dem zugehörigen Text. Ein Sticky-Titel wird zur schmalen Leiste mit Fortschritt.
Ohne Bewegung. Crossfade statt Clip-Reveal und Zoom. Sticky selbst ist unkritisch.
Barrierefrei. Alle wechselnden Bilder mit eigenem alt im DOM halten, nicht per JS austauschen, oder das Bild direkt dem Text zuordnen. Der Tastaturfokus in der scrollenden Spalte muss sichtbar bleiben. Die Bildunterschrift der stehenden Spalte kann per aria-live den aktiven Abschnitt nennen.
Code
<!DOCTYPE html>
<!--
Split-Screen mit Sticky-Seite (eine Seite steht, andere scrollt)
Fundus · Hero & Section-Layouts · https://cecodesign.de/lab/fundus/hero-layouts/split-screen-sticky-seiten/
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>Split-Screen mit Sticky-Seite · 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: 'Instrument Sans'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/instrument-sans:vf@latest/latin-wght-normal.woff2') format('woff2-variations'); font-weight: 400 700; 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; }
@font-face { font-family: 'Instrument Serif'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/instrument-serif@latest/latin-400-italic.woff2') format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Instrument Serif'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/instrument-serif@latest/latin-400-normal.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Fragment Mono'; src: url('https://cdn.jsdelivr.net/fontsource/fonts/fragment-mono@latest/latin-400-normal.woff2') format('woff2'); font-weight: 400; font-display: swap; }
:root {
--grund: #efebe4; --text: #161514; --leise: rgba(22, 21, 20, .64); --linie: rgba(22, 21, 20, .14);
--nacht: #141312; --hell: #f4f1ea;
--akzent: #c9542c; --akzent-text: #af4926; /* Akzent für kleine Schrift: 4,6:1 auf Grund */
--kurve: cubic-bezier(0.16, 1, 0.3, 1); /* expo.out */
--dauer: 1.2s; /* Clip-Reveal */
--dauer-bild: 1.6s; /* Bild zoomt zurück */
--dauer-text: .6s; /* aktiver Block, Marker */
--oben-titel: 8em; /* Sticky-Offset OFF+BRAND */
--spalte: 320px; /* feste Spalte Raycast */
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { background: var(--grund); color: var(--text); font-family: 'Instrument Sans', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
body { background: var(--grund); }
img { display: block; max-width: 100%; }
ul, ol { list-style: none; }
a { color: inherit; }
em { font-family: 'Instrument Serif', Georgia, serif; font-style: italic; font-weight: 400; letter-spacing: -.01em; }
.mono { font: 500 11px/1.45 'Geist Mono', ui-monospace, monospace; letter-spacing: .14em; text-transform: uppercase; color: var(--leise); }
[hidden] { display: none !important; }
/* ── Variante A: Bild steht, Text scrollt ─────────────────────────── */
.split-bild { display: grid; grid-template-columns: 1fr 1fr; } /* kein overflow:hidden auf Vorfahren, sonst bricht sticky */
.anker { position: sticky; top: 0; height: 100svh; padding: 14px 0 14px 14px; }
.buehne { position: relative; height: 100%; overflow: hidden; border-radius: 6px; background: var(--nacht); color: var(--hell); isolation: isolate; }
.stapel { position: absolute; inset: 0; isolation: isolate; }
.ebene { position: absolute; inset: 0; margin: 0; background: var(--bg, var(--nacht)); clip-path: inset(100% 0 0 0); transition: clip-path var(--dauer) var(--kurve); }
.ebene.sichtbar { clip-path: inset(0 0 0 0); }
.ebene picture { display: contents; }
.ebene img, .ebene svg { display: block; width: 100%; height: 100%; object-fit: cover; scale: 1; transition: scale var(--dauer-bild) var(--kurve); }
.ebene.einpassen img { position: absolute; left: 0; top: 50%; translate: 0 -50%; height: auto; max-height: 100%; object-fit: contain; -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 22%, #000 78%, transparent 100%); mask-image: linear-gradient(180deg, transparent 0%, #000 22%, #000 78%, transparent 100%); }
/* Beschriftung invertiert sich gegen das Bild (hell auf dunkel, dunkel auf hell) */
.buehne__kopf, .buehne__fuss, .striche { mix-blend-mode: difference; color: #fff; }
.buehne__kopf, .buehne__fuss { position: absolute; left: 24px; right: 24px; z-index: 1; display: flex; justify-content: space-between; align-items: flex-end; gap: 16px; }
.buehne__kopf { top: 22px; align-items: center; }
.buehne__fuss { bottom: 22px; }
.buehne .mono { color: rgba(255, 255, 255, .7); }
.marke { font-weight: 600; font-size: 15px; letter-spacing: -.01em; color: #fff; }
.marke em { font-size: 17px; }
.zaehler { display: flex; align-items: flex-end; gap: 10px; line-height: 1; }
.ziffern { position: relative; display: block; height: 1lh; width: 1.02em; overflow: hidden; font: italic 400 clamp(64px, 8vw, 116px)/1 'Instrument Serif', Georgia, serif; }
.ziffern span { position: absolute; left: 0; top: 0; transition: transform var(--dauer) var(--kurve); }
.zaehler .mono { padding-bottom: .9em; }
.bildtext { text-align: right; white-space: nowrap; }
.bildtext b { display: block; color: #fff; font-weight: 500; }
.striche { position: absolute; right: 24px; top: 50%; translate: 0 -50%; z-index: 1; display: grid; gap: 8px; }
.striche i { display: block; width: 2px; height: 26px; background: rgba(255, 255, 255, .3); border-radius: 2px; transition: background var(--dauer-text) var(--kurve), height var(--dauer-text) var(--kurve); }
.striche i.an { background: #fff; height: 44px; }
.strom { padding: 0 clamp(28px, 5.5vw, 88px) 0 clamp(32px, 6vw, 96px); }
.block { min-height: 88svh; display: grid; align-content: center; gap: 22px; max-width: 520px; padding: 10svh 0; }
.block:first-child { min-height: 100svh; padding-top: 14px; align-content: space-between; }
.block:last-child { min-height: 92svh; }
.block > * { transition: opacity var(--dauer-text) var(--kurve); }
.block:not(.aktiv) > :not(.intro) { opacity: .26; }
.navi { display: flex; justify-content: space-between; align-items: center; gap: 16px; padding-top: 10px; }
.navi ul { display: flex; gap: 20px; }
.navi a { text-decoration: none; }
.navi a[aria-current] { color: var(--text); }
.h1 { font-size: clamp(44px, 5.6vw, 88px); font-weight: 600; letter-spacing: -.045em; line-height: .94; text-wrap: balance; }
.h1 em { font-size: 1.06em; color: var(--akzent); }
.vorspann { font-size: clamp(17px, 1.35vw, 20px); line-height: 1.5; color: var(--leise); max-width: 34ch; }
.intro, .erst { display: grid; gap: 26px; }
.erst { gap: 18px; }
.hinweis { display: flex; align-items: center; gap: 12px; }
.hinweis::before { content: ''; width: 32px; height: 1px; background: currentColor; }
.block__nr { display: flex; gap: 14px; }
.block__nr b { color: var(--akzent-text); font-weight: 500; }
.h3 { font-size: clamp(32px, 3.4vw, 54px); font-weight: 600; letter-spacing: -.035em; line-height: 1; text-wrap: balance; }
.text { font-size: clamp(16px, 1.15vw, 18px); line-height: 1.6; color: var(--leise); max-width: 40ch; }
.liste { display: flex; flex-wrap: wrap; gap: 8px; }
.liste li { border: 1px solid var(--linie); border-radius: 999px; padding: 6px 12px; }
.mehr { justify-self: start; display: inline-flex; gap: 10px; align-items: center; text-decoration: none; font-weight: 500; font-size: 15px; border-bottom: 1px solid var(--text); padding-bottom: 3px; }
.mehr span { transition: translate .15s linear; }
.mehr:hover span { translate: 4px 0; }
a:focus-visible, button:focus-visible { outline: 2px solid var(--akzent); outline-offset: 4px; border-radius: 2px; }
.inline-bild { display: none; }
/* ── Variante B: Titel steht, Karten scrollen ─────────────────────── */
.split-titel { display: flex; gap: clamp(40px, 7vw, 128px); max-width: 1280px; margin: 0 auto; padding: 0 clamp(24px, 5vw, 72px); }
.titelspalte { flex: 0 0 var(--spalte); position: sticky; top: var(--oben-titel); align-self: flex-start; display: grid; gap: 26px; padding-bottom: 6vh; }
.titelspalte .h2 { font-size: clamp(40px, 4vw, 60px); font-weight: 600; letter-spacing: -.045em; line-height: .96; text-wrap: balance; }
.titelspalte .h2 em { color: var(--akzent); font-size: 1.06em; }
.titelspalte .text { font-size: 16px; }
.index { display: grid; border-top: 1px solid var(--linie); }
.index li { display: grid; grid-template-columns: 34px 1fr auto; align-items: center; gap: 8px; padding: 13px 0; border-bottom: 1px solid var(--linie); font-size: 15px; color: var(--leise); transition: color var(--dauer-text) var(--kurve); }
.index li .mono { color: inherit; }
.index li::after { content: ''; width: 24px; height: 2px; background: var(--akzent); transform: scaleX(0); transform-origin: right; transition: transform var(--dauer-text) var(--kurve); }
.index li.an { color: var(--text); }
.index li.an::after { transform: scaleX(1); }
.karten { flex: 1; min-width: 0; display: grid; gap: clamp(72px, 14vh, 140px); padding: var(--oben-titel) 0 34svh; }
.karte { display: grid; gap: 18px; transition: opacity var(--dauer-text) var(--kurve); }
.karte:not(.aktiv) { opacity: .34; }
.karte__bild { aspect-ratio: 3 / 2; overflow: hidden; border-radius: 6px; background: var(--nacht); }
.karte__bild img, .karte__bild svg { display: block; width: 100%; height: 100%; object-fit: cover; }
.karte__zeile { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.karte__zeile b { color: var(--text); font-weight: 500; }
.karte .h3 { font-size: clamp(26px, 2.4vw, 38px); }
.leiste { display: none; }
/* ── Variante C: Archiv. Liste scrollt, Vorschau steht fest, Crossfade ──
Eigene Welt nach Rezept fotograf-film-bild-zuerst: neutrales Hellgrau, Serif nur für Titel,
Fragment Mono für Zähler und Bildunterschrift, Bildwechsel nur über Opazität (inOutQuad). */
.split-archiv {
--a-grund: #f4f4f2; --a-text: #141414; --a-leise: #6e6e6e; --a-linie: rgba(20, 20, 20, .12); --a-platz: #e6e6e6;
--a-kurve: cubic-bezier(0.455, 0.03, 0.515, 0.955); /* easeInOutQuad, Bildwechsel */
--a-blende: 600ms; --a-ui: 200ms;
display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); background: var(--a-grund); color: var(--a-text);
}
.a-mono { font: 400 12px/1.4 'Fragment Mono', ui-monospace, monospace; letter-spacing: .02em; font-variant-numeric: tabular-nums; color: var(--a-leise); }
.arch-vorschau { position: sticky; top: 0; height: 100svh; display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: 18px; padding: 22px clamp(20px, 2.6vw, 40px); }
.arch-kopf { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; }
.arch-name { font: 400 clamp(20px, 1.6vw, 24px)/1 'Instrument Serif', Georgia, serif; letter-spacing: -.01em; }
.arch-rahmen { position: relative; margin: 0; min-height: 0; background: var(--a-platz); overflow: hidden; }
.arch-rahmen img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; }
.arch-rahmen img.vorher { opacity: 1; z-index: 1; }
.arch-rahmen img.an { opacity: 1; z-index: 2; transition: opacity var(--a-blende) var(--a-kurve); }
.arch-unterschrift { display: grid; grid-template-columns: 5em minmax(0, 1fr) auto; white-space: nowrap; gap: 14px; align-items: baseline; }
.arch-unterschrift b { font-weight: 400; color: var(--a-text); }
.arch-liste { padding: 22px clamp(20px, 3.2vw, 48px) 0 clamp(8px, 1.4vw, 20px); }
.arch-titel { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: 1fr auto; gap: 16px 24px; min-height: calc(50svh - 64px); padding: 6px 0 28px; }
.arch-bio { grid-column: 1 / -1; max-width: 36ch; font-size: 15px; line-height: 1.5; color: var(--a-leise); }
.arch-bio b { font-weight: 500; color: var(--a-text); }
.arch-titel h2 { font: 400 clamp(40px, 4.4vw, 68px)/1 'Instrument Serif', Georgia, serif; letter-spacing: -.02em; align-self: end; }
.arch-titel h2 i { font-style: italic; }
.arch-titel .a-mono { align-self: end; padding-bottom: .5em; }
.arch-reihen { list-style: none; border-bottom: 1px solid var(--a-linie); margin-bottom: 44svh; }
.arch-zeile { display: grid; grid-template-columns: 4.5em minmax(0, 1fr) minmax(0, 11em) 6.5em; gap: 16px; align-items: baseline; padding: clamp(14px, 1.5vw, 20px) 0; border-top: 1px solid var(--a-linie); text-decoration: none; color: var(--a-leise); transition: color var(--a-ui) var(--a-kurve); }
.arch-zeile .t { font: 400 clamp(24px, 2.3vw, 36px)/1.05 'Instrument Serif', Georgia, serif; letter-spacing: -.01em; }
.arch-zeile .a-mono { color: inherit; }
.arch-zeile .n { text-align: right; }
.arch-zeile.an { color: var(--a-text); }
.arch-zeile:focus-visible { outline: 1.5px solid var(--a-text); outline-offset: 4px; }
.arch-daumen { display: none; }
@media (max-width: 1100px) { .arch-zeile { grid-template-columns: 4.5em minmax(0, 1fr) 6.5em; } .arch-zeile .o { display: none; } }
/* ── Abspann: hier löst sich die Sticky-Spalte ────────────────────── */
.abspann { background: var(--nacht); color: var(--hell); padding: clamp(72px, 14vh, 140px) clamp(24px, 5vw, 72px); display: grid; gap: 28px; }
.abspann .mono { color: rgba(244, 241, 234, .6); }
.abspann .h1 { max-width: 13ch; }
.abspann .h1 em { color: #e9875c; }
.abspann__zeile { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; border-top: 1px solid rgba(244, 241, 234, .16); padding-top: 18px; }
/* ── Steuerung (dezent) ───────────────────────────────────────────── */
.steuer { position: fixed; right: 16px; bottom: 16px; z-index: 100; display: grid; gap: 8px; justify-items: end; max-width: calc(100vw - 32px); pointer-events: none; }
.steuer > * { pointer-events: auto; }
.modi { display: flex; gap: 4px; padding: 4px; border-radius: 999px; background: rgba(239, 235, 228, .82); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border: 1px solid var(--linie); }
.modi button { font: inherit; letter-spacing: inherit; text-transform: inherit; color: var(--leise); background: none; border: 0; border-radius: 999px; height: 28px; padding: 0 12px; cursor: pointer; transition: background .15s linear, color .15s linear; }
.modi button[aria-pressed='true'] { background: var(--text); color: var(--grund); }
.werte { font-size: 10px; text-align: right; background: rgba(239, 235, 228, .82); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border: 1px solid var(--linie); border-radius: 8px; padding: 8px 12px; max-width: 380px; }
.werte b { color: var(--text); font-weight: 500; }
/* ── Reduzierte Bewegung: Crossfade statt Clip/Scale ──────────────── */
.reduziert .ebene { clip-path: none !important; opacity: 0; transition: opacity .25s linear; }
.reduziert .ebene.sichtbar { opacity: 1; }
.reduziert .ebene img, .reduziert .ebene svg { scale: 1 !important; transition: none; }
.reduziert .ziffern span { transition: none; }
.reduziert .block > *, .reduziert .karte, .reduziert .index li, .reduziert .index li::after, .reduziert .striche i { transition-duration: .2s; transition-timing-function: linear; }
.reduziert .arch-rahmen img.an { transition: opacity .2s linear; }
.reduziert .arch-zeile { transition-duration: .2s; transition-timing-function: linear; }
/* ── Vorschau 960 × 720: nur die Bühne ────────────────────────────── */
.vorschau body { overflow: hidden; }
.vorschau .steuer, .vorschau .abspann__zeile { display: none; }
@media (hover: none) { .mehr span { transition: none; } .mehr:hover span { translate: none; } }
/* ── Telefon: Spalten stapeln, Bild wird Sticky-Streifen ──────────── */
@media (max-width: 760px) {
.split-bild { grid-template-columns: 1fr; }
.anker { height: min(44svh, 78vw); padding: 10px 10px 0; z-index: 5; background: var(--grund); }
.buehne__kopf { left: 16px; right: 16px; top: 14px; }
.buehne__fuss { left: 16px; right: 16px; bottom: 14px; }
.ziffern { font-size: 60px; }
.striche { right: 14px; gap: 6px; }
.striche i { height: 16px; } .striche i.an { height: 28px; }
.bildtext { max-width: none; white-space: nowrap; letter-spacing: .1em; }
.bildtext span { display: none; }
.ebene svg { width: auto; height: calc(100% - 100px); aspect-ratio: 4 / 5; margin: 42px auto 0; } /* ganzes Motiv im Streifen, frei von Zähler und Bildtext */
.strom { padding: 0 20px; }
.block { min-height: 62svh; padding: 8svh 0; gap: 18px; }
.block:first-child { min-height: 0; padding-top: 28px; gap: 40px; }
.block:last-child { min-height: 70svh; }
.navi ul { display: none; }
.h1 { font-size: clamp(40px, 12vw, 56px); }
.split-titel { display: block; padding: 0; }
.titelspalte { position: static; padding: 40px 20px 28px; }
.titelspalte .index { display: none; }
.leiste { display: block; position: sticky; top: 0; z-index: 5; container-type: scroll-state; }
.leiste__innen { display: grid; gap: 10px; padding: 14px 20px 12px; background: rgba(239, 235, 228, .92); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border-bottom: 1px solid var(--linie); }
.leiste__zeile { display: flex; justify-content: space-between; gap: 12px; }
.leiste__zeile b { color: var(--text); font-weight: 500; }
.leiste__balken { height: 2px; background: var(--linie); }
.leiste__balken i { display: block; height: 100%; background: var(--akzent); transform-origin: left; transform: scaleX(.25); transition: transform var(--dauer-text) var(--kurve); }
@container scroll-state(stuck: top) { .leiste__innen { box-shadow: 0 10px 24px -18px rgba(0, 0, 0, .5); } }
.karten { padding: 28px 20px 30svh; gap: 64px; }
.karte:not(.aktiv) { opacity: .5; }
.werte { display: none; }
.steuer { right: 12px; bottom: 12px; }
.split-archiv { grid-template-columns: 1fr; }
.arch-vorschau { height: auto; z-index: 5; background: var(--a-grund); padding: 12px 16px 10px; gap: 10px; grid-template-rows: auto min(38svh, 64vw) auto; border-bottom: 1px solid var(--a-linie); }
.arch-kopf .a-mono { display: none; }
.arch-unterschrift { grid-template-columns: 5em minmax(0, 1fr); }
.arch-rahmen { background: none; }
.arch-rahmen img { object-fit: contain; } /* ganzes Werk im Streifen, nie beschnitten */
.arch-unterschrift [data-arch-ort] { display: none; }
.arch-liste { padding: 0 16px; }
.arch-titel { min-height: 0; padding: 26px 0 18px; }
.arch-bio { font-size: 14px; }
.arch-titel h2 { font-size: 40px; }
.arch-zeile { grid-template-columns: 3.4em minmax(0, 1fr) auto; gap: 10px; }
.arch-zeile .o { display: none; }
.arch-zeile .t { font-size: 25px; }
.arch-reihen { margin-bottom: 30svh; }
}
</style>
</head>
<body>
<!-- Variante A: Sticky-Medium mit Clip-Reveal pro Textblock -->
<section class="split-bild" data-variante="bild" aria-label="Leistungen">
<div class="anker">
<div class="buehne" data-buehne>
<div class="stapel">
<figure class="ebene sichtbar" style="--bg: #f4f1ea">
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" viewBox="0 0 800 1000" role="img" aria-label="Signet Pier 9, Kaffeerösterei am Hafen: Poller über drei Wellen im runden Stempel, darunter die Wortmarke">
<rect width="800" height="1000" fill="#f4f1ea"/>
<defs><path id="pier-kreis" d="M400 320a150 150 0 1 1 0 300a150 150 0 1 1 0-300"/></defs>
<circle cx="400" cy="470" r="196" fill="none" stroke="#1d1b18" stroke-width="5"/>
<circle cx="400" cy="470" r="118" fill="#1d1b18"/>
<text font-family="'Geist Mono', monospace" font-size="21" letter-spacing="6" fill="#1d1b18"><textPath href="#pier-kreis">KAFFEERÖSTEREI · AM HAFEN · MÜNSTER ·</textPath></text>
<path d="M366 476V430q0-14 14-14h40q14 0 14 14v46" fill="#f4f1ea"/><rect x="352" y="404" width="96" height="18" rx="9" fill="#f4f1ea"/>
<path d="M318 500q20-14 41 0t41 0t41 0t41 0M318 526q20-14 41 0t41 0t41 0t41 0" fill="none" stroke="#c9542c" stroke-width="7" stroke-linecap="round"/>
<text x="400" y="770" text-anchor="middle" font-family="'Instrument Sans', sans-serif" font-weight="600" font-size="78" letter-spacing="16" fill="#1d1b18">PIER<tspan fill="#c9542c"> 9</tspan></text>
<text x="400" y="818" text-anchor="middle" font-family="'Geist Mono', monospace" font-size="19" letter-spacing="5" fill="#8a8178">SEIT 2019 · RÖSTET DIENSTAGS</text>
</svg>
</figure>
<figure class="ebene" style="--bg: #dfe3d2">
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" viewBox="0 0 800 1000" role="img" aria-label="Titelseite Kornblume, Heft für Gartenkultur: kursiver Titel, geometrische Kornblume, Themen am Rand gegen das Raster gesetzt">
<rect width="800" height="1000" fill="#dfe3d2"/>
<text x="400" y="262" text-anchor="middle" font-family="'Instrument Serif', Georgia, serif" font-style="italic" font-size="156" letter-spacing="-4" fill="#1f2a22">Kornblume</text>
<text x="400" y="304" text-anchor="middle" font-family="'Geist Mono', monospace" font-size="15" letter-spacing="3.5" fill="#1f2a22">HEFT FÜR GARTENKULTUR · N° 12 · HERBST 2026 · 9,80 €</text>
<path d="M120 326H680" stroke="#1f2a22" stroke-width="2"/>
<g transform="translate(520 600) scale(.92)">
<g fill="#3a5fb0"><ellipse cx="0" cy="-118" rx="30" ry="70" transform="rotate(0)"/><ellipse cx="0" cy="-118" rx="30" ry="70" transform="rotate(30)"/><ellipse cx="0" cy="-118" rx="30" ry="70" transform="rotate(60)"/><ellipse cx="0" cy="-118" rx="30" ry="70" transform="rotate(90)"/><ellipse cx="0" cy="-118" rx="30" ry="70" transform="rotate(120)"/><ellipse cx="0" cy="-118" rx="30" ry="70" transform="rotate(150)"/><ellipse cx="0" cy="-118" rx="30" ry="70" transform="rotate(180)"/><ellipse cx="0" cy="-118" rx="30" ry="70" transform="rotate(210)"/><ellipse cx="0" cy="-118" rx="30" ry="70" transform="rotate(240)"/><ellipse cx="0" cy="-118" rx="30" ry="70" transform="rotate(270)"/><ellipse cx="0" cy="-118" rx="30" ry="70" transform="rotate(300)"/><ellipse cx="0" cy="-118" rx="30" ry="70" transform="rotate(330)"/></g>
<g fill="#26407f"><ellipse cx="0" cy="-74" rx="15" ry="40" transform="rotate(15)"/><ellipse cx="0" cy="-74" rx="15" ry="40" transform="rotate(45)"/><ellipse cx="0" cy="-74" rx="15" ry="40" transform="rotate(75)"/><ellipse cx="0" cy="-74" rx="15" ry="40" transform="rotate(105)"/><ellipse cx="0" cy="-74" rx="15" ry="40" transform="rotate(135)"/><ellipse cx="0" cy="-74" rx="15" ry="40" transform="rotate(165)"/><ellipse cx="0" cy="-74" rx="15" ry="40" transform="rotate(195)"/><ellipse cx="0" cy="-74" rx="15" ry="40" transform="rotate(225)"/><ellipse cx="0" cy="-74" rx="15" ry="40" transform="rotate(255)"/><ellipse cx="0" cy="-74" rx="15" ry="40" transform="rotate(285)"/><ellipse cx="0" cy="-74" rx="15" ry="40" transform="rotate(315)"/><ellipse cx="0" cy="-74" rx="15" ry="40" transform="rotate(345)"/></g>
<circle r="44" fill="#1f2a22"/><circle r="16" fill="#dfe3d2"/>
</g>
<path d="M520 742V1000" stroke="#1f2a22" stroke-width="5"/>
<g font-family="'Instrument Sans', sans-serif" fill="#1f2a22">
<text x="120" y="420" font-size="60" font-weight="600" letter-spacing="-2">36</text><text x="120" y="452" font-size="22">Samen, die wir</text><text x="120" y="480" font-size="22">tauschen</text>
<text x="120" y="602" font-size="60" font-weight="600" letter-spacing="-2">12</text><text x="120" y="634" font-size="22">Seiten Kürbis</text>
<text x="120" y="700" font-size="22">Der Hof der</text><text x="120" y="728" font-size="22">Familie Brehm</text>
</g>
<text transform="translate(706 380) rotate(90)" font-family="'Geist Mono', monospace" font-size="16" letter-spacing="5" fill="#1f2a22">GARTEN · KÜCHE · LAND</text>
</svg>
</figure>
<figure class="ebene" style="--bg: #232e32">
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" viewBox="0 0 800 1000" role="img" aria-label="Auftritt Radhaus Lütke, Werkstatt und Café: rundes Schild mit Speichenrad, Farbsystem in vier Punkten und Zeilen der Tafel">
<rect width="800" height="1000" fill="#232e32"/>
<circle cx="400" cy="430" r="200" fill="#e9e1d0"/>
<g fill="none" stroke="#232e32" stroke-linecap="round">
<circle cx="400" cy="400" r="104" stroke-width="16"/><circle cx="400" cy="400" r="12" stroke-width="10"/>
<path d="M400 296V512M296 400H504M326 326L474 474M474 326L326 474" stroke-width="4"/>
<path d="M362 330V462H448" stroke="#d9663b" stroke-width="22"/>
</g>
<text x="400" y="566" text-anchor="middle" font-family="'Instrument Serif', Georgia, serif" font-size="50" fill="#232e32">Radhaus <tspan font-style="italic">Lütke</tspan></text>
<g transform="translate(271 676)"><circle r="20" fill="#e9e1d0"/><circle cx="86" r="20" fill="#d9663b"/><circle cx="172" r="20" fill="#7f9f8a"/><circle cx="258" r="20" fill="#11181b" stroke="#e9e1d0" stroke-width="2"/></g>
<g font-family="'Geist Mono', monospace" font-size="20" letter-spacing="3" fill="#e9e1d0">
<text x="150" y="752">ESPRESSO</text><text x="650" y="752" text-anchor="end">2,40</text>
<text x="150" y="792">SCHLAUCH FLICKEN</text><text x="650" y="792" text-anchor="end">8,00</text>
<text x="150" y="832">KETTE ÖLEN</text><text x="650" y="832" text-anchor="end">GRATIS</text>
</g>
<path d="M150 770H650M150 810H650" stroke="#e9e1d0" stroke-opacity=".18" stroke-width="2"/>
</svg>
</figure>
<figure class="ebene" style="--bg: #1c1b18">
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" viewBox="0 0 800 1000" role="img" aria-label="Plakat für den Pianisten Tomás Reiner: goldenes Monogramm TR im Kreis, Name und Termine, unten eine Reihe Klaviertasten">
<rect width="800" height="1000" fill="#1c1b18"/>
<circle cx="400" cy="330" r="132" fill="none" stroke="#c8a45a" stroke-width="3"/>
<text x="400" y="384" text-anchor="middle" font-family="'Instrument Serif', Georgia, serif" font-style="italic" font-size="170" letter-spacing="-8" fill="#c8a45a">TR</text>
<text x="400" y="582" text-anchor="middle" font-family="'Instrument Serif', Georgia, serif" font-size="82" letter-spacing="-1" fill="#efe8d8">Tomás Reiner</text>
<text x="400" y="630" text-anchor="middle" font-family="'Geist Mono', monospace" font-size="20" letter-spacing="6" fill="#c8a45a">KLAVIERABENDE 2026</text>
<g font-family="'Geist Mono', monospace" font-size="19" letter-spacing="3" fill="#efe8d8" fill-opacity=".72" text-anchor="middle">
<text x="400" y="700">14. NOV · MÜNSTER · ERBDROSTENHOF</text><text x="400" y="736">22. NOV · OSNABRÜCK · LUTHERHAUS</text>
</g>
<g transform="translate(0 772)"><rect x="124" y="0" width="36" height="74" fill="#efe8d8"/><rect x="164" y="0" width="36" height="74" fill="#efe8d8"/><rect x="204" y="0" width="36" height="74" fill="#efe8d8"/><rect x="244" y="0" width="36" height="74" fill="#efe8d8"/><rect x="284" y="0" width="36" height="74" fill="#efe8d8"/><rect x="324" y="0" width="36" height="74" fill="#efe8d8"/><rect x="364" y="0" width="36" height="74" fill="#efe8d8"/><rect x="404" y="0" width="36" height="74" fill="#efe8d8"/><rect x="444" y="0" width="36" height="74" fill="#efe8d8"/><rect x="484" y="0" width="36" height="74" fill="#efe8d8"/><rect x="524" y="0" width="36" height="74" fill="#efe8d8"/><rect x="564" y="0" width="36" height="74" fill="#efe8d8"/><rect x="604" y="0" width="36" height="74" fill="#efe8d8"/><rect x="644" y="0" width="36" height="74" fill="#efe8d8"/><rect x="149" y="0" width="22" height="44" fill="#1c1b18"/><rect x="189" y="0" width="22" height="44" fill="#1c1b18"/><rect x="269" y="0" width="22" height="44" fill="#1c1b18"/><rect x="309" y="0" width="22" height="44" fill="#1c1b18"/><rect x="349" y="0" width="22" height="44" fill="#1c1b18"/><rect x="429" y="0" width="22" height="44" fill="#1c1b18"/><rect x="469" y="0" width="22" height="44" fill="#1c1b18"/><rect x="549" y="0" width="22" height="44" fill="#1c1b18"/><rect x="589" y="0" width="22" height="44" fill="#1c1b18"/><rect x="629" y="0" width="22" height="44" fill="#1c1b18"/></g>
</svg>
</figure>
</div>
<div class="buehne__kopf"><span class="marke">Studio <em>Wendel</em></span><span class="mono">Leistungen</span></div>
<div class="striche" aria-hidden="true"><i class="an"></i><i></i><i></i><i></i></div>
<div class="buehne__fuss">
<div class="zaehler" aria-hidden="true"><span class="ziffern" data-ziffern><span>01</span></span><span class="mono">/ 04</span></div>
<p class="mono bildtext" data-bildtext aria-live="polite"><b>Pier 9</b><span>Signet · Wortmarke</span></p>
</div>
</div>
</div>
<div class="strom">
<article class="block aktiv" data-block data-titel="Pier 9" data-art="Signet · Wortmarke">
<div class="intro">
<nav class="navi mono" aria-label="Demo-Navigation"><span>Münster, Hafen</span><ul><li><a href="#kontakt">Arbeiten</a></li><li><a href="#kontakt" aria-current="page">Leistungen</a></li><li><a href="#kontakt">Kontakt</a></li></ul></nav>
</div>
<div class="intro">
<h1 class="h1">Marken, die <em>stehen</em> bleiben.</h1>
<p class="vorspann">Wir gestalten Zeichen, Schrift und Auftritt für Cafés, Läden und kleine Häuser. Vier Dinge machen wir besonders gern.</p>
</div>
<div class="erst">
<p class="block__nr mono"><b>01</b><span>Signet & Wortmarke</span></p>
<h2 class="h3">Ein Zeichen, das überall trägt.</h2>
<p class="text">Auf dem Kaffeebecher genauso wie auf der Markise. Signet und Wortmarke entstehen aus einer einzigen Idee und werden früh in echter Größe geprüft.</p>
<p class="mono hinweis">Weiter scrollen</p>
</div>
</article>
<article class="block" data-block data-titel="Kornblume" data-art="Editorial Design">
<p class="block__nr mono"><b>02</b><span>Editorial Design</span></p>
<h2 class="h3">Ein Raster, das <em>Brüche</em> erlaubt.</h2>
<p class="text">Magazine, Kataloge, Jahresberichte. Wir bauen ein Raster, das Ordnung hält, und lassen bewusst Stellen offen, an denen die Typografie aus der Reihe tanzt.</p>
<ul class="liste mono"><li>Raster</li><li>Satzspiegel</li><li>Titelgestaltung</li></ul>
<a class="mehr" href="#kontakt">Kornblume ansehen <span aria-hidden="true">→</span></a>
</article>
<article class="block" data-block data-titel="Radhaus Lütke" data-art="Markenauftritt">
<p class="block__nr mono"><b>03</b><span>Markenauftritt</span></p>
<h2 class="h3">Vom Schild bis zur <em>Speisekarte</em>.</h2>
<p class="text">Ein Logo allein macht noch keinen Laden. Wir übersetzen das Zeichen in Farben, Schrift und Regeln, damit Tafel, Website und Becher dieselbe Sprache sprechen.</p>
<ul class="liste mono"><li>Farbsystem</li><li>Beschilderung</li><li>Speisekarte</li></ul>
<a class="mehr" href="#kontakt">Radhaus Lütke ansehen <span aria-hidden="true">→</span></a>
</article>
<article class="block" data-block data-titel="Tomás Reiner" data-art="Personal Branding">
<p class="block__nr mono"><b>04</b><span>Personal Branding</span></p>
<h2 class="h3">Wenn der Mensch die <em>Marke</em> ist.</h2>
<p class="text">Für Musikerinnen, Handwerker und Selbstständige, die selbst auf der Bühne stehen. Ein Auftritt mit Haltung, der auf Plakat und Visitenkarte gleich gut funktioniert.</p>
<ul class="liste mono"><li>Bildmarke</li><li>Plakat</li><li>Visitenkarte</li></ul>
<a class="mehr" href="#kontakt">Tomás Reiner ansehen <span aria-hidden="true">→</span></a>
</article>
</div>
</section>
<!-- Variante B: Sticky-Titel (Spalte 320 px, top 8em), Karten scrollen -->
<section class="split-titel" data-variante="titel" aria-label="Ausgewählte Arbeiten" hidden>
<div class="titelspalte">
<p class="mono">Studio Wendel · Ausgewählte Arbeiten</p>
<h2 class="h2">Vier Marken, <em>eine</em> Haltung.</h2>
<p class="text">Jedes Projekt beginnt mit einem Gespräch vor Ort. Was dabei herauskommt, sieht man rechts.</p>
<ol class="index" data-index>
<li class="an"><span class="mono">01</span>Bäckerei Overkamp</li>
<li><span class="mono">02</span>Lindholm PR</li>
<li><span class="mono">03</span>kio</li>
<li><span class="mono">04</span>Sechs Marken, ein Blatt</li>
</ol>
</div>
<div class="leiste" aria-hidden="true"><div class="leiste__innen">
<p class="leiste__zeile mono"><b data-leiste-titel>Bäckerei Overkamp</b><span data-leiste-nr>01 / 04</span></p>
<div class="leiste__balken"><i data-leiste-balken></i></div>
</div></div>
<div class="karten">
<article class="karte aktiv" data-karte data-titel="Bäckerei Overkamp">
<div class="karte__bild"><svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" viewBox="0 0 1200 800" role="img" aria-label="Rundes Abzeichen der Bäckerei Overkamp mit Ähre und Umschrift, hell auf Schwarz">
<rect width="1200" height="800" fill="#141312"/>
<defs><path id="ok-kreis" d="M600 240a160 160 0 1 1 0 320a160 160 0 1 1 0-320"/></defs>
<circle cx="600" cy="400" r="214" fill="none" stroke="#efe6d4" stroke-width="4"/><circle cx="600" cy="400" r="128" fill="none" stroke="#efe6d4" stroke-width="2"/>
<text font-family="'Geist Mono', monospace" font-size="24" letter-spacing="7" fill="#efe6d4"><textPath href="#ok-kreis">BÄCKEREI OVERKAMP · SEIT 1931 · TELGTE ·</textPath></text>
<g fill="#efe6d4"><path d="M600 300V500" stroke="#efe6d4" stroke-width="5"/><ellipse cx="580" cy="320" rx="11" ry="26" transform="rotate(-28 580 320)"/><ellipse cx="620" cy="320" rx="11" ry="26" transform="rotate(28 620 320)"/><ellipse cx="580" cy="354" rx="11" ry="26" transform="rotate(-28 580 354)"/><ellipse cx="620" cy="354" rx="11" ry="26" transform="rotate(28 620 354)"/><ellipse cx="580" cy="388" rx="11" ry="26" transform="rotate(-28 580 388)"/><ellipse cx="620" cy="388" rx="11" ry="26" transform="rotate(28 620 388)"/><ellipse cx="580" cy="422" rx="11" ry="26" transform="rotate(-28 580 422)"/><ellipse cx="620" cy="422" rx="11" ry="26" transform="rotate(28 620 422)"/><ellipse cx="580" cy="456" rx="11" ry="26" transform="rotate(-28 580 456)"/><ellipse cx="620" cy="456" rx="11" ry="26" transform="rotate(28 620 456)"/><ellipse cx="600" cy="300" rx="10" ry="24"/></g>
</svg></div>
<p class="karte__zeile mono"><b>01 · Bäckerei Overkamp</b><span>Abzeichen · Stempel</span></p>
<h3 class="h3">Ein Abzeichen wie aus dem Ladenfenster.</h3>
<p class="text">Gezeichnet für Prägung, Stempel und Fensterfolie. Die Ähre hält das runde Zeichen zusammen.</p>
</article>
<article class="karte" data-karte data-titel="Lindholm PR">
<div class="karte__bild"><svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" viewBox="0 0 1200 800" role="img" aria-label="Wortmarke Lindholm, Presse- und Medienarbeit, mit L als Sprechblase, weiß auf Orange">
<rect width="1200" height="800" fill="#e2622d"/>
<path d="M330 290h56v160h88v56H362l-32 34Z" fill="#fff"/>
<text x="510" y="472" font-family="'Instrument Sans', sans-serif" font-weight="600" font-size="128" letter-spacing="-4" fill="#fff">lindholm</text>
<text x="514" y="530" font-family="'Geist Mono', monospace" font-size="24" letter-spacing="6" fill="#fff" fill-opacity=".85">PRESSE- UND MEDIENARBEIT</text>
</svg></div>
<p class="karte__zeile mono"><b>02 · Lindholm PR</b><span>Wortmarke · Ausstattung</span></p>
<h3 class="h3">Klar wie eine gute Pressemitteilung.</h3>
<p class="text">Ein L als Sprechblase, eine Hausfarbe, die man im Postfach sofort wiedererkennt. Mehr braucht eine Agentur für Medienarbeit nicht.</p>
</article>
<article class="karte" data-karte data-titel="kio">
<div class="karte__bild"><svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" viewBox="0 0 1200 800" role="img" aria-label="Bildmarke kio in runden weißen Buchstaben auf kräftigem Blau, der i-Punkt sitzt als gelber Kreis in der Mitte">
<rect width="1200" height="800" fill="#2346c9"/>
<g fill="none" stroke="#fff" stroke-width="58" stroke-linecap="round">
<path d="M392 250V560M392 452l118-112M440 408l84 152"/>
<path d="M600 410V560"/>
<circle cx="760" cy="486" r="74"/>
</g>
<circle cx="600" cy="300" r="40" fill="#ffd23f"/>
</svg></div>
<p class="karte__zeile mono"><b>03 · kio</b><span>Bildmarke</span></p>
<h3 class="h3">Drei Buchstaben, ein Punkt.</h3>
<p class="text">Die Buchstaben teilen sich die Strichstärke und die runden Enden. Der gelbe Punkt trägt das Zeichen bis ins kleinste Favicon.</p>
</article>
<article class="karte" data-karte data-titel="Sechs Marken, ein Blatt">
<div class="karte__bild"><svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" viewBox="0 0 1200 800" role="img" aria-label="Sechs erfundene Logos auf einem Raster: Fjell, Okra, Mühlenweg, Salz und Lake, Novo, Haldenhof">
<rect width="1200" height="800" fill="#ecebe6"/>
<path d="M440 120V680M760 120V680M140 400H1060" stroke="#1d1b18" stroke-opacity=".14" stroke-width="2"/>
<g transform="translate(290 250)"><g fill="#1d1b18"><path d="M-40 26 0-34l40 60Z"/></g><text y="88" text-anchor="middle" font-family="'Geist Mono', monospace" font-size="22" letter-spacing="5" fill="#1d1b18">FJELL</text></g><g transform="translate(610 250)"><g fill="#1d1b18"><circle r="32"/><path d="M0 -32q26 30 0 64" fill="#ecebe6"/></g><text y="88" text-anchor="middle" font-family="'Geist Mono', monospace" font-size="22" letter-spacing="5" fill="#1d1b18">OKRA</text></g><g transform="translate(930 250)"><g fill="#1d1b18"><path d="M-6-38h12v76h-12ZM-38-6h76v12h-76Z" transform="rotate(45)"/></g><text y="88" text-anchor="middle" font-family="'Geist Mono', monospace" font-size="22" letter-spacing="5" fill="#1d1b18">MÜHLENWEG</text></g><g transform="translate(290 540)"><g fill="#1d1b18"><rect x="-30" y="-30" width="60" height="60"/><path d="M-30 6q15-12 30 0t30 0" stroke="#ecebe6" stroke-width="6" fill="none"/></g><text y="88" text-anchor="middle" font-family="'Geist Mono', monospace" font-size="22" letter-spacing="5" fill="#1d1b18">SALZ & LAKE</text></g><g transform="translate(610 540)"><g fill="#1d1b18"><circle r="34"/><path d="M-14 16V-16l28 32V-16" stroke="#ecebe6" stroke-width="7" fill="none" stroke-linejoin="round"/></g><text y="88" text-anchor="middle" font-family="'Geist Mono', monospace" font-size="22" letter-spacing="5" fill="#1d1b18">NOVO</text></g><g transform="translate(930 540)"><g fill="#1d1b18"><path d="M-34 34V-4L0-34l34 30v38Z"/></g><text y="88" text-anchor="middle" font-family="'Geist Mono', monospace" font-size="22" letter-spacing="5" fill="#1d1b18">HALDENHOF</text></g>
</svg></div>
<p class="karte__zeile mono"><b>04 · Sechs Marken, ein Blatt</b><span>Logosammlung</span></p>
<h3 class="h3">Jedes Zeichen mit eigener Stimme.</h3>
<p class="text">Von der Bergsportmarke bis zum Hofladen. Sechs Logos aus sehr verschiedenen Branchen, alle nach denselben Regeln gezeichnet.</p>
</article>
</div>
</section>
<!-- archiv:start -->
<!-- Variante C: Archiv. Liste scrollt, Vorschau steht fest und blendet über (Welt: Fotografin, Rezept fotograf-film-bild-zuerst) -->
<section class="split-archiv" data-variante="archiv" aria-label="Archiv" hidden>
<div class="arch-vorschau">
<p class="arch-kopf"><span class="arch-name">Hanne Brockmöller</span><span class="a-mono">Fotografie · Hamburg</span></p>
<figure class="arch-rahmen">
<img src="bilder/split-screen-sticky-seiten-archiv-1.jpg" alt="Watt bei Ebbe im warmen Gegenlicht, flache Wasserstreifen spiegeln die tiefe Sonne" width="800" height="1000" class="an" data-arch-bild>
<img src="bilder/split-screen-sticky-seiten-archiv-2.jpg" alt="Fast weißer Nebel über der Elbe, ein Schiff nur als blasser Schatten" width="800" height="1000" loading="lazy" data-arch-bild>
<img src="bilder/split-screen-sticky-seiten-archiv-3.jpg" alt="Tiefblauer Himmel mit rosa Streifen am Horizont, darunter dunkle Brandung" width="800" height="1000" loading="lazy" data-arch-bild>
<img src="bilder/split-screen-sticky-seiten-archiv-4.jpg" alt="Reihe alter Holzpfähle, die in graugrünes Wasser hinausläuft" width="800" height="1000" loading="lazy" data-arch-bild>
<img src="bilder/split-screen-sticky-seiten-archiv-5.jpg" alt="Helle Sonne über dunkler Ostsee, breiter Lichtpfad auf dem Wasser" width="800" height="1000" loading="lazy" data-arch-bild>
<img src="bilder/split-screen-sticky-seiten-archiv-6.jpg" alt="Nacht über der Hallig, Vollmond mit schmaler Lichtsäule im Wasser" width="800" height="1000" loading="lazy" data-arch-bild>
<img src="bilder/split-screen-sticky-seiten-archiv-7.jpg" alt="Zugefrorener See unter hellgrauem Himmel, am Horizont eine dunkle Schilfkante" width="800" height="1000" loading="lazy" data-arch-bild>
<img src="bilder/split-screen-sticky-seiten-archiv-8.jpg" alt="Helle Düne mit Strandhafer im Vordergrund unter blassem Himmel" width="800" height="1000" loading="lazy" data-arch-bild>
</figure>
<p class="arch-unterschrift a-mono" aria-live="polite"><span data-arch-nr>01 / 08</span><b data-arch-titel>Ebbe, Nachmittag</b><span data-arch-ort>Wattenmeer</span></p>
</div>
<div class="arch-liste">
<header class="arch-titel">
<p class="arch-bio"><b>Hanne Brockmöller</b> fotografiert Küsten und Wasser in Norddeutschland, meist mit langer Belichtung. Aufträge für Verlage und Tourismus, dazwischen freie Serien.</p>
<h2>Archiv <i>2021–2026</i></h2>
<p class="a-mono">8 Serien · neueste zuerst</p>
</header>
<ol class="arch-reihen">
<li><a class="arch-zeile an" href="#kontakt" data-arch data-titel="Ebbe, Nachmittag" data-ort="Wattenmeer"><span class="a-mono">2026</span><span class="t">Ebbe, Nachmittag</span><span class="a-mono o">Wattenmeer</span><span class="a-mono n">18 Bilder</span></a></li>
<li><a class="arch-zeile" href="#kontakt" data-arch data-titel="Nebelbank" data-ort="Elbe, Wittenbergen"><span class="a-mono">2025</span><span class="t">Nebelbank</span><span class="a-mono o">Elbe, Wittenbergen</span><span class="a-mono n">24 Bilder</span></a></li>
<li><a class="arch-zeile" href="#kontakt" data-arch data-titel="Blaue Stunde" data-ort="Sylt, Weststrand"><span class="a-mono">2025</span><span class="t">Blaue Stunde</span><span class="a-mono o">Sylt, Weststrand</span><span class="a-mono n">31 Bilder</span></a></li>
<li><a class="arch-zeile" href="#kontakt" data-arch data-titel="Pfähle" data-ort="Dangast"><span class="a-mono">2024</span><span class="t">Pfähle</span><span class="a-mono o">Dangast</span><span class="a-mono n">40 Bilder</span></a></li>
<li><a class="arch-zeile" href="#kontakt" data-arch data-titel="Gegenlicht" data-ort="Ostsee, Ahrenshoop"><span class="a-mono">2024</span><span class="t">Gegenlicht</span><span class="a-mono o">Ostsee, Ahrenshoop</span><span class="a-mono n">22 Bilder</span></a></li>
<li><a class="arch-zeile" href="#kontakt" data-arch data-titel="Mondwasser" data-ort="Hallig Hooge"><span class="a-mono">2023</span><span class="t">Mondwasser</span><span class="a-mono o">Hallig Hooge</span><span class="a-mono n">16 Bilder</span></a></li>
<li><a class="arch-zeile" href="#kontakt" data-arch data-titel="Schneelicht" data-ort="Dümmer See"><span class="a-mono">2022</span><span class="t">Schneelicht</span><span class="a-mono o">Dümmer See</span><span class="a-mono n">12 Bilder</span></a></li>
<li><a class="arch-zeile" href="#kontakt" data-arch data-titel="Dünenrand" data-ort="Amrum"><span class="a-mono">2021</span><span class="t">Dünenrand</span><span class="a-mono o">Amrum</span><span class="a-mono n">20 Bilder</span></a></li>
</ol>
</div>
</section>
<!-- archiv:ende -->
<footer class="abspann" id="kontakt">
<p class="mono">Ende der Sektion · hier löst sich die Sticky-Spalte</p>
<p class="h1">Neues Projekt? <em>Erzählen Sie.</em></p>
<div class="abspann__zeile mono"><span>Studio Wendel · Münster</span><span>Termine dienstags und donnerstags</span></div>
</footer>
<div class="steuer mono">
<div class="modi" role="group" aria-label="Variante">
<button type="button" data-wahl="bild" aria-pressed="true">Bild steht</button>
<button type="button" data-wahl="titel" aria-pressed="false">Titel steht</button>
<button type="button" data-wahl="archiv" aria-pressed="false">Archiv</button>
</div>
<p class="werte" data-werte aria-live="polite"></p>
</div>
<script>
(() => {
const html = document.documentElement;
const reduziert = () => html.classList.contains('reduziert');
const DAUER = 1200; // Clip-Reveal, ms
const WERTE = {
bild: '<b>sticky</b> top 0 · 100svh · Spalten 1fr 1fr · <b>Sync</b> IO rootMargin −50% 0 −50% 0 · <b>Clip</b> inset(100% 0 0 0) → 0 · 1200 ms · <b>Bild</b> scale 1.12 → 1 · 1600 ms · expo.out',
titel: '<b>sticky</b> top 8em · <b>Spalte</b> 320px fest · <b>Sync</b> IO rootMargin −50% 0 −50% 0 · <b>Marker</b> 600 ms · expo.out · inaktiv opacity .34',
archiv: '<b>sticky</b> top 0 · 100svh · Spalten 5fr 7fr · <b>Sync</b> IO −50% oder Hover · <b>Crossfade</b> opacity 0 → 1 · 600 ms · cubic-bezier(0.455, 0.03, 0.515, 0.955) · Zeilen 200 ms'
};
const sektionen = { bild: document.querySelector('[data-variante="bild"]'), titel: document.querySelector('[data-variante="titel"]'), archiv: document.querySelector('[data-variante="archiv"]') };
const knoepfe = [...document.querySelectorAll('[data-wahl]')];
const werteFeld = document.querySelector('[data-werte]');
// Variante aus der URL (?v=bild|titel|archiv), unbekannt oder leer: erste Variante
const VARIANTEN = Object.keys(sektionen);
const ausUrl = new URLSearchParams(location.search).get('v');
let variante = VARIANTEN.includes(ausUrl) ? ausUrl : VARIANTEN[0];
/* Variante A: Bildstapel in der Sticky-Spalte */
const ebenen = [...document.querySelectorAll('.ebene')];
const bloecke = [...document.querySelectorAll('[data-block]')];
const striche = [...document.querySelectorAll('.striche i')];
const ziffern = document.querySelector('[data-ziffern]');
const bildtext = document.querySelector('[data-bildtext]');
let aktivBild = 0, ebeneZ = 1, aufraeumen = null;
function zeigeBild(n, sofort) {
if (n === aktivBild && !sofort) return;
const richtung = n > aktivBild ? 1 : -1;
const ebene = ebenen[n], bild = ebene.querySelector('img, svg');
clearTimeout(aufraeumen);
// Startzustand ohne Übergang: von unten aufziehen (vorwärts) bzw. von oben (rückwärts)
ebene.style.transition = 'none'; bild.style.transition = 'none';
ebene.classList.remove('sichtbar');
ebene.style.clipPath = richtung > 0 ? 'inset(100% 0 0 0)' : 'inset(0 0 100% 0)';
bild.style.scale = reduziert() ? '1' : '1.12';
ebene.style.zIndex = ++ebeneZ;
ebene.getBoundingClientRect();
ebene.style.transition = ''; bild.style.transition = '';
ebene.style.clipPath = ''; bild.style.scale = '';
ebene.classList.add('sichtbar');
// Ältere Ebenen erst verstecken, wenn die neue sie ganz verdeckt
aufraeumen = setTimeout(() => ebenen.forEach((e, i) => { if (i !== n) e.classList.remove('sichtbar'); }), reduziert() ? 300 : DAUER + 100);
bloecke.forEach((b, i) => b.classList.toggle('aktiv', i === n));
striche.forEach((s, i) => s.classList.toggle('an', i === n));
rolleZiffer(String(n + 1).padStart(2, '0'), richtung);
bildtext.innerHTML = '<b>' + bloecke[n].dataset.titel + '</b><span>' + bloecke[n].dataset.art + '</span>';
aktivBild = n;
}
function rolleZiffer(wert, richtung) {
const alt = ziffern.lastElementChild;
if (alt && alt.textContent === wert) return;
const neu = document.createElement('span');
neu.textContent = wert;
if (reduziert() || !alt) { ziffern.replaceChildren(neu); return; }
neu.style.transform = `translateY(${richtung * 100}%)`;
ziffern.append(neu);
neu.getBoundingClientRect();
neu.style.transform = 'translateY(0)';
alt.style.transform = `translateY(${-richtung * 100}%)`;
setTimeout(() => alt.remove(), DAUER);
[...ziffern.children].slice(0, -2).forEach(s => s.remove());
}
/* Variante B: Sticky-Titel mit Index */
const karten = [...document.querySelectorAll('[data-karte]')];
const indexEintraege = [...document.querySelectorAll('[data-index] li')];
const leisteTitel = document.querySelector('[data-leiste-titel]');
const leisteNr = document.querySelector('[data-leiste-nr]');
const leisteBalken = document.querySelector('[data-leiste-balken]');
let aktivKarte = 0;
function zeigeKarte(n) {
karten.forEach((k, i) => k.classList.toggle('aktiv', i === n));
indexEintraege.forEach((e, i) => e.classList.toggle('an', i === n));
leisteTitel.textContent = karten[n].dataset.titel;
leisteNr.textContent = String(n + 1).padStart(2, '0') + ' / 04';
leisteBalken.style.transform = `scaleX(${(n + 1) / karten.length})`;
aktivKarte = n;
}
/* Variante C: Archiv. Alle Bilder liegen mit alt im DOM, die Vorschau blendet nur über */
const archZeilen = [...document.querySelectorAll('[data-arch]')];
const archBilder = [...document.querySelectorAll('[data-arch-bild]')];
const archNr = document.querySelector('[data-arch-nr]');
const archTitel = document.querySelector('[data-arch-titel]');
const archOrt = document.querySelector('[data-arch-ort]');
const BLENDE = 600; // Crossfade, ms
let aktivArchiv = 0, perScroll = 0, zeigtHover = false, blendUhr = null;
function zeigeArchiv(n) {
if (n < 0 || n === aktivArchiv) return;
clearTimeout(blendUhr);
const alt = archBilder[aktivArchiv], neu = archBilder[n];
archBilder.forEach(b => { if (b !== alt && b !== neu) b.classList.remove('an', 'vorher'); });
alt.classList.remove('an'); alt.classList.add('vorher'); // das alte Bild bleibt stehen, das neue blendet darüber ein
neu.classList.remove('vorher'); neu.classList.add('an');
blendUhr = setTimeout(() => alt.classList.remove('vorher'), reduziert() ? 220 : BLENDE + 40);
archZeilen.forEach((z, i) => z.classList.toggle('an', i === n));
archNr.textContent = String(n + 1).padStart(2, '0') + ' / ' + String(archZeilen.length).padStart(2, '0');
archTitel.textContent = archZeilen[n].dataset.titel;
archOrt.textContent = archZeilen[n].dataset.ort;
aktivArchiv = n;
}
// Hover und Fokus übersteuern die Scroll-Synchronisation, bis der Zeiger die Liste verlässt
archZeilen.forEach((z, i) => {
z.addEventListener('pointerenter', e => { if (e.pointerType === 'mouse') { zeigtHover = true; zeigeArchiv(i); } });
z.addEventListener('focus', () => zeigeArchiv(i));
z.addEventListener('click', e => e.preventDefault());
});
const archListe = document.querySelector('.arch-reihen');
archListe.addEventListener('pointerleave', () => { if (zeigtHover) { zeigtHover = false; zeigeArchiv(perScroll); } });
/* Synchronisation: aktiv ist der Block, der die Viewport-Mitte schneidet */
const io = new IntersectionObserver(eintraege => eintraege.forEach(e => {
if (!e.isIntersecting) return;
const i = bloecke.indexOf(e.target);
if (i > -1) { zeigeBild(i); return; }
const a = archZeilen.indexOf(e.target);
if (a > -1) { perScroll = a; if (!zeigtHover) zeigeArchiv(a); return; }
zeigeKarte(karten.indexOf(e.target));
}), { rootMargin: '-50% 0px -50% 0px' });
[...bloecke, ...karten, ...archZeilen].forEach(el => io.observe(el));
function setzeVariante(v) {
variante = v;
Object.entries(sektionen).forEach(([k, s]) => { s.hidden = k !== v; });
knoepfe.forEach(b => b.setAttribute('aria-pressed', String(b.dataset.wahl === v)));
werteFeld.innerHTML = WERTE[v];
}
function schreibeUrl(v) {
const u = new URL(location.href);
u.searchParams.set('v', v); // andere Parameter (reduziert, vorschau) bleiben stehen
history.replaceState(history.state, '', u);
}
knoepfe.forEach(b => b.addEventListener('click', () => { pause(); setzeVariante(b.dataset.wahl); schreibeUrl(b.dataset.wahl); scrollTo(0, 0); }));
/* Vorführung der aktuellen Variante: Selbst-Scroll von Block zu Block mit Halt, am Ende löst sich die Spalte.
Im Archiv sind die Zeilen kurz, also kürzere Fahrt und kürzerer Halt. */
const TAKT = { bild: [1100, 1500], titel: [1100, 1500], archiv: [700, 1100] };
let FAHRT = 1100, HALT = 1500;
let uhr = null, plan = [], t0 = 0;
const weich = x => x < .5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2; // Kamerafahrt, nicht die Effektkurve
function zielY(el) { const r = el.getBoundingClientRect(); return r.top + scrollY + r.height / 2 - innerHeight / 2; }
function planen() {
const s = sektionen[variante];
[FAHRT, HALT] = TAKT[variante];
const ziele = ({ bild: bloecke, titel: karten, archiv: archZeilen })[variante].slice(1).map(zielY);
const ende = s.offsetTop + s.offsetHeight - innerHeight * .55;
const punkte = [0, ...ziele, ende];
plan = []; let t = 900;
for (let i = 1; i < punkte.length; i++) { plan.push({ von: punkte[i - 1], nach: punkte[i], t0: t, t1: t + FAHRT }); t += FAHRT + HALT; }
return t;
}
function vorfuehren() {
pause();
html.classList.add('vorfuehrung');
scrollTo(0, 0);
zeigtHover = false;
if (variante === 'bild') zeigeBild(0, true); else if (variante === 'titel') zeigeKarte(0); else zeigeArchiv(0);
const laenge = planen();
t0 = performance.now();
const schritt = jetzt => {
const t = jetzt - t0;
if (t > laenge) { vorfuehren(); return; }
const f = plan.find(p => t < p.t1) || plan[plan.length - 1];
let y = f.von;
if (t >= f.t0) y = reduziert() ? f.nach : f.von + (f.nach - f.von) * weich(Math.min(1, (t - f.t0) / FAHRT));
scrollTo(0, y);
uhr = requestAnimationFrame(schritt);
};
uhr = requestAnimationFrame(schritt);
}
function pause() { cancelAnimationFrame(uhr); uhr = null; html.classList.remove('vorfuehrung'); }
function neustart() { pause(); scrollTo(0, 0); zeigeBild(0, true); zeigeKarte(0); zeigtHover = false; zeigeArchiv(0); }
function weiter() { if (!uhr) vorfuehren(); }
['wheel', 'touchstart', 'keydown'].forEach(t => addEventListener(t, () => { if (uhr && !html.classList.contains('vorschau')) pause(); }, { passive: true }));
setzeVariante(variante);
})();
</script>
</body>
</html>