{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "css-native-karussell",
 "name": "Natives CSS-Karussell (Scroll-Snap, Scroll-Buttons, Scroll-Marker)",
 "name_en": "CSS-only carousel with ::scroll-button and ::scroll-marker",
 "kurz": "Produktreihe einer Münsteraner Rösterei als echter Scroller: Scroll-Snap, Pfeile und Punkte vom Browser, die eingerastete Tüte hebt sich per scroll-state(), ganz ohne JS.",
 "kategorie": "Galerien & Slider",
 "kategorie_slug": "galerien-slider",
 "kategorie_nr": 12,
 "bau_chat": "C6",
 "prioritaet": "A",
 "trendstatus": "aufsteigend",
 "belegstatus": "teilbelegt",
 "website_belege": 1,
 "stimmung": [
  "ruhig",
  "präzise"
 ],
 "stimmung_roh": [
  "sachlich",
  "robust",
  "modern",
  "ruhig"
 ],
 "technik": [
  "css",
  "scroll-snap",
  "scroll-driven-css",
  "scroll-state-queries"
 ],
 "technik_gruppen": [
  "css"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Ein echter Scroller mit overflow-x auto und scroll-snap-type x mandatory. Die Kinder rasten mit scroll-snap-align center ein; scroll-snap-stop always sorgt für eine Karte pro Klick oder Geste. ::scroll-button(left/right) erzeugt die Pfeile mit Alt-Text, ::scroll-marker mit scroll-marker-group die Punkte als Tablist. Mit container-type scroll-state und @container scroll-state(snapped: x) hebt sich die eingerastete Karte hervor. Optional skaliert oder verschiebt eine view-timeline die Karten beim Durchlaufen.",
  "warum_es_wirkt": "Es ist echtes Scrollen: Trackpad, Mausrad, Wischen und Tastatur verhalten sich auf jedem Gerät so, wie man es erwartet. Es braucht kein JS, und Buttons und Marker bringen ihre Rollen für Tastatur und Screenreader mit. Für Claude ist es der robusteste Standard, auf den man aufbauen kann.",
  "wann_einsetzen": "Produktreihen, Shop-Teaser, Referenzen, Blog-Teaser und Karten-Slider auf Landingpages. Immer dann, wenn kein Endlos-Loop nötig ist.",
  "wann_nicht": "Wenn ein nahtloser Endlos-Loop, Trägheit mit eigener Physik oder eine 3D-Anordnung gefragt ist. Wenn Firefox- und Safari-Nutzer genau dieselbe Bedienung brauchen: Dort gibt es bisher nur Scroll-Snap und eigene Buttons.",
  "varianten": [
   "Nur Scroll-Snap mit eigenen Buttons (läuft überall)",
   "Mit ::scroll-button und ::scroll-marker als Punkte oder Farbfelder",
   "Mit scroll-state(snapped) für die aktive Karte",
   "Mit view-timeline für Skalierung oder Parallaxe beim Durchlaufen",
   "Mit interactivity: inert für nicht sichtbare Karten (laut Chrome-Configurator)",
   "Vollbild-Bühne: ein Bild füllt die Breite, Marker als Reiter mit Titel im Modus tabs (scroll-marker-group: after tabs, Chrome 154)",
   "Kartenreihe mit Peek: Start-Ausrichtung, die nächste Karte schaut an der Kante herein, Marker im Modus links",
   "Variable Breiten: gemischte Hoch- und Querformate in fester Höhe (width auto), Snap auf start, Pfeile blättern um die Sichtbreite, Zähler zeigt den sichtbaren Bereich",
   "Fenster: ein Bild in einem schmalen Fenster von etwa 4 Spalten, zentriert, Endlosschleife über Klone, keine Punkte, große 1-px-Haarlinien-Pfeile im Leerraum (nach Kereliott)"
  ],
  "umsetzung": "Progressive Enhancement. Basis ist Scroll-Snap mit eigenen Buttons (scrollBy) und einem IntersectionObserver für den Aktivzustand. Mit @supports selector(::scroll-button(right)) die eigenen Buttons ausblenden und die nativen nutzen. Die nativen Buttons lassen sich mit position-anchor an jede Stelle der Seite setzen. Fallstricke: Ohne scroll-snap-stop always überspringen schnelle Gesten Karten. scrollbar-width none nur mit sichtbaren Alternativen. Die Marker-Gruppe braucht ein eigenes Layout (flex, gap). Damit die erste und letzte Karte mittig einrasten, braucht der Scroller seitliches Padding von 50 % minus halber Kartenbreite.",
  "mobil": "Ideal: natives Wischen mit Einrasten. Pfeile auf Touch ausblenden, Marker behalten.",
  "reduzierte_bewegung": "scroll-behavior auto statt smooth. view-timeline-Effekte in der Media Query entfernen. Die Hervorhebung darf bleiben, aber ohne Übergang.",
  "barrierefreiheit": "Der Browser vergibt Rollen, Tab-Reihenfolge und Zustand für Buttons und Marker. Trotzdem braucht der Scroller ein aria-label und jede Karte eine eindeutige Beschriftung (z. B. „Aasee, 2 von 8“). Im Fallback eigene Buttons mit aria-label und aria-controls."
 },
 "messwerte": {
  "easing": "native Scroll-Physik; Hervorhebung ease bzw. cubic-bezier(0.33,1,0.68,1)",
  "dauer_ms": "Aktivzustand 300–500",
  "stagger_ms": "",
  "distanz": "Button scrollt ca. 85 % der Scrollerbreite",
  "sonstiges": "Chrome 133 (scroll-state), Chrome 135 (scroll-button/marker); Firefox/Safari laut Chrome-Artikel ohne Unterstützung",
  "herkunft": "beobachtet",
  "quelle": "https://developer.chrome.com/blog/carousels-with-css"
 },
 "kurve": {
  "bezier": [
   0.33,
   1.0,
   0.68,
   1.0
  ],
  "css": "cubic-bezier(0.33, 1, 0.68, 1)",
  "name": "power2.out",
  "dauer_ms": 400
 },
 "gesehen_bei": [
  {
   "seite": "Chrome for Developers – Carousels with CSS",
   "url": "https://developer.chrome.com/blog/carousels-with-css",
   "auszeichnung": "",
   "beobachtung": "::scroll-button() und ::scroll-marker ab Chrome/Edge 135; Buttons scrollen ca. 85 %; Marker als Tablist angesagt; Demos chrome.dev/carousel und Configurator; zyklisches Scrollen ist geplant.",
   "art": "artikel"
  },
  {
   "seite": "Chrome for Developers – CSS scroll-state() queries",
   "url": "https://developer.chrome.com/blog/css-scroll-state-queries",
   "auszeichnung": "",
   "beobachtung": "snapped: x/y/inline/block ab Chrome 133; Muster: Slides gedimmt (opacity 0,25, 0,5 s ease), eingerastetes Slide auf 1.",
   "art": "artikel"
  },
  {
   "seite": "MDN – ::scroll-marker",
   "url": "https://developer.mozilla.org/en-US/docs/Web/CSS/::scroll-marker",
   "auszeichnung": "",
   "beobachtung": "Status: experimentell, nicht Baseline (Stand Abruf 10/2026); verwandt: scroll-target-group, :target-before/:target-after.",
   "art": "artikel"
  },
  {
   "seite": "Terminal Industries",
   "url": "https://terminal-industries.com/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft 31.10.2026 (HTML/Bundle per curl abgerufen): Karussell auf scroll-snap-type: x mandatory, per JS um Drag mit Trägheit und snapPoints ergänzt (Snap während des Wurfs abgeschaltet). Nur die Scroll-Snap-Basis, keine ::scroll-button/::scroll-marker.",
   "art": "website",
   "browser_gemessen": true
  }
 ],
 "tutorials": [
  {
   "titel": "Chrome: Carousels with CSS",
   "url": "https://developer.chrome.com/blog/carousels-with-css"
  },
  {
   "titel": "Chrome: CSS scroll-state() queries",
   "url": "https://developer.chrome.com/blog/css-scroll-state-queries"
  },
  {
   "titel": "MDN: ::scroll-marker",
   "url": "https://developer.mozilla.org/en-US/docs/Web/CSS/::scroll-marker"
  }
 ],
 "kombinierbar_mit": [
  "drag-slider-traegheit-loop",
  "token-swiss-knackig",
  "token-tech-praezise"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/galerien-slider/css-native-karussell/",
  "meta": "https://cecodesign.de/lab/fundus/galerien-slider/css-native-karussell/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/galerien-slider/css-native-karussell/demo"
 },
 "herkunft": {
  "quelldateien": [
   "galerien_stile.json",
   "patch-belege-2.json"
  ],
  "pruefnotizen": [
   "patch-belege-2.json: ::scroll-button/::scroll-marker/scroll-marker-group in keinem der ~100 geprüften Produktions-Bundles gefunden; Scroll-Snap-Basis dagegen verbreitet (by-kin.com, k72.ca, htarchitecte.com). Herabstufung auf B.",
   "02.11.2026: Priorität C → A (Lückenrecherche K2), weil steht in 15 Rezepten, Priorität C widersprach der tatsächlichen Nutzung."
  ],
  "prioritaet_hinweis": "31.10.2026: A → B laut patch-belege-2.json (::scroll-button/::scroll-marker/scroll-marker-group in keinem der ~100 geprüften Produktions-Bundles gefunden; Scroll-Snap-Basis dagegen verbreitet (by-kin.com, k72.ca, htarchitecte.com). Herabstufung) 02.11.2026: Priorität C → A (Lückenrecherche K2), weil steht in 15 Rezepten, Priorität C widersprach der tatsächlichen Nutzung."
 },
 "bau": {
  "status": "fertig",
  "kurz": "Produktreihe einer Münsteraner Rösterei als echter Scroller: Scroll-Snap, Pfeile und Punkte vom Browser, die eingerastete Tüte hebt sich per scroll-state(), ganz ohne JS.",
  "demo": true,
  "abhaengigkeiten": [],
  "werte": {
   "scroll_snap_type": "x mandatory",
   "scroll_snap_align": "center",
   "scroll_snap_stop": "always",
   "scroll_behavior": "smooth (reduziert: auto)",
   "padding_inline": "calc(50% - var(--breite) / 2), damit erste und letzte Karte mittig einrasten",
   "kartenbreite": "clamp(232px, min(25vw, 35svh), 340px); Telefon 74vw",
   "luecke": "clamp(16px, 2vw, 28px)",
   "scroll_button": "::scroll-button(left/right), content '‹' / 'Vorherige Sorte'; Browser scrollt ca. 85 % der Breite, durch scroll-snap-stop always genau eine Karte; per position-anchor an einen Platzhalter neben der Überschrift gesetzt",
   "scroll_marker": "scroll-marker-group: after; ::scroll-marker 8 × 8 px, :target-current 30 px breit",
   "aktivzustand": "@container scroll-state(snapped: x): opacity 0,46 → 1, Kachel scale 0,94 → 1, Tüte translate 0 −5 %",
   "easing": "cubic-bezier(0.33, 1, 0.68, 1)",
   "dauer_ms": 400,
   "ui_dauer_ms": 150,
   "durchlauf_view_timeline": "view-timeline inline je Slide; Tüte translateX 34 % → 0 → −34 %, rotate 9° → 0 → −9°, linear (Scroll ist die Zeit)",
   "fallback": "eigene Knöpfe scrollBy(±0,85 × clientWidth); IntersectionObserver mit rootMargin 0 −45 % (mittlere 10 %) setzt .ist-aktiv und den Zähler",
   "vorfuehrung": "Zeiger fährt in 750 ms zum Pfeil, Druck 160 ms (scale 0,92), danach 1300 ms Pause; Band läuft hin und zurück"
  },
  "ausloeser": "scroll",
  "touch": "Natives Wischen mit Einrasten, eine Karte pro Geste. Pfeile ausgeblendet, Punkt-Marker bleiben und sind antippbar; Karten 74vw breit. Varianten: Bühne und Kartenreihe ebenfalls per Wischen, Pfeile auf Touch aus; Bühnen-Reiter zeigen auf dem Telefon nur die Nummer. Variable Breiten: Wischen mit Einrasten am Bildanfang, Pfeile auf Touch aus, Zähler bleibt. Fenster: Wischen im Fenster mit Endlosschleife, die Haarlinien-Pfeile stehen auf dem Telefon unter dem Bild (120 px).",
  "reduziert": "scroll-behavior auto (Pfeile und Marker springen), keine view-timeline-Bewegung, Aktivzustand ohne Übergang. Einrasten und Hervorhebung bleiben. Varianten: kein Einzoomen des Bildes, kein Hover-Zoom, Marker ohne Übergang. Variable Breiten und Fenster: Pfeile springen ohne Gleiten, die Pfeil-Linie verkürzt sich ohne Übergang; der Sprung vom Klon zum Original ist ohnehin unsichtbar.",
  "korrekturen": {
   "name": "Natives CSS-Karussell (Scroll-Snap, Scroll-Buttons, Scroll-Marker)",
   "beschreibung": "Ein echter Scroller mit overflow-x auto und scroll-snap-type x mandatory. Die Kinder rasten mit scroll-snap-align center ein; scroll-snap-stop always sorgt für eine Karte pro Klick oder Geste. ::scroll-button(left/right) erzeugt die Pfeile mit Alt-Text, ::scroll-marker mit scroll-marker-group die Punkte als Tablist. Mit container-type scroll-state und @container scroll-state(snapped: x) hebt sich die eingerastete Karte hervor. Optional skaliert oder verschiebt eine view-timeline die Karten beim Durchlaufen.",
   "warum_es_wirkt": "Es ist echtes Scrollen: Trackpad, Mausrad, Wischen und Tastatur verhalten sich auf jedem Gerät so, wie man es erwartet. Es braucht kein JS, und Buttons und Marker bringen ihre Rollen für Tastatur und Screenreader mit. Für Claude ist es der robusteste Standard, auf den man aufbauen kann.",
   "wann_einsetzen": "Produktreihen, Shop-Teaser, Referenzen, Blog-Teaser und Karten-Slider auf Landingpages. Immer dann, wenn kein Endlos-Loop nötig ist.",
   "wann_nicht": "Wenn ein nahtloser Endlos-Loop, Trägheit mit eigener Physik oder eine 3D-Anordnung gefragt ist. Wenn Firefox- und Safari-Nutzer genau dieselbe Bedienung brauchen: Dort gibt es bisher nur Scroll-Snap und eigene Buttons.",
   "varianten": [
    "Nur Scroll-Snap mit eigenen Buttons (läuft überall)",
    "Mit ::scroll-button und ::scroll-marker als Punkte oder Farbfelder",
    "Mit scroll-state(snapped) für die aktive Karte",
    "Mit view-timeline für Skalierung oder Parallaxe beim Durchlaufen",
    "Mit interactivity: inert für nicht sichtbare Karten (laut Chrome-Configurator)",
    "Vollbild-Bühne: ein Bild füllt die Breite, Marker als Reiter mit Titel im Modus tabs (scroll-marker-group: after tabs, Chrome 154)",
    "Kartenreihe mit Peek: Start-Ausrichtung, die nächste Karte schaut an der Kante herein, Marker im Modus links",
    "Variable Breiten: gemischte Hoch- und Querformate in fester Höhe (width auto), Snap auf start, Pfeile blättern um die Sichtbreite, Zähler zeigt den sichtbaren Bereich",
    "Fenster: ein Bild in einem schmalen Fenster von etwa 4 Spalten, zentriert, Endlosschleife über Klone, keine Punkte, große 1-px-Haarlinien-Pfeile im Leerraum (nach Kereliott)"
   ],
   "umsetzung": "Progressive Enhancement. Basis ist Scroll-Snap mit eigenen Buttons (scrollBy) und einem IntersectionObserver für den Aktivzustand. Mit @supports selector(::scroll-button(right)) die eigenen Buttons ausblenden und die nativen nutzen. Die nativen Buttons lassen sich mit position-anchor an jede Stelle der Seite setzen. Fallstricke: Ohne scroll-snap-stop always überspringen schnelle Gesten Karten. scrollbar-width none nur mit sichtbaren Alternativen. Die Marker-Gruppe braucht ein eigenes Layout (flex, gap). Damit die erste und letzte Karte mittig einrasten, braucht der Scroller seitliches Padding von 50 % minus halber Kartenbreite.",
   "mobil": "Ideal: natives Wischen mit Einrasten. Pfeile auf Touch ausblenden, Marker behalten.",
   "reduzierte_bewegung": "scroll-behavior auto statt smooth. view-timeline-Effekte in der Media Query entfernen. Die Hervorhebung darf bleiben, aber ohne Übergang.",
   "barrierefreiheit": "Der Browser vergibt Rollen, Tab-Reihenfolge und Zustand für Buttons und Marker. Trotzdem braucht der Scroller ein aria-label und jede Karte eine eindeutige Beschriftung (z. B. „Aasee, 2 von 8“). Im Fallback eigene Buttons mit aria-label und aria-controls."
  },
  "geprueft": "03.11.2026",
  "notiz": "Rezept gastro-warm-appetitlich (Sektion Shop/Bohnen nennt dieses Muster). Erfundene Kaffeerösterei Speicher Neun am Hafen in Münster, acht Sorten, Abo und Röstkurs-Gutschein als CSS-Tüten mit Etikett und Bohnen (keine Fotos). Fraunces + Commissioner, Papier #f0ece0 mit Salbei, Senf, Rosé und Dunkelgrün. Drei Varianten: Nativ (0 Zeilen JS), Durchlauf (view-timeline) und Fallback (scrollBy + IntersectionObserver); ohne ::scroll-button-Unterstützung schaltet die Demo automatisch auf Fallback. Öffnungsstatus wird aus echten Zeiten berechnet. Referenzen: developer.chrome.com, momofuku.com, josephdirand.com. AD-Review 01.11.2026: Note 5. Varianten 01.11.2026: Umschalter im Fuß (?v=produktreihe|buehne|peek), die alte Umschaltung heißt jetzt „Technik“. „Vollbild-Bühne“: Lehmkuhl Architekten, Haus am Kalkberg, 6 SVG-Szenen, Marker als Reiter mit Titel im Modus tabs, Weiche „Fallback: eigene Reiter“ im Pult. „Kartenreihe mit Peek“: Hotel Haus Fernsicht, 5 Pakete, Marker im Modus links. Headless-Chromium 153 meldet CSS.supports für beide Modi bereits true; belegt ist der Modus ab Chrome 154. Fallstrick: ::scroll-marker mit Text braucht eine feste Höhe, sonst rechnet Chrome 153 die Höhe 0. Zugang 02.11.2026: --leise Alpha .62 → .75 (Bühne .6 → .68, Peek .62 → .78), --p-meta #82847f → #666863; Salbei als Textfarbe #586b54 (neues Token --salbei-text), Wortmarke „Neun“ #70836b; Kontrastmodus-Rahmen für Knöpfe. Offen: Die abgedunkelten Nachbarkarten (opacity .46, Kern des scroll-state(snapped)-Effekts) bleiben unter 4,5:1; Tütenetiketten (aria-hidden, Name steht in h3) werden bei Textabständen 1.4.12 beschnitten; „kein Fokusstil“ am Band betrifft die ::scroll-button-Pseudoelemente, die einen sichtbaren Ring haben (Fehlalarm). Varianten 03.11.2026: „Variable Breiten“ (Rezept fotograf-film-bild-zuerst): Mara Seelig Fotografie in Kassel, Serie Stille Räume, 10 Bilder hoch und quer aus medien/, Instrument Serif + Instrument Sans + Fragment Mono, Gleiten 800 ms cubic-bezier(0.76, 0, 0.24, 1). „Fenster“ (Rezept boutique-hotel-gastgeber): Ferienhaus Haus Oberhagen am Großen Plöner See, 8 Bilder im Fenster 4:5, Newsreader + Mona Sans, nativ mit Scroll-Snap, eigenen Pfeilen und je einem Klon vorn und hinten; Gleiten 900 ms cubic-bezier(0.37, 0, 0.63, 1), Dauer abgeleitet aus Flickity friction 0.28 und selectedAttraction 0.025 (Kereliott live gemessen, 98 % des Wegs nach ≈ 830 ms). Steuerung und Anzeige (Zähler, Leiste, Daumen, Selbstlauf, Anker) stehen jetzt im eigenen Muster karussell-steuerung, nur-mobil und zweireihig in raster-zu-wischreihe. Prüfung: bestehende drei Varianten unverändert (kein Querscrollen, keine Fehler), neue Varianten ohne Befund in pruef-zugang. Selbsturteil neue Varianten 4.",
  "varianten": [
   {
    "id": "produktreihe",
    "name": "Produktreihe",
    "wann": "Shop, Rösterei, Mode, d2c: viele gleichrangige Produkte, die mittlere hebt sich hervor (Technik umschaltbar: Nativ, Durchlauf, Fallback).",
    "werte": {
     "aufbau": "Karten mittig eingerastet (padding-inline 50 % minus halbe Karte), scroll-state(snapped) hebt hervor",
     "marker": "scroll-marker-group: after (Standardmodus), Punkte",
     "rezept": "gastro-warm-appetitlich",
     "details": "siehe bau.werte"
    }
   },
   {
    "id": "buehne",
    "name": "Vollbild-Bühne",
    "wann": "Architektur, Fotografie, Praxisräume, Galerie einer Kanzlei: ein Bild zur Zeit, die Reiter nennen den Raum.",
    "werte": {
     "aufbau": "grid-auto-columns: 100 %, snap center, stop always; Bildhöhe min(60svh, 52vw), Telefon 62vw",
     "marker": "::scroll-marker als Reiter mit content: attr(data-nr) \"  \" attr(data-titel) (Telefon nur Nummer); scroll-marker-group: after, per @supports (scroll-marker-group: after tabs) im Modus tabs",
     "modus_tabs": "ab Chrome 154: Gruppe role tablist, Marker role tab, Folien role tabpanel, nur der aktive Marker ist Tab-Stopp, Pfeiltasten wechseln, inaktive Folien nicht im Accessibility-Baum",
     "fallback": "ohne ::scroll-marker (oder per Pult erzwungen): eigene Reiter role=tab mit roving tabindex, Pfeiltasten, inaktive Folien aria-hidden, Aktivzustand per IntersectionObserver (Mitte ±5 %), eigene Pfeilknöpfe",
     "pfeile": "::scroll-button eckig 44px, per position-anchor neben den Projektdaten",
     "bild": "scale 1,06 → 1, 1000 ms cubic-bezier(0.1, 0.9, 0.3, 1) per @container scroll-state(snapped: x)",
     "ui": "250 ms cubic-bezier(0.1, 0.6, 0.4, 1)",
     "schrift": "Instrument Sans 450 (Titel), Instrument Serif kursiv als Akzent, Geist Mono (Reiter)",
     "farben": "Grund #FFFFFF, Text #231F20, Meta #76767A, Fläche #E1E3E3, Fokus #0022FF",
     "bilder": "eigene SVG-Szenen",
     "rezept": "architektur-ruhiges-raster"
    }
   },
   {
    "id": "peek",
    "name": "Kartenreihe mit Peek",
    "wann": "Hotel-Pakete, Kurse, Projekte, Use Cases: mehrere Angebote nebeneinander, die angeschnittene nächste Karte zeigt, dass es weitergeht.",
    "werte": {
     "aufbau": "snap start, padding-inline und scroll-padding-inline = Seitenrand; Karte clamp(240px, 26vw, 360px), Telefon 80vw; Lücke clamp(14px, 1.6vw, 24px)",
     "marker": "scroll-marker-group: after, per @supports (scroll-marker-group: after links) im Modus links: Gruppe role navigation, jeder Marker ein Link und eigener Tab-Stopp (ab Chrome 154, Standardmodus)",
     "marker_form": "Strich 28 × 2 px, aktiv 44 px",
     "pfeile": "::scroll-button rund 44px per position-anchor rechts über der Reihe; ohne Unterstützung eigene Knöpfe (scrollBy ± eine Karte)",
     "bild": "Hover scale 1,04, 1100 ms cubic-bezier(0.37, 0, 0.63, 1)",
     "ui": "200 ms cubic-bezier(0.4, 0, 0.2, 1)",
     "schrift": "Newsreader 300/400 (Titel), Archivo wdth 125 versal (Labels), Archivo (Text)",
     "farben": "Grund #F3EEE7, Creme #FEF2E3, Text #3E3A37, Linie #D5D1C8, Meta #82847F, Holz #6E5A47",
     "bilder": "eigene SVG-Szenen",
     "rezept": "boutique-hotel-gastgeber"
    }
   },
   {
    "id": "variable-breiten",
    "name": "Variable Breiten",
    "wann": "Fotograf, Kreativstudio, Handwerk (Referenzen), Kultur: Bildserien mit gemischten Hoch- und Querformaten, die nicht beschnitten werden sollen.",
    "werte": {
     "rezept": "fotograf-film-bild-zuerst",
     "aufbau": "display flex, feste Höhe clamp(220px, min(54svh, 62vw), 600px), img width auto aus width/height, Lücke clamp(10px, 1.2vw, 16px); figure width min-content, damit die Bildunterschrift umbricht",
     "snap": "start, scroll-padding-inline = Seitenrand",
     "pfeile": "blättern um die Sichtbreite: vor = erstes angeschnittenes Bild wird erstes, zurück = eine Sichtbreite zurück auf den nächsten Bildanfang; Tastatur ein Bild",
     "gleiten": "800 ms cubic-bezier(0.76, 0, 0.24, 1), Snap während der Kurve aus",
     "zaehler": "sichtbarer Bereich „03–05 / 10“ in Fragment Mono 0.75rem tabular-nums",
     "schrift": "Instrument Serif (Name, Titel), Instrument Sans, Fragment Mono",
     "farben": "Grund #F4F4F2, Text #141414, Meta #6D6D6D, Platzhalter #E6E6E6",
     "bilder": "medien/ (selbst erzeugt)"
    }
   },
   {
    "id": "fenster",
    "name": "Fenster",
    "wann": "Ferienhaus, Hotel, Manufaktur, Fotograf: ruhig, ein Bild nach dem anderen, ohne Punkte und ohne Ende.",
    "werte": {
     "rezept": "boutique-hotel-gastgeber",
     "fenster": "min(30.7vw, 48svh, 520px) (Kereliott: 442 px bei 1440), 4:5, zentriert in einem Raster 1fr / Fenster / 1fr; Telefon min(78vw, 56svh)",
     "schleife": "Klon des letzten Bildes vorn, des ersten hinten (aria-hidden, inert); nach dem Einrasten auf einem Klon unsichtbarer Sprung zum Original",
     "pfeile": "1-px-Haarlinie 168 px lang auf halber Fensterhöhe im Leerraum, Hover verkürzt den Schaft auf 82 % und schiebt die Spitze 22 px, 600 ms",
     "punkte": "keine; Bildname kursiv unter dem Fenster, Ansage „Bild 3 von 8: …“",
     "gleiten": "900 ms cubic-bezier(0.37, 0, 0.63, 1); Flickity friction 0.28, selectedAttraction 0.025 erreicht 98 % nach ≈ 830 ms",
     "schrift": "Newsreader 300 und kursiv, Mona Sans wdth 125 versal",
     "farben": "Grund #F3EEE7, Text #3E3A37, Meta #6A6C67, Holz #6E5A47",
     "bilder": "medien/ (selbst erzeugt, Hochformate)"
    }
   }
  ]
 }
}
