{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "vt-cross-document-mpa",
 "name": "Native Seitenübergänge zwischen echten Seiten (Cross-document View Transitions)",
 "name_en": "Cross-document view transitions (MPA)",
 "kurz": "Echte Seitenaufrufe mit App-Gefühl: Der Kopf bleibt stehen, das Bild wächst aus der Karte zur Detailseite, und das Ganze steckt in einer einzigen CSS-Zeile.",
 "kategorie": "Seitenübergänge",
 "kategorie_slug": "seitenuebergaenge",
 "kategorie_nr": 1,
 "bau_chat": "C3",
 "prioritaet": "A",
 "trendstatus": "aufsteigend",
 "belegstatus": "belegt",
 "website_belege": 4,
 "stimmung": [
  "ruhig",
  "editorial",
  "präzise",
  "luxuriös"
 ],
 "stimmung_roh": [
  "ruhig",
  "editorial",
  "technisch",
  "hochwertig"
 ],
 "technik": [
  "css",
  "view-transitions",
  "vanilla-js"
 ],
 "technik_gruppen": [
  "css",
  "js"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Beide Seiten (gleiche Origin) setzen in CSS @view-transition { navigation: auto; }. Beim Klick auf einen normalen Link macht der Browser einen Schnappschuss der alten Seite, lädt die neue ganz normal und blendet über. Standard ist ein Crossfade von ::view-transition-old(root) zu ::view-transition-new(root). Elemente mit demselben view-transition-name auf beiden Seiten lösen sich aus dem Crossfade und morphen in Position und Größe. Mit den Events pageswap (alte Seite, letzter Frame) und pagereveal (neue Seite, vor dem ersten Rendern) vergibt man Namen erst kurz vor dem Schnappschuss, liest navigation.activation (von welcher zu welcher URL) und setzt Typen wie viewTransition.types.add('forwards'). Mit html:active-view-transition-type(forwards) steuert man je Typ eigene Keyframes. Optional hält <link rel=\"expect\" blocking=\"render\" href=\"#hero\"> das erste Rendern zurück, bis das Ziel-Element im DOM ist.",
  "warum_es_wirkt": "Die Seite fühlt sich wie eine App an, obwohl jede Navigation ein echter Seitenaufruf bleibt. Zurück-Button, Scroll-Wiederherstellung, Deep Links, Fokus, Ansage des Seitentitels und Analytics funktionieren ohne Nachbau. Es kostet kaum Gewicht und hat keine SPA-Nebenwirkungen wie doppelte Listener oder Embeds, die nicht neu starten.",
  "wann_einsetzen": "Bei Portfolio-, Studio-, Editorial- und Shop-Seiten mit klassischem Multi-Page-Aufbau, etwa Astro, Eleventy, WordPress, Webflow oder statisches HTML. Immer dann, wenn Crossfade, Wipe, Slide, Vorhang oder ein Shared-Element-Morph reichen.",
  "wann_nicht": "Wenn die Animation unterwegs reagieren soll, etwa gestaffelt per Split-Text oder physikbasiert: Schnappschüsse lassen sich nach dem Start nicht mehr umchoreografieren. Nicht, wenn WebGL über den Seitenwechsel weiterlaufen soll, und nicht für Navigationen zu einer anderen Origin. Firefox zeigt Stand Herbst 2026 noch einen normalen Seitenwechsel.",
  "varianten": [
   "Reiner Root-Crossfade: Standard, ohne eine Zeile JS",
   "Root mit eigenem Keyframe: Wipe, Slide oder Scale-Fade",
   "Mit benannten Elementen: Header bleibt stehen, Bild und Titel morphen",
   "Typgesteuert: vorwärts und zurück, Übersicht zu Detail und Detail zu Übersicht",
   "Selektiv aktiviert: Übergang nur für bestimmte Navigationen, Typ in pageswap gesetzt (Google AI Mode)",
   "Mit Splash-Element: ein verstecktes Element mit eigenem view-transition-name, das nur während des Übergangs sichtbar ist (Usecue)",
   "Quelle hervorheben: a:navigation-source bekommt einen eigenen view-transition-name, der angeklickte Link hebt sich im Übergang ab (Chrome 156, nur Chromium; Rückfall per Klick-Markierung)"
  ],
  "umsetzung": "Global in CSS: @view-transition { navigation: auto; }. Namen über eine CSS-Variable vergeben oder im pageswap-Handler setzen und nach viewTransition.finished wieder entfernen, damit sie eindeutig bleiben. Den pagereveal-Listener als klassisches, parser-blockierendes Script im <head> registrieren. Typen übernimmt die neue Seite nicht von der alten, sie müssen dort erneut gesetzt werden. Dauer und Kurve setzt man auf ::view-transition-group(*), ::view-transition-old(*) und ::view-transition-new(*). Bei Bildern mit anderem Seitenverhältnis auf beiden Seiten ::view-transition-old/new(name) { height: 100%; object-fit: cover } setzen. Fallstricke: Navigationen über 4 s bricht Chrome mit TimeoutError ab. Bilder auf der Zielseite blockieren das Rendern, deshalb mit Speculation Rules vorrendern. view-transition-name erzeugt einen neuen Stacking Context. Width/Height-Keyframes laufen auf dem Main Thread, besser auf transform umrechnen. Keine Übergänge per Hover auslösen, weil die Pseudo-Ebene Hover blockiert. Den angeklickten Link trifft seit Chrome 156 (20.10.2026) der Selektor :navigation-source, ohne JavaScript: a:navigation-source { view-transition-name: quelle } auf der alten Seite. Firefox und Safari kennen ihn noch nicht (Stand 02.11.2026), deshalb in @supports selector(:navigation-source) und als eigene Regel; der Rückfall merkt sich den Link beim Klick oder liest NavigateEvent.sourceElement und setzt den Namen in pageswap.",
  "mobil": "Läuft auf iOS Safari ab 18.2 und auf Chrome für Android. Auf schwachen Geräten können automatisch erzeugte Größen-Animationen Frames verlieren (Google-Fallstudie), deshalb transform-Keyframes bevorzugen.",
  "reduzierte_bewegung": "@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } } ergibt einen normalen Seitenwechsel, ganz ohne JS. Alternativ Namen nur unter prefers-reduced-motion: no-preference vergeben, dann bleibt ein ruhiger Crossfade.",
  "barrierefreiheit": "Fokus, Ansage des Seitentitels und Zurück-Navigation bleiben nativ, das ist der größte Vorteil. Während der Animation ist die Pseudo-Ebene nicht bedienbar, deshalb den Übergang kurz halten."
 },
 "messwerte": {
  "easing": "Browser-Default ease; für Seiten-Wipes typischerweise cubic-bezier(0.76,0,0.24,1) oder ease-out",
  "dauer_ms": "Default 250; Seitenübergänge 400–700 typisch; Policybazaar setzt die Root-Dauer auf 400",
  "stagger_ms": "manuell über --index * 40–80 ms (typisch)",
  "distanz": "",
  "sonstiges": "Chrome bricht ab 4 s Navigationsdauer ab (beobachtet, developer.chrome.com)",
  "herkunft": "beobachtet",
  "quelle": "https://developer.chrome.com/docs/web-platform/view-transitions/cross-document"
 },
 "kurve": {
  "bezier": [
   0.25,
   0.1,
   0.25,
   1
  ],
  "css": "cubic-bezier(0.25, 0.1, 0.25, 1)",
  "name": "ease",
  "dauer_ms": 250
 },
 "gesehen_bei": [
  {
   "seite": "Google Search: Wechsel in den AI Mode",
   "url": "https://developer.chrome.com/blog/google-ai-mode-view-transitions-case-study",
   "auszeichnung": "",
   "beobachtung": "Cross-document View Transitions nur für AI-Mode-Navigationen. Typ 'ai-mode' wird in pageswap gesetzt, view-transition-name nur über html:active-view-transition-type(ai-mode). Render-Blocking per <link> nur auf früh gerenderte Elemente, dazu ein Watchdog-Timer. z-index liegt auf den Pseudo-Elementen statt auf den Originalen.",
   "art": "artikel"
  },
  {
   "seite": "Usecue: Nachbau des Brand-Creatives-Vorhangs",
   "url": "https://www.usecue.com/blog/page-transitions-done-right/",
   "auszeichnung": "",
   "beobachtung": "Der pinke Vorhang von Brand Creatives (dort Barba.js, GSAP, Lenis und Webflow, rund 180 kB plus etwa 750 Zeilen Code) wird mit @view-transition, einem Splash-Element mit view-transition-name, pagereveal, clip-path und shape() für die gebogene Kante in etwa 80 Zeilen CSS nachgebaut.",
   "art": "artikel"
  },
  {
   "seite": "Cyd Stumpel: Projekte Broed, Kota und Visdeurbel (Vortrag)",
   "url": "https://conffab.com/presentation/css-tried-to-come-for-my-job-a-practical-guide-to-view-transitions-for-creative-developers/",
   "auszeichnung": "Kota: laut Studio-Blog Awwwards Honorable Mention (Zuordnung zu genau dieser Seite unsicher)",
   "beobachtung": "Laut Vortrag setzen diese Produktionsseiten View Transitions ein: Übersicht zu Detail mit Typen, gestaffelte Karten über manuelle --index-Variable und Namen nur unter prefers-reduced-motion: no-preference.",
   "art": "artikel"
  },
  {
   "seite": "Una Kravets (una.im)",
   "url": "https://una.im/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft (_slug_.B9qqzX4S.css): @media not (prefers-reduced-motion: reduce){@view-transition{navigation:auto}}; Karten tragen inline view-transition-name (<slug>-img, <slug>-title).",
   "art": "website"
  },
  {
   "seite": "nerdy.dev (Adam Argyle)",
   "url": "https://nerdy.dev/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft: <style>@view-transition { navigation: auto; }</style> im Head, view-transitions.js render-blockierend mit pageswap/pagereveal-Listenern (view-transitions-toolkit).",
   "art": "website"
  },
  {
   "seite": "Dave Rupert",
   "url": "https://daverupert.com/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft (Inline-CSS): @view-transition{navigation:auto}; Logo #dave mit view-transition-name:dave-logo, ::view-transition-group(dave-logo) mit eigener Spring-Easing-Variable; reduced-motion setzt den Namen auf none.",
   "art": "website"
  },
  {
   "seite": "CSS Day",
   "url": "https://cssday.nl/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft (cssday.css): @view-transition { navigation: auto; } auf der Konferenzseite.",
   "art": "website"
  }
 ],
 "tutorials": [
  {
   "titel": "Cross-document view transitions for multi-page applications (Chrome for Developers)",
   "url": "https://developer.chrome.com/docs/web-platform/view-transitions/cross-document"
  },
  {
   "titel": "@view-transition (MDN)",
   "url": "https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/%40view-transition"
  },
  {
   "titel": "Page transitions done right (Usecue, 25.08.2026)",
   "url": "https://www.usecue.com/blog/page-transitions-done-right/"
  },
  {
   "titel": "How Google created a connected experience for AI Mode using view transitions",
   "url": "https://developer.chrome.com/blog/google-ai-mode-view-transitions-case-study"
  }
 ],
 "kombinierbar_mit": [
  "vt-shared-element-morph",
  "vorhang-farbpanel-wipe",
  "clip-path-reveal-seite",
  "richtungsbewusste-uebergaenge",
  "intro-ohne-wartezeit"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/seitenuebergaenge/vt-cross-document-mpa/",
  "meta": "https://cecodesign.de/lab/fundus/seitenuebergaenge/vt-cross-document-mpa/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/seitenuebergaenge/vt-cross-document-mpa/demo"
 },
 "herkunft": {
  "quelldateien": [
   "uebergaenge.json",
   "patch-belege-3.json"
  ],
  "pruefnotizen": [
   "patch-belege-3.json: Vier echte MPA-Seiten mit nativer Cross-Document-Transition."
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Echte Seitenaufrufe mit App-Gefühl: Der Kopf bleibt stehen, das Bild wächst aus der Karte zur Detailseite, und das Ganze steckt in einer einzigen CSS-Zeile.",
  "demo": true,
  "abhaengigkeiten": [],
  "werte": {
   "echter_einsatz": "@view-transition { navigation: auto; } in beiden Seiten (gleiche Origin)",
   "benannt_dauer_ms": 600,
   "benannt_easing": "cubic-bezier(0.76, 0, 0.24, 1)",
   "benannt_namen": "kopf (Header, bleibt stehen), held (Kartenbild ↔ Bild der Detailseite), titel (Kartentitel ↔ h1); zwischen zwei Detailseiten nur held",
   "benannt_root": "alt opacity 1 → 0 in 300 ms, neu opacity 0 → 1 in 400 ms ab 200 ms, gleiche Kurve",
   "benannt_snapshots": "::view-transition-old/new(held) { height: 100%; object-fit: cover } · ::view-transition-old/new(titel) { width: 100%; height: 100% }",
   "titel_angleich": "Kartentitel und h1 mit gleichen Schnittwerten (Fraunces wght 460, opsz 60, SOFT 100), gleicher Laufweite (-0.015em) und line-height 1, damit die Schnappschüsse deckungsgleich skalieren",
   "typen_dauer_ms": 600,
   "typen_easing": "cubic-bezier(0.76, 0, 0.24, 1)",
   "typen": "vorwaerts (Übersicht → Detail, Detail → nächste Detailseite), zurueck (Detail → Übersicht); gesetzt über startViewTransition({ update, types }) bzw. im MPA über viewTransition.types.add() in pageswap/pagereveal",
   "typ_vorwaerts": "alt translateX(0 → -30%), neu translateX(100% → 0) mit box-shadow -40px 0 80px rgba(25,24,20,.16) → 0",
   "typ_zurueck": "alt translateX(0 → 100%) mit z-index 1 und Schatten, neu translateX(-30% → 0)",
   "crossfade_dauer_ms": 400,
   "crossfade_easing": "cubic-bezier(0.25, 0.1, 0.25, 1) (ease, Browser-Kurve)",
   "crossfade": "nur ::view-transition-old/new(root), keine Namen, kein JS",
   "aspekt": "Kartenbild und Bild der Detailseite beide 4:3, damit der Morph ohne Beschnittwechsel läuft",
   "reduziert": "keine Namen, keine Typen, Root-Crossfade 250 ms cubic-bezier(0.25, 0.1, 0.25, 1)",
   "scroll": "neue Seite beginnt oben, zurück zur Übersicht stellt die Scroll-Position wieder her",
   "hover_karte": "Bild scale 1 → 1.035, 1000 ms cubic-bezier(0.16, 1, 0.3, 1)",
   "quelle": {
    "auswahl_echt": "a:navigation-source { view-transition-name: quelle } in @supports selector(:navigation-source); Chrome 156 (20.10.2026), Firefox und Safari ohne (Stand 02.11.2026)",
    "auswahl_demo": "data-quelle am angeklickten Link, gesetzt vor dem Schnappschuss (die Demo navigiert nicht wirklich); zugleich Rückfall für Browser ohne den Selektor (Klick merken oder NavigateEvent.sourceElement)",
    "markierung": "Kartenbild outline 2px solid #eac16e, outline-offset 5px; Titel bzw. Zurück-Link in #eac16e",
    "quelle_dauer_ms": 900,
    "quelle_keyframes": "scale 1 → 1.04 bis 40 %, voll sichtbar bis 70 %, dann opacity → 0; z-index 4",
    "root_alt": "opacity → 0 und brightness(.6), 400 ms",
    "root_neu": "opacity 0 → 1, 450 ms ab 300 ms",
    "easing": "cubic-bezier(0.76, 0, 0.24, 1)",
    "kopf": "bleibt stehen (Name kopf), keine Morphs von Bild und Titel",
    "reduziert": "kein Name, nur Root-Crossfade 250 ms; die Markierung erscheint statisch"
   }
  },
  "ausloeser": "klick",
  "touch": "Tippen auf ein Gericht, auf Zurück oder auf Nächster Gang löst denselben Übergang aus. Auf schmalen Bildschirmen steht das Tellerbild über dem Text, das Menü ist ausgeblendet, der Kopf zeigt nur Marke und Reservieren. Umschalter mit 34 px hohen Knöpfen, kein Hover-Zoom.",
  "reduziert": "Keine benannten Elemente, keine Typen, keine Bewegung: die Seiten überblenden in 250 ms (ease). Der Umschalter ist abgeblendet, die Werte-Anzeige nennt das.",
  "korrekturen": {
   "beschreibung": "Beide Seiten (gleiche Origin) setzen in CSS @view-transition { navigation: auto; }. Beim Klick auf einen normalen Link macht der Browser einen Schnappschuss der alten Seite, lädt die neue ganz normal und blendet über. Standard ist ein Crossfade von ::view-transition-old(root) zu ::view-transition-new(root). Elemente mit demselben view-transition-name auf beiden Seiten lösen sich aus dem Crossfade und morphen in Position und Größe. Mit den Events pageswap (alte Seite, letzter Frame) und pagereveal (neue Seite, vor dem ersten Rendern) vergibt man Namen erst kurz vor dem Schnappschuss, liest navigation.activation (von welcher zu welcher URL) und setzt Typen wie viewTransition.types.add('forwards'). Mit html:active-view-transition-type(forwards) steuert man je Typ eigene Keyframes. Optional hält <link rel=\"expect\" blocking=\"render\" href=\"#hero\"> das erste Rendern zurück, bis das Ziel-Element im DOM ist.",
   "warum_es_wirkt": "Die Seite fühlt sich wie eine App an, obwohl jede Navigation ein echter Seitenaufruf bleibt. Zurück-Button, Scroll-Wiederherstellung, Deep Links, Fokus, Ansage des Seitentitels und Analytics funktionieren ohne Nachbau. Es kostet kaum Gewicht und hat keine SPA-Nebenwirkungen wie doppelte Listener oder Embeds, die nicht neu starten.",
   "wann_einsetzen": "Bei Portfolio-, Studio-, Editorial- und Shop-Seiten mit klassischem Multi-Page-Aufbau, etwa Astro, Eleventy, WordPress, Webflow oder statisches HTML. Immer dann, wenn Crossfade, Wipe, Slide, Vorhang oder ein Shared-Element-Morph reichen.",
   "wann_nicht": "Wenn die Animation unterwegs reagieren soll, etwa gestaffelt per Split-Text oder physikbasiert: Schnappschüsse lassen sich nach dem Start nicht mehr umchoreografieren. Nicht, wenn WebGL über den Seitenwechsel weiterlaufen soll, und nicht für Navigationen zu einer anderen Origin. Firefox zeigt Stand Herbst 2026 noch einen normalen Seitenwechsel.",
   "varianten": [
    "Reiner Root-Crossfade: Standard, ohne eine Zeile JS",
    "Root mit eigenem Keyframe: Wipe, Slide oder Scale-Fade",
    "Mit benannten Elementen: Header bleibt stehen, Bild und Titel morphen",
    "Typgesteuert: vorwärts und zurück, Übersicht zu Detail und Detail zu Übersicht",
    "Selektiv aktiviert: Übergang nur für bestimmte Navigationen, Typ in pageswap gesetzt (Google AI Mode)",
    "Mit Splash-Element: ein verstecktes Element mit eigenem view-transition-name, das nur während des Übergangs sichtbar ist (Usecue)",
    "Quelle hervorheben: a:navigation-source bekommt einen eigenen view-transition-name, der angeklickte Link hebt sich im Übergang ab (Chrome 156, nur Chromium; Rückfall per Klick-Markierung)"
   ],
   "umsetzung": "Global in CSS: @view-transition { navigation: auto; }. Namen über eine CSS-Variable vergeben oder im pageswap-Handler setzen und nach viewTransition.finished wieder entfernen, damit sie eindeutig bleiben. Den pagereveal-Listener als klassisches, parser-blockierendes Script im <head> registrieren. Typen übernimmt die neue Seite nicht von der alten, sie müssen dort erneut gesetzt werden. Dauer und Kurve setzt man auf ::view-transition-group(*), ::view-transition-old(*) und ::view-transition-new(*). Bei Bildern mit anderem Seitenverhältnis auf beiden Seiten ::view-transition-old/new(name) { height: 100%; object-fit: cover } setzen. Fallstricke: Navigationen über 4 s bricht Chrome mit TimeoutError ab. Bilder auf der Zielseite blockieren das Rendern, deshalb mit Speculation Rules vorrendern. view-transition-name erzeugt einen neuen Stacking Context. Width/Height-Keyframes laufen auf dem Main Thread, besser auf transform umrechnen. Keine Übergänge per Hover auslösen, weil die Pseudo-Ebene Hover blockiert. Den angeklickten Link trifft seit Chrome 156 (20.10.2026) der Selektor :navigation-source, ohne JavaScript: a:navigation-source { view-transition-name: quelle } auf der alten Seite. Firefox und Safari kennen ihn noch nicht (Stand 02.11.2026), deshalb in @supports selector(:navigation-source) und als eigene Regel; der Rückfall merkt sich den Link beim Klick oder liest NavigateEvent.sourceElement und setzt den Namen in pageswap.",
   "mobil": "Läuft auf iOS Safari ab 18.2 und auf Chrome für Android. Auf schwachen Geräten können automatisch erzeugte Größen-Animationen Frames verlieren (Google-Fallstudie), deshalb transform-Keyframes bevorzugen.",
   "reduzierte_bewegung": "@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } } ergibt einen normalen Seitenwechsel, ganz ohne JS. Alternativ Namen nur unter prefers-reduced-motion: no-preference vergeben, dann bleibt ein ruhiger Crossfade.",
   "barrierefreiheit": "Fokus, Ansage des Seitentitels und Zurück-Navigation bleiben nativ, das ist der größte Vorteil. Während der Animation ist die Pseudo-Ebene nicht bedienbar, deshalb den Übergang kurz halten."
  },
  "geprueft": "02.11.2026",
  "notiz": "Neue Welt (01.11.2026): erfundenes Restaurant „Osteria Cardo, Mainz“ mit saisonaler Herbstkarte. Übersicht /karte mit drei Gängen (Rote Bete, Cappellacci, Zwetschge) und je einer Gerichtseite /karte/<gericht> mit Herkunft, Weinempfehlung, Allergen-Kürzeln und Reservieren. Gestaltung nach Rezept gastro-warm-appetitlich: Fraunces (SOFT 100, opsz) für Titel, Commissioner mit FLAR 90 für Versal-Labels, kein Mono; dunkles Tannengrün #293e3a als Raum, Papier-Weiß als Schrift, Senf #eac16e und Rosé #e1a894 als Hausfarben. Bilder sind eigene SVG-Teller von oben (Teller, Serviette, Gabel-Silhouette) auf Senf, Salbei und Rosé, keine medien/-Fotos. Öffnungsstatus im Kopf wird aus den Öffnungszeiten berechnet. Inspiration aus dem Bildfundus (nur Prinzipien): momofuku-com, p-caf-integral-menue, m-adam-smith-by-magpie-woven, m-foreign-policy-makan, sirenuse-it. Technik und Bewegungswerte unverändert: Umschalter Benannt/Typen/Crossfade, Werte-Anzeige nennt Dauer, Kurve und die simulierte URL samt Typ. Die Seiten sind Zustände derselben Datei: document.startViewTransition({ update, types }) ersetzt den Seitenaufruf, die ::view-transition-Regeln sind 1:1 die für MPA. Im echten Einsatz reicht @view-transition { navigation: auto; } in beiden Seiten, Namen und Typen setzt man in pageswap/pagereveal. Ohne View-Transition-Unterstützung wechselt der Inhalt sofort. Vorführung: gedachter Zeiger öffnet nacheinander die drei Gerichte (je eine Variante) und geht zurück zur Karte. Zugang 02.11.2026: Unter 380 px Kopf-Knopf mit Innenabstand 13 px und Kopf-Lücke 10 px (kein Querscrollen bei 320 px, vorher +6 px); Kontrastmodus-Rahmen für Knöpfe. Korrektur 02.11.2026: Regel 13 nachgerüstet (?v=, replaceState, bau.varianten mit knopf; Umschalter-Auswahl auf .modi begrenzt, vorher bekam auch <html> aria-pressed) und vierte Variante „quelle“: Der angeklickte Link (Kartenbild mit Ring in Senf, Titel bzw. Zurück-Link) bekommt den Namen quelle, hebt sich über die abgedunkelte alte Seite (scale 1.04) und blendet zuletzt aus. Echt: :navigation-source (Chrome 156; Beleg buildmvpfast.com zu Chrome 156 stabil, Selektor laut CSSWG-Issue 11801 als Gegenstück zu NavigateEvent.sourceElement; in den abrufbaren Chrome-Quellen nicht gegengeprüft). Die Demo navigiert nicht wirklich, deshalb setzt sie data-quelle beim Klick; die Werte-Zeile nennt, ob der Browser den Selektor kennt. Galerie-Vorschau ohne ?v= wechselt weiter durch die ersten drei Varianten.",
  "varianten": [
   {
    "id": "benannt",
    "name": "Benannt: Kopf steht, Bild und Titel morphen",
    "knopf": "Benannt",
    "wann": "Übersicht und Detailseiten mit gleichem Bild (Speisekarte, Projekte, Produkte): der Klassiker mit Wiedererkennung.",
    "werte": {
     "dauer_ms": 600,
     "easing": "cubic-bezier(0.76, 0, 0.24, 1)",
     "namen": "kopf (Header, bleibt stehen), held (Kartenbild ↔ Bild der Detailseite), titel (Kartentitel ↔ h1); zwischen zwei Detailseiten nur held",
     "root": "alt opacity 1 → 0 in 300 ms, neu opacity 0 → 1 in 400 ms ab 200 ms, gleiche Kurve",
     "snapshots": "::view-transition-old/new(held) { height: 100%; object-fit: cover } · ::view-transition-old/new(titel) { width: 100%; height: 100% }",
     "echter_einsatz": "@view-transition { navigation: auto; } in beiden Seiten (gleiche Origin)",
     "reduziert": "keine Namen, keine Typen, Root-Crossfade 250 ms cubic-bezier(0.25, 0.1, 0.25, 1)",
     "scroll": "neue Seite beginnt oben, zurück zur Übersicht stellt die Scroll-Position wieder her"
    }
   },
   {
    "id": "typen",
    "name": "Typgesteuert: vorwärts und zurück",
    "knopf": "Typen",
    "wann": "Seiten mit klarer Richtung (Übersicht → Detail → nächstes Detail), wenn die Bewegung die Lage im Angebot zeigen soll.",
    "werte": {
     "dauer_ms": 600,
     "easing": "cubic-bezier(0.76, 0, 0.24, 1)",
     "typen": "vorwaerts (Übersicht → Detail, Detail → nächste Detailseite), zurueck (Detail → Übersicht); gesetzt über startViewTransition({ update, types }) bzw. im MPA über viewTransition.types.add() in pageswap/pagereveal",
     "vorwaerts": "alt translateX(0 → -30%), neu translateX(100% → 0) mit box-shadow -40px 0 80px rgba(25,24,20,.16) → 0",
     "zurueck": "alt translateX(0 → 100%) mit z-index 1 und Schatten, neu translateX(-30% → 0)"
    }
   },
   {
    "id": "crossfade",
    "name": "Reiner Root-Crossfade",
    "knopf": "Crossfade",
    "wann": "Für jede Seite als ruhige Grundlage, ohne JavaScript und ohne Namen; passt auch zu Kanzlei, Praxis und Behörde.",
    "werte": {
     "dauer_ms": 400,
     "easing": "cubic-bezier(0.25, 0.1, 0.25, 1) (ease, Browser-Kurve)",
     "art": "nur ::view-transition-old/new(root), keine Namen, kein JS"
    }
   },
   {
    "id": "quelle",
    "name": "Quelle: der angeklickte Link hebt sich ab (:navigation-source)",
    "knopf": "Quelle",
    "wann": "Listen mit vielen gleichrangigen Links (Speisekarte, Kursliste, Referenzen), wenn die Auswahl bestätigt werden soll, ohne Bild-Morph; der Selektor greift nur in Chromium, sonst per Klick-Markierung.",
    "werte": {
     "auswahl_echt": "a:navigation-source { view-transition-name: quelle } in @supports selector(:navigation-source); Chrome 156 (20.10.2026), Firefox und Safari ohne (Stand 02.11.2026)",
     "auswahl_demo": "data-quelle am angeklickten Link, gesetzt vor dem Schnappschuss (die Demo navigiert nicht wirklich); zugleich Rückfall für Browser ohne den Selektor (Klick merken oder NavigateEvent.sourceElement)",
     "markierung": "Kartenbild outline 2px solid #eac16e, outline-offset 5px; Titel bzw. Zurück-Link in #eac16e",
     "quelle_dauer_ms": 900,
     "quelle_keyframes": "scale 1 → 1.04 bis 40 %, voll sichtbar bis 70 %, dann opacity → 0; z-index 4",
     "root_alt": "opacity → 0 und brightness(.6), 400 ms",
     "root_neu": "opacity 0 → 1, 450 ms ab 300 ms",
     "easing": "cubic-bezier(0.76, 0, 0.24, 1)",
     "kopf": "bleibt stehen (Name kopf), keine Morphs von Bild und Titel",
     "reduziert": "kein Name, nur Root-Crossfade 250 ms; die Markierung erscheint statisch"
    }
   }
  ]
 }
}
