{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "3d-karussell-zylinder",
 "name": "3D-Karussell / Bildzylinder (Scroll- und Drag-gesteuert)",
 "name_en": "3D cylinder carousel / on-scroll 3D carousel / Curved WebGL galleries / wavy infinite carousels / image tubes / Scroll-driven carousel effects (cover flow, scale on snap)",
 "kurz": "Zwölf Bilder auf einem CSS-3D-Zylinder: dreht sich langsam von selbst, Scrollen beschleunigt, Ziehen wirft ihn mit Trägheit an.",
 "kategorie": "Galerien & Slider",
 "kategorie_slug": "galerien-slider",
 "kategorie_nr": 12,
 "bau_chat": "C6",
 "prioritaet": "A",
 "trendstatus": "aufsteigend",
 "belegstatus": "belegt",
 "website_belege": 2,
 "stimmung": [
  "ruhig",
  "editorial",
  "präzise",
  "filmisch",
  "verspielt",
  "laut"
 ],
 "stimmung_roh": [
  "verspielt",
  "technisch",
  "laut",
  "immersiv",
  "flüssig",
  "editorial",
  "produkt",
  "modern"
 ],
 "technik": [
  "css",
  "gsap",
  "scrolltrigger",
  "draggable",
  "inertia",
  "observer",
  "three",
  "webgl-shader",
  "r3f",
  "lenis",
  "scroll-driven-css"
 ],
 "technik_gruppen": [
  "css",
  "gsap",
  "lenis",
  "webgl"
 ],
 "leistungskosten": "mittel",
 "steckbrief": {
  "beschreibung": "Bilder sitzen auf einem Zylinder. Jedes Panel bekommt rotateY(i × 360° / n) und wird um den Radius nach vorn verschoben. Gedreht wird nur der Ring, mit perspective auf der Bühne und transform-style preserve-3d. Eine langsame Grundrotation läuft immer (360° in 30 s, linear). Scrollen setzt deren Tempo hoch, danach federt es zurück. Ziehen dreht direkt und wirft den Ring mit Trägheit weiter. Beim Drücken zieht sich jedes Bild leicht zusammen (clip-path inset 5 %). In der Scroll-Variante steuert die Scrollposition Drehung, leichtes Kippen und Helligkeit.",
  "warum_es_wirkt": "Die Galerie wird zum Objekt mit echter Tiefe, und das ohne WebGL. Weil das Tempo der Scrollgeschwindigkeit folgt, sieht man die eigene Eingabe. Das lädt zum Spielen ein. Ziehen mit Trägheit fühlt sich an wie ein echter Drehteller.",
  "wann_einsetzen": "Portfolio- und Kampagnen-Startseiten, Kollektionen, Studio- und Fotografenseiten, Event- und Musikseiten. Überall, wo eine Bildfolge Stimmung machen soll und einzelne Bilder nicht verglichen werden müssen.",
  "wann_nicht": "Bei Karten mit Text, denn seitlich verzerrt ist er kaum lesbar. Bei sehr wenigen Bildern oder mehr als etwa 20 Panels. Wenn Nutzer gezielt suchen, filtern oder vergleichen müssen. In nüchternen, ernsten Kontexten.",
  "varianten": [
   "Zylinder: CSS 3D, Grundrotation, Tempo aus der Scrollgeschwindigkeit, Ziehen mit Trägheit",
   "Scroll-gekoppelt: Drehung, Kippen und Helligkeit hängen an der Scrollposition (scrub)",
   "Federnde Spreizung und Neigung je nach Scrollgeschwindigkeit (Steifigkeit 120, Dämpfung 14)",
   "Cover Flow: waagerechte Leiste mit scroll-snap, Drehung um die Mitte per animation-timeline: view(inline)",
   "Hintergrundverlauf aus der Farbe des vorderen Bildes",
   "WebGL: Bildröhre, durch die man hindurchscrollt",
   "WebGL: welliges Endloskarussell, dessen Bänder sich mit dem Tempo per Vertex-Shader biegen",
   "WebGL: gekrümmtes Produkt-Grid"
  ],
  "umsetzung": "Ein Wrapper dreht sich, nicht jedes Panel einzeln. Radius aus Panelbreite und Anzahl: r = (w / 2) / tan(π / n), mit Luft zwischen den Panels auch größer (Osmo: r = 50vw, perspective 90vw). Rückseiten entweder ausblenden (backface-visibility hidden) oder sichtbar lassen und abdunkeln. Grundrotation, Scroll-Tempo und Ziehen in einem gemeinsamen Winkelwert zusammenführen und in einem Takt (requestAnimationFrame oder gsap.ticker) schreiben. Federn mit begrenztem Zeitschritt (höchstens 1/30 s) rechnen. Resize entprellen (200 ms), dann neu messen und ScrollTrigger.refresh(). Fallstrick Safari: overflow, filter oder clip-path auf einem Element innerhalb der preserve-3d-Kette macht den Zylinder flach, also nur auf Blattelementen oder außerhalb einsetzen. Cover Flow ohne JS: .track { display: flex; overflow-x: auto; scroll-snap-type: x mandatory } .item { scroll-snap-align: center; animation: flow linear both; animation-timeline: view(inline) } @keyframes flow { 0% { transform: perspective(900px) rotateY(45deg) scale(.8) } 50% { transform: perspective(900px) rotateY(0) scale(1) } 100% { transform: perspective(900px) rotateY(-45deg) scale(.8) } }. WebGL-Varianten: Plane-Geometrie mit genug Segmenten (etwa 32 × 32) für die Biegung, ein gemeinsamer Bewegungswert speist alle Shader.",
  "mobil": "Ziehen statt Scroll-Kopplung. Kleinerer Radius, größere Panels, senkrechtes Scrollen frei lassen (touch-action: pan-y). Auf schwachen Geräten auf eine flache Wischleiste mit scroll-snap zurückfallen. Cover Flow passt ideal zur nativen Wischgeste.",
  "reduzierte_bewegung": "Keine Autorotation und keine Trägheit. Bewegungsfaktor stark senken (Codrops: ein Drittel) oder ganz auf eine flache Leiste ohne Drehung wechseln. Navigation über Knöpfe und Pfeiltasten, Sprünge ohne Animation.",
  "barrierefreiheit": "Panels als Liste von Links mit alt-Text in logischer Reihenfolge. Nur das vordere Bild ist fokussierbar. Knöpfe für vor und zurück mit aria-label, Pfeiltasten auf der Bühne. Die Autorotation lässt sich per Knopf anhalten. Keine Scroll-Falle: Ziehen darf senkrechtes Scrollen nicht blockieren. Den Namen der vorderen Arbeit in einer aria-live-Region ausgeben. Im Cover Flow den scrollbaren Container mit tabindex=\"0\" und aria-label versehen."
 },
 "messwerte": {
  "easing": "Produktion CLOU: Ring-Einflug CustomEase ringIn (M0,0 C0.508,0 0.946,0.788 1,1), UI cubic-bezier(.55,0,.1,1); Demo Codrops: Grundrotation none, Intro expo.inOut, Drücken power4.out; power2.inOut (Einrasten); Glättung smoothness 4",
  "dauer_ms": "Umdrehung 30000; Intro 2000; Drücken 300 / Loslassen 500; Velocity-Rückkehr 1200; 700 + 300 Verzögerung",
  "stagger_ms": "Inhalt-Einblendung 800 gesamt, zufällige Reihenfolge",
  "distanz": "Radius 0,5 × Fensterbreite bzw. 500 px; Kippen ±3°; Kartenrotation ±10°; Drehung um Y bis 1.05π je Slide-Abstand; Versatz 1.9 Einheiten",
  "sonstiges": "Federn stiffness 120 / damping 14; Spreizung max. 180 px; Neigung max. 20°; Exponent 0.7 lässt die Drehung nahe der Mitte schneller anlaufen",
  "herkunft": "beobachtet",
  "quelle": "https://www.clouarchitects.com/wp-content/themes/clou/public/scripts/theme.js; https://www.paffi.it/assets/index.0dba25b1.js",
  "aus_eintrag": [
   "scroll-3d-karussell-zylinder"
  ]
 },
 "kurve": {
  "bezier": [
   0.55,
   0.0,
   0.1,
   1.0
  ],
  "css": "cubic-bezier(0.55, 0, 0.1, 1)",
  "name": "eigene Kurve",
  "dauer_ms": null
 },
 "gesehen_bei": [
  {
   "seite": "Codrops Demo – On-Scroll 3D Carousel",
   "url": "https://tympanus.net/Development/3DCarousel/",
   "auszeichnung": "",
   "beobachtung": "Quellcode: ScrollTrigger scrub (top bottom bis bottom top), Timeline-Ease sine.inOut; Karussell rotationY von 0 bis −180, rotationX/Z +3° bis −3°; Karten brightness 250 % → 80 % (power3) und rotationZ ±10; Federn stiffness 120, damping 14, Spreizung 0,05 (max. 180 px), Neigung 0,006 (max. 20°); Drag-Spin-Faktor 0,12, quickTo 0,6 s power3; Standardradius 500 px; Reduced Motion verkleinert den Bewegungsfaktor auf 1/3.",
   "art": "demo"
  },
  {
   "seite": "Osmo – 3D Image Carousel (Original von Ilja van Eck, basiert auf GSAP-CodePen)",
   "url": "https://www.osmo.supply/resource/3d-image-carousel",
   "auszeichnung": "",
   "beobachtung": "perspective 90vw; Radius = innerWidth × 0,5; 12 Panels im 30°-Abstand; Spin −=360 in 30 s ease none; Drag-Proxy mit inertia; beim Drücken clip-path inset(5 %) 0,3 s power4.out, beim Loslassen 0,5 s; Scroll-Velocity × 0,005 geklemmt auf ±60 als timeScale, Rückkehr in 1,2 s; Intro: timeScale 15 → 1 in 2 s expo.inOut.",
   "art": "demo"
  },
  {
   "seite": "Codrops – Building a 3D Infinite Carousel with Reactive Background Gradients (11/2025)",
   "url": "https://tympanus.net/codrops/2025/11/11/building-a-3d-infinite-carousel-with-reactive-background-gradients/",
   "auszeichnung": "",
   "beobachtung": "Laut Teaser: 3D-Karussell, dessen Hintergrundverlauf sich aus den Bildfarben ableitet (Artikeltext nicht abrufbar).",
   "art": "artikel"
  },
  {
   "seite": "Codrops – Reactive Depth: Scroll-Driven 3D Image Tube with R3F (02/2026)",
   "url": "https://tympanus.net/codrops/2026/02/17/reactive-depth-building-a-scroll-driven-3d-image-tube-with-react-three-fiber/",
   "auszeichnung": "",
   "beobachtung": "Laut Teaser: endlose Bildröhre mit Shadern und Trägheit.",
   "art": "artikel",
   "weitere_beobachtung": "Laut Feed: unendlich loopende, scrollgetriebene Bildröhre mit Shadern und vereinheitlichtem Bewegungssystem."
  },
  {
   "seite": "Codrops – Wavy Infinite Carousels in R3F",
   "url": "https://tympanus.net/codrops/2025/11/26/creating-wavy-infinite-carousels-in-react-three-fiber-with-glsl-shaders/",
   "auszeichnung": "",
   "beobachtung": "Laut Feed: unendlich scrollende 3D-Karussells mit scrollgetriebener Wellenverzerrung.",
   "art": "artikel"
  },
  {
   "seite": "Codrops – 3D Product Grid",
   "url": "https://tympanus.net/codrops/2026/02/24/from-flat-to-spatial-creating-a-3d-product-grid-with-react-three-fiber/",
   "auszeichnung": "",
   "beobachtung": "Laut Feed: gekrümmtes 3D-Produktgrid mit R3F und GLSL.",
   "art": "artikel"
  },
  {
   "seite": "Codrops – Infinite Canvas",
   "url": "https://tympanus.net/codrops/2026/01/07/infinite-canvas-building-a-seamless-pan-anywhere-image-space/",
   "auszeichnung": "",
   "beobachtung": "Laut Feed: pannbare Bildleinwand mit chunkbasiertem Rendering.",
   "art": "artikel"
  },
  {
   "seite": "scroll-driven-animations.style – Cover Flow / Window Carousel",
   "url": "https://scroll-driven-animations.style/demos/cover-flow/css/",
   "auszeichnung": "",
   "beobachtung": "Cover-Flow-Effekt rein mit CSS scroll-driven animations.",
   "art": "demo"
  },
  {
   "seite": "CLOU architects",
   "url": "https://www.clouarchitects.com/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft 31.10.2026 (HTML/Bundle per curl abgerufen): Startseite mit ziehbarem Projekt-Ring (miniRingData) in Three.js, GSAP Draggable + InertiaPlugin, eigene Einflugkurve ringIn = CustomEase „M0,0 C0.508,0 0.946,0.788 1,1“, Ebenen mit stagger. Fund über Tridimensi-Artikel („Drag to rotate the ring“).",
   "art": "website"
  },
  {
   "seite": "Paffi",
   "url": "https://www.paffi.it/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft 31.10.2026 (HTML/Bundle per curl abgerufen): index.0dba25b1.js: Startseite als „Totem-Slider“: vertikaler Endlos-Slider (ZliderManager: slideSize = innerHeight, loop, center .5, smoothness 4, Drag/Rad/Tastatur, Einrasten auf nächsten Slide) steuert gestapelte Three.js-Boxen (R3F, BendBox 20×50×20 Segmente). Pro Box mit Abstand d: rotation.y = sign(d)·|d|^0.7·1.05π, position.y = 1.9·d, scale.y 1.2 + .4|d|, scale.x/z 1.2 + .1|d|, Biegung u_bend = outSine(|d|)·.25. Wechsel zum Hauptprojekt 0,7 s power2.inOut mit 0,3 s Verzögerung; Hintergrundfarbe aus lerpColors der beiden nächsten Slides.",
   "art": "website"
  }
 ],
 "tutorials": [
  {
   "titel": "GitHub: codrops/3DCarousel",
   "url": "https://github.com/codrops/3DCarousel"
  },
  {
   "titel": "Codrops: Creating Wavy Infinite Carousels in R3F with GLSL",
   "url": "https://tympanus.net/codrops/2025/11/26/creating-wavy-infinite-carousels-in-react-three-fiber-with-glsl-shaders/"
  },
  {
   "titel": "Codrops: 3D Infinite Carousel with Reactive Background Gradients",
   "url": "https://tympanus.net/codrops/2025/11/11/building-a-3d-infinite-carousel-with-reactive-background-gradients/"
  },
  {
   "titel": "Osmo: 3D Image Carousel",
   "url": "https://www.osmo.supply/resource/3d-image-carousel"
  },
  {
   "titel": "Reactive Depth: Building a Scroll-Driven 3D Image Tube with React Three Fiber",
   "url": "https://tympanus.net/codrops/2026/02/17/reactive-depth-building-a-scroll-driven-3d-image-tube-with-react-three-fiber/"
  },
  {
   "titel": "From Flat to Spatial: Creating a 3D Product Grid with React Three Fiber",
   "url": "https://tympanus.net/codrops/2026/02/24/from-flat-to-spatial-creating-a-3d-product-grid-with-react-three-fiber/"
  },
  {
   "titel": "Infinite Canvas: Building a Seamless, Pan-Anywhere Image Space",
   "url": "https://tympanus.net/codrops/2026/01/07/infinite-canvas-building-a-seamless-pan-anywhere-image-space/"
  },
  {
   "titel": "Cover Flow (CSS)",
   "url": "https://scroll-driven-animations.style/demos/cover-flow/css/"
  },
  {
   "titel": "Carousel with markers (CSS)",
   "url": "https://scroll-driven-animations.style/demos/carousel-with-markers/css/"
  }
 ],
 "kombinierbar_mit": [
  "galerie-shared-element-vollbild",
  "token-physik-traege",
  "token-federnd-verspielt",
  "webgl-bildverzerrung",
  "shader-uebergang-dissolve",
  "css-3d-transforms",
  "horizontal-scroll-section",
  "css-view-reveal-nativ"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/galerien-slider/3d-karussell-zylinder/",
  "meta": "https://cecodesign.de/lab/fundus/galerien-slider/3d-karussell-zylinder/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/galerien-slider/3d-karussell-zylinder/demo"
 },
 "herkunft": {
  "quelldateien": [
   "galerien_stile.json",
   "material3d.json",
   "scroll.json",
   "patch-belege-2.json",
   "r3-belege-a.json"
  ],
  "pruefnotizen": [
   "patch-belege-2.json: 1 Produktionsbeleg; Ziel ≥2 nicht erreicht.",
   "r3-belege-a.json (Runde 3, 31.10.2026): Nur eingeschränkt passend: Paffi dreht gestapelte 3D-Körper um die Y-Achse (Totem) statt Bilder auf einem Zylinder. Ein echter Bildring mit Produktionsbeleg wurde in rund 520 geprüften Websites nicht gefunden; CSS-Treffer rotateY()+translateZ() waren Würfel bzw. Münzen."
  ],
  "zusammengelegt_aus": [
   "scroll-3d-karussell-zylinder",
   "wellen-karussell-3d-galerie",
   "coverflow-scroll-karussell"
  ],
  "querverweis_kategorien": [
   "3D & WebGL",
   "Scroll & Section-Animationen"
  ],
  "leistungskosten_spanne": "niedrig–mittel (je nach Variante)"
 },
 "bau": {
  "status": "fertig",
  "kurz": "Zwölf Bilder auf einem CSS-3D-Zylinder: dreht sich langsam von selbst, Scrollen beschleunigt, Ziehen wirft ihn mit Trägheit an.",
  "demo": true,
  "abhaengigkeiten": [
   "gsap@3.15.0",
   "ScrollTrigger@3.15.0",
   "Draggable@3.15.0",
   "InertiaPlugin@3.15.0"
  ],
  "werte": {
   "aufbau": "12 Panels, je rotateY(i × 30deg) translateZ(r); Ring: translateZ(−r) rotateY(winkel), transform-style preserve-3d",
   "radius": "r = 0,5 × B; B = min(Fensterbreite, 1,5 × Fensterhöhe), unter 640 px B = min(1,8 × Breite, 0,9 × Höhe)",
   "perspective": "0,9 × B (Osmo: 90vw bei r = 50vw)",
   "panel": "Breite 0,22 × B (Telefon 0,24 × B), Seitenverhältnis 4:5, border-radius 5px",
   "licht_je_panel": "brightness = 0,18 + 0,82 × ((cos θ + 1) / 2)^1,6; Rückseiten sichtbar und gespiegelt",
   "grundrotation": "360° in 30000 ms, linear",
   "intro": "Tempo 15 → 1 in 2000 ms expo.inOut; Panels opacity 0 → 1, 600 ms power1.out, stagger 800 ms gesamt, from random",
   "scroll_tempo": "Tempo = Scrollgeschwindigkeit (px/s) × 0,005, geklemmt ±60, Richtung folgt dem Scrollen; zurück auf ±1 in 1200 ms power1.out",
   "ziehen": "3 × Fensterbreite = 360°, InertiaPlugin; beim Drücken Tempo → 0 in 300 ms, nach dem Loslassen in Wurfrichtung zurück auf 1 in 1200 ms",
   "druck_feedback": "clip-path inset(0% round 5px) → inset(5% round 5px), 300 ms power4.out; Loslassen 500 ms power4.out",
   "schritt": "Knöpfe, Pfeiltasten, Klick auf seitliches Bild: 30° in 700 ms cubic-bezier(0.55, 0, 0.1, 1); hält die Autorotation an",
   "variante_scroll": "rotateY 0 → −180°, rotateX/Z +3° → −3°, sine.inOut über die Scrollstrecke (320svh, sticky); brightness 150 % → 80 % power3.out (Codrops misst 250 %, brennt auf hellen Logos aus)",
   "variante_scroll_federn": "Steifigkeit 120, Dämpfung 14, Zeitschritt max. 1/30 s; Spreizung |v| × 0,05 (max. 180 px) auf den Radius; Neigung v × 0,006 (max. 20°) auf rotateX",
   "variante_scroll_ziehen": "Ziehstrecke × 0,12 °/px, gsap.quickTo 600 ms power3",
   "variante_cover_flow": "scroll-snap-type x mandatory, scroll-snap-align center; animation-timeline view(inline); Keyframes perspective(900px) rotateY 45° → 0 → −45°, scale 0,8 → 1 → 0,8, brightness 55 % → 100 % → 55 %; JS-Ersatz ohne Unterstützung",
   "hintergrund": "radialer Verlauf mit 40 % der Bildfarbe des vorderen Panels, @property --ton, Übergang 1200 ms linear",
   "bildunterschrift": "Name steigt 0,35em ein, 600 ms cubic-bezier(0.16, 1, 0.3, 1); bei Wechseln unter 350 ms nur Texttausch",
   "resize": "entprellt 200 ms, danach ScrollTrigger.refresh()"
  },
  "ausloeser": "ziehen",
  "touch": "Ziehen dreht den Zylinder mit Trägheit, senkrechtes Scrollen bleibt frei (touch-action pan-y). Keine Scroll-Kopplung des Tempos, keine Tempo-Anzeige. Cover Flow per nativer Wischgeste mit Einrasten. Kleinerer Ring, größere Panels.",
  "reduziert": "Keine Autorotation, kein Intro, keine Scroll-Kopplung, keine Federn und keine Trägheit. Ziehen wirkt mit einem Drittel und rastet auf das nächste Bild ein. Knöpfe und Pfeiltasten springen ohne Animation. Cover Flow wird zur flachen Leiste ohne Drehung.",
  "korrekturen": {
   "beschreibung": "Bilder sitzen auf einem Zylinder. Jedes Panel bekommt rotateY(i × 360° / n) und wird um den Radius nach vorn verschoben. Gedreht wird nur der Ring, mit perspective auf der Bühne und transform-style preserve-3d. Eine langsame Grundrotation läuft immer (360° in 30 s, linear). Scrollen setzt deren Tempo hoch, danach federt es zurück. Ziehen dreht direkt und wirft den Ring mit Trägheit weiter. Beim Drücken zieht sich jedes Bild leicht zusammen (clip-path inset 5 %). In der Scroll-Variante steuert die Scrollposition Drehung, leichtes Kippen und Helligkeit.",
   "warum_es_wirkt": "Die Galerie wird zum Objekt mit echter Tiefe, und das ohne WebGL. Weil das Tempo der Scrollgeschwindigkeit folgt, sieht man die eigene Eingabe. Das lädt zum Spielen ein. Ziehen mit Trägheit fühlt sich an wie ein echter Drehteller.",
   "wann_einsetzen": "Portfolio- und Kampagnen-Startseiten, Kollektionen, Studio- und Fotografenseiten, Event- und Musikseiten. Überall, wo eine Bildfolge Stimmung machen soll und einzelne Bilder nicht verglichen werden müssen.",
   "wann_nicht": "Bei Karten mit Text, denn seitlich verzerrt ist er kaum lesbar. Bei sehr wenigen Bildern oder mehr als etwa 20 Panels. Wenn Nutzer gezielt suchen, filtern oder vergleichen müssen. In nüchternen, ernsten Kontexten.",
   "varianten": [
    "Zylinder: CSS 3D, Grundrotation, Tempo aus der Scrollgeschwindigkeit, Ziehen mit Trägheit",
    "Scroll-gekoppelt: Drehung, Kippen und Helligkeit hängen an der Scrollposition (scrub)",
    "Federnde Spreizung und Neigung je nach Scrollgeschwindigkeit (Steifigkeit 120, Dämpfung 14)",
    "Cover Flow: waagerechte Leiste mit scroll-snap, Drehung um die Mitte per animation-timeline: view(inline)",
    "Hintergrundverlauf aus der Farbe des vorderen Bildes",
    "WebGL: Bildröhre, durch die man hindurchscrollt",
    "WebGL: welliges Endloskarussell, dessen Bänder sich mit dem Tempo per Vertex-Shader biegen",
    "WebGL: gekrümmtes Produkt-Grid"
   ],
   "umsetzung": "Ein Wrapper dreht sich, nicht jedes Panel einzeln. Radius aus Panelbreite und Anzahl: r = (w / 2) / tan(π / n), mit Luft zwischen den Panels auch größer (Osmo: r = 50vw, perspective 90vw). Rückseiten entweder ausblenden (backface-visibility hidden) oder sichtbar lassen und abdunkeln. Grundrotation, Scroll-Tempo und Ziehen in einem gemeinsamen Winkelwert zusammenführen und in einem Takt (requestAnimationFrame oder gsap.ticker) schreiben. Federn mit begrenztem Zeitschritt (höchstens 1/30 s) rechnen. Resize entprellen (200 ms), dann neu messen und ScrollTrigger.refresh(). Fallstrick Safari: overflow, filter oder clip-path auf einem Element innerhalb der preserve-3d-Kette macht den Zylinder flach, also nur auf Blattelementen oder außerhalb einsetzen. Cover Flow ohne JS: .track { display: flex; overflow-x: auto; scroll-snap-type: x mandatory } .item { scroll-snap-align: center; animation: flow linear both; animation-timeline: view(inline) } @keyframes flow { 0% { transform: perspective(900px) rotateY(45deg) scale(.8) } 50% { transform: perspective(900px) rotateY(0) scale(1) } 100% { transform: perspective(900px) rotateY(-45deg) scale(.8) } }. WebGL-Varianten: Plane-Geometrie mit genug Segmenten (etwa 32 × 32) für die Biegung, ein gemeinsamer Bewegungswert speist alle Shader.",
   "mobil": "Ziehen statt Scroll-Kopplung. Kleinerer Radius, größere Panels, senkrechtes Scrollen frei lassen (touch-action: pan-y). Auf schwachen Geräten auf eine flache Wischleiste mit scroll-snap zurückfallen. Cover Flow passt ideal zur nativen Wischgeste.",
   "reduzierte_bewegung": "Keine Autorotation und keine Trägheit. Bewegungsfaktor stark senken (Codrops: ein Drittel) oder ganz auf eine flache Leiste ohne Drehung wechseln. Navigation über Knöpfe und Pfeiltasten, Sprünge ohne Animation.",
   "barrierefreiheit": "Panels als Liste von Links mit alt-Text in logischer Reihenfolge. Nur das vordere Bild ist fokussierbar. Knöpfe für vor und zurück mit aria-label, Pfeiltasten auf der Bühne. Die Autorotation lässt sich per Knopf anhalten. Keine Scroll-Falle: Ziehen darf senkrechtes Scrollen nicht blockieren. Den Namen der vorderen Arbeit in einer aria-live-Region ausgeben. Im Cover Flow den scrollbaren Container mit tabindex=\"0\" und aria-label versehen."
  },
  "geprueft": "31.10.2026",
  "notiz": "Portfolio des erfundenen Studio Rundlauf (Köln) mit drei Varianten: Zylinder (Osmo-Werte: 30 s Grundrotation, Scroll-Tempo, Ziehen mit Trägheit, clip-path beim Drücken), Scroll (Codrops-Werte: Drehung über die Strecke, Kippen, Federn für Spreizung und Neigung) und Cover Flow (CSS scroll-driven, JS-Ersatz). Hintergrundverlauf folgt der Bildfarbe. Abweichung: Helligkeit startet bei 150 % statt gemessenen 250 %. Vorführung: Intro-Schub, gezeichneter Zeiger zieht und wirft, danach Scroll-Schub mit Tempoanzeige. Bilder 01.11.2026: eigene Bilder statt Portfolio. Zugang 02.11.2026: Tastaturfokus im Zylinder hält die Autodrehung an (wie der Pause-Knopf, aria-pressed wird gesetzt) und holt die fokussierte Karte nach vorn; Tab landet sofort auf der vorderen Karte (vorher fokussiert, aber weggedreht). Ziehen und Klicken unverändert. Knopfrahmen im Kontrastmodus. Kein Fehler: übrige Karten tabindex -1 (Pfeiltasten am Zylinder); Zielgröße-Treffer an hochkant gedrehten Karten hängen vom Drehwinkel ab."
 }
}
