/* Echte Angebotsfotos aus dem Dashboard (server.mjs setzt die Karten ein, store.js füllt die Detailansicht).
   Das Foto steht immer ganz im Bild (contain), so schneidet kein Hoch- oder Querformat Ärmel ab. Die freien Ränder malt
   paintPhotoEdges() in store.js mit den Randfarben des Fotos (.has-edges); bis dahin füllt eine unscharfe Kopie. */
.product-image .product-photo-fill,
.product-image .product-photo { position: absolute; display: block; pointer-events: none; }
.product-image .product-photo-fill { z-index: 1; inset: -10%; width: 120%; height: 120%; max-width: none; object-fit: cover; filter: blur(22px) brightness(.72) saturate(.9); }
.product-image.has-edges .product-photo-fill, .product-image.has-edges::before, .product-image.has-edges::after { display: none; }
/* Der Innenschatten der Karte würde nur den gemalten Rand abdunkeln, nicht das Foto darüber. */
.product-image.has-edges, :root[data-theme="light"] .product-image.has-edges { box-shadow: none; }
.product-image.has-edges:hover { box-shadow: inset 0 0 0 1px rgba(245,246,242,.38); }
:root[data-theme="light"] .product-image.has-edges:hover { box-shadow: inset 0 0 0 1px rgba(var(--ink-rgb),.38); }
.product-image .product-photo { z-index: 2; inset: 0; width: 100%; height: 100%; object-fit: contain; transition: transform .7s var(--ease, ease); }
.product-image:hover .product-photo, .product-image:focus-visible .product-photo { transform: scale(1.03); }

.dialog-gallery { position: absolute; inset: 0; overflow: hidden; }
.dialog-gallery .dialog-photo-fill,
.dialog-gallery .dialog-photo { position: absolute; display: block; }
.dialog-gallery .dialog-photo-fill { inset: -10%; width: 120%; height: 120%; max-width: none; object-fit: cover; filter: blur(28px) brightness(.66) saturate(.9); }
.dialog-gallery.has-edges .dialog-photo-fill { display: none; }
.dialog-gallery .dialog-photo { inset: 0; width: 100%; height: 100%; object-fit: contain; }
.dialog-thumbs { position: absolute; right: 12px; bottom: 12px; left: 12px; display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; }
.dialog-thumbs::-webkit-scrollbar { display: none; }
.dialog-thumb { flex: 0 0 auto; width: 50px; height: 50px; padding: 0; overflow: hidden; border: 1px solid rgba(245,246,242,.35); background: #000; opacity: .72; }
.dialog-thumb[aria-pressed="true"] { border-color: #f5f6f2; opacity: 1; }
.dialog-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.dialog-more { border-top: 0; }
.dialog-description { white-space: pre-line; }

.cart-thumb.has-photo { overflow: hidden; aspect-ratio: 1; }
.cart-thumb.has-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }

:root[data-theme="light"] .product-image .product-photo-fill { filter: blur(22px) brightness(1.02) saturate(.85); }
:root[data-theme="light"] .dialog-gallery .dialog-photo-fill { filter: blur(28px) brightness(1.02) saturate(.85); }
:root[data-theme="light"] .dialog-thumb { border-color: rgba(17,17,17,.25); background: #fff; }
:root[data-theme="light"] .dialog-thumb[aria-pressed="true"] { border-color: #111; }

/* Am Handy ist das Dialogfoto nur ~250 px hoch: kleine Vorschaubilder links unten statt einer breiten Leiste über dem Motiv. */
@media (max-width: 680px) {
  .dialog-thumbs { right: auto; bottom: 8px; left: 8px; gap: 4px; }
  .dialog-thumb { width: 34px; height: 34px; }
}

@media (prefers-reduced-motion: reduce) {
  .product-image .product-photo { transition: none; }
  .product-image:hover .product-photo, .product-image:focus-visible .product-photo { transform: none; }
}

/* Ausverkauft (30.09.2026): im Dashboard umschaltbar. Die Karte bleibt stehen, damit man sieht, was schon weg ist:
   Foto entsättigt, Stempel drüber, kein Herz, kein Weg in die Tasche (store.js). server.mjs stellt sie hinter das Verfügbare. */
.product-card.is-sold .product-image { filter: grayscale(.85) brightness(.74); }
.product-card.is-sold .photo-slot { opacity: .55; }
.sold-badge { position: absolute; z-index: 3; top: 50%; left: 50%; padding: 8px 12px 7px; border: 1px solid rgba(245,246,242,.82); color: #f5f6f2; background: rgba(8,8,8,.74); font: 10px/1 var(--mono); letter-spacing: .22em; white-space: nowrap; pointer-events: none; transform: translate(-50%,-50%) rotate(-7deg); box-shadow: 0 10px 26px rgba(0,0,0,.35); }
.product-dialog.is-sold .dialog-price { color: var(--muted); }
/* Verkauft: „Nicht mehr verfügbar“ an der Stelle von „Größe einschätzen ↗“ (store.js fillProduct, 21.10.2026). */
.dialog-size-head .dialog-sold-tag { color: var(--paper); font: 700 8px var(--mono); letter-spacing: .12em; text-transform: uppercase; }
:root[data-theme="light"] .product-card.is-sold .product-image { filter: grayscale(.85) brightness(.96) contrast(.92); }
:root[data-theme="light"] .sold-badge { border-color: rgba(17,17,17,.72); color: #1a1a18; background: rgba(250,249,245,.88); box-shadow: 0 10px 24px rgba(var(--ink-rgb),.14); }
@media (max-width: 680px) {
  .sold-badge { padding: 6px 8px 5px; font-size: 7px; letter-spacing: .18em; }
}
/* Gerade gekauft (store.js archiveTasche.gekauft, 03.11.2026): Solange die Kasse offen ist, sieht die Karte noch aus wie
   vorher. Geht sie zu, knallt der Stempel von oben drauf, die Karte ruckt kurz und das Foto wird grau. */
.product-card.wird-verkauft .product-image { filter: none; }
.product-card.wird-verkauft .sold-badge { opacity: 0; }
.product-card.stempelt .product-image { transition: filter .7s ease .32s; }
.product-card.stempelt .sold-badge { animation: stempel-drauf .5s cubic-bezier(.2, 1.4, .4, 1) .3s both; }
.product-card.stempelt .product-image-wrap { animation: stempel-ruck .32s ease-out .62s; }
@keyframes stempel-drauf {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(-18deg) scale(2.4); }
  55% { opacity: 1; }
  100% { opacity: 1; transform: translate(-50%, -50%) rotate(-7deg) scale(1); }
}
@keyframes stempel-ruck { 35% { transform: scale(.975); } }
@media (prefers-reduced-motion: reduce) {
  .product-card.stempelt .product-image { transition: none; }
  .product-card.stempelt .sold-badge, .product-card.stempelt .product-image-wrap { animation: none; }
}

/* Letzte Verkäufe (06.10.2026): Unter verkauften Karten steht, wann das Stück verkauft wurde und wann es von der Seite
   verschwindet (server.mjs verkauftNotiz, store.js renderSoldNotes). Die vier Tageskästchen davor sind auf Michas Wunsch
   weg (06.10.2026), es steht nur noch der Text. */
.sold-note { display: flex; align-items: center; gap: 8px; margin-top: 9px; color: #9a9a95; font: 7.5px/1.4 var(--mono); letter-spacing: .13em; text-transform: uppercase; }
:root[data-theme="light"] .sold-note { color: var(--ink-note); }
@media (max-width: 680px) {
  .sold-note { gap: 6px; margin-top: 7px; font-size: 6.5px; letter-spacing: .1em; }
}

/* Flamme „Beliebt“ (06.10.2026): im Dashboard pro Artikel an- und ausschaltbar (server.mjs setzt .is-hot und das Schild).
   Selbst gezeichnete Flamme, kein Emoji; sie lodert (unten), bei reduzierter Bewegung steht sie still. */
.hot-badge { position: absolute; z-index: 4; top: 11px; left: 12px; display: inline-flex; align-items: center; gap: 6px; padding: 5px 9px 5px 7px; border: 1px solid rgba(239,242,242,.38); color: var(--paper); background: rgba(17,19,20,.66); box-shadow: inset 0 1px 0 rgba(248,250,250,.12), 0 4px 14px rgba(0,0,0,.22); -webkit-backdrop-filter: blur(9px) saturate(1.1); backdrop-filter: blur(9px) saturate(1.1); pointer-events: none; }
.hot-badge[hidden] { display: none; }
.hot-badge b { font: 700 8px/1 var(--mono); letter-spacing: .18em; }
/* Die Flamme lodert (06.10.2026, Michas „animiere diese Flamme noch“): die äußere Flamme zuckt unregelmäßig und wechselt
   zwischen Orange und Rot, der helle Kern züngelt im eigenen Takt, ein warmer Schein pulsiert, zwei Funken steigen auf. */
.hot-flame { position: relative; z-index: 1; display: block; width: 14px; height: 14px; overflow: visible; transform-origin: 50% 92%; animation: hot-lodern 1.7s linear infinite, hot-schein 2.3s ease-in-out infinite; will-change: transform; }
.hot-flame path { transform-box: fill-box; transform-origin: 50% 100%; }
.hot-flame-aussen { fill: #ff6a1f; animation: hot-farbe 2.9s ease-in-out infinite; }
.hot-flame-innen { fill: #ffd76a; animation: hot-kern .95s ease-in-out infinite alternate; }
@keyframes hot-lodern {
  0% { transform: scale(1, 1) skewX(0deg); }
  11% { transform: scale(.93, 1.11) skewX(-5deg) translateY(-.4px); }
  23% { transform: scale(1.05, .94) skewX(2deg); }
  36% { transform: scale(.96, 1.09) skewX(6deg) translateY(-.3px); }
  49% { transform: scale(1.03, .97) skewX(-2deg); }
  61% { transform: scale(.94, 1.14) skewX(-6deg) translateY(-.6px); }
  74% { transform: scale(1.04, .95) skewX(3deg); }
  87% { transform: scale(.97, 1.07) skewX(-2deg) translateY(-.2px); }
  100% { transform: scale(1, 1) skewX(0deg); }
}
@keyframes hot-schein {
  0%, 100% { filter: drop-shadow(0 0 1.5px rgba(255,106,31,.55)) drop-shadow(0 0 4px rgba(255,80,20,.25)); }
  50% { filter: drop-shadow(0 0 3px rgba(255,140,40,.9)) drop-shadow(0 0 8px rgba(255,90,20,.45)); }
}
@keyframes hot-farbe {
  0%, 100% { fill: #ff6a1f; }
  35% { fill: #ff8a2b; }
  70% { fill: #ff4d18; }
}
@keyframes hot-kern {
  0% { transform: scale(1, .9) translateY(.3px); fill: #ffd76a; }
  100% { transform: scale(.82, 1.16) translateY(-.4px); fill: #fff2bf; }
}
/* Funken: zwei Glutpunkte steigen über der Flamme auf und verglühen, leicht versetzt. */
.hot-badge::before,
.hot-badge::after { position: absolute; z-index: 2; top: 6px; left: 12px; width: 2px; height: 2px; border-radius: 50%; background: #ffb347; box-shadow: 0 0 3px 1px rgba(255,140,40,.8); content: ""; opacity: 0; pointer-events: none; animation: hot-funke 1.8s ease-out infinite; }
.hot-badge::after { left: 15px; width: 1.5px; height: 1.5px; animation-duration: 2.4s; animation-delay: .9s; }
@keyframes hot-funke {
  0% { opacity: 0; transform: translate(0, 0) scale(1); }
  15% { opacity: 1; }
  100% { opacity: 0; transform: translate(-3px, -14px) scale(.4); }
}
.hot-badge::after { animation-name: hot-funke-rechts; }
@keyframes hot-funke-rechts {
  0% { opacity: 0; transform: translate(0, 0) scale(1); }
  20% { opacity: 1; }
  100% { opacity: 0; transform: translate(3px, -12px) scale(.4); }
}
.dialog-hot { top: 16px; left: 16px; padding: 7px 11px 7px 9px; }
.dialog-hot .hot-flame { width: 16px; height: 16px; }
.dialog-hot::before { top: 9px; left: 15px; }
.dialog-hot::after { top: 9px; left: 19px; }
.dialog-hot b { font-size: 9px; }
/* Kopfleiste des Produktfensters (22.10.2026, Micha: „beim Runterscrollen sollen Schließen und Beliebt oben bleiben“): Kreuz
   und Flamme liegen zusammen in .dialog-oben (index.html). Am Laptop über dem Bild wie vorher, am Handy klebt die Leiste beim
   Scrollen oben (handy.css). */
.product-dialog > .dialog-oben { position: absolute; z-index: 6; top: 0; right: 0; left: 0; height: 0; }
:root[data-theme="light"] .hot-badge { border-color: rgba(17,17,17,.24); color: #1a1a18; background: rgba(250,249,245,.86); box-shadow: 0 6px 16px rgba(var(--ink-rgb),.12); }
@media (max-width: 680px) {
  .hot-badge { top: 8px; left: 8px; gap: 4px; padding: 4px 6px 4px 5px; }
  .hot-badge b { font-size: 6.5px; letter-spacing: .14em; }
  .hot-flame { width: 11px; height: 11px; }
  .hot-badge::before { top: 4px; left: 9px; }
  .hot-badge::after { top: 4px; left: 11px; }
}
@media (prefers-reduced-motion: reduce) {
  .hot-flame, .hot-flame-aussen, .hot-flame-innen { animation: none; }
  .hot-badge::before, .hot-badge::after { display: none; }
}

/* Filter und Sortierung auch über den verkauften Stücken im Drop-Modus (06.10.2026, Michas „da fehlt das Sortieren, Filtern“).
   drop.css blendet Reiter, Leiste und Trefferzeile dort aus; drop.css bleibt unverändert, diese Regeln sind stärker (:not([hidden])). */
html[data-modus="drop"] .shop-section .category-row:not([hidden]),
html[data-modus="drop"] .shop-section .shop-toolbar:not([hidden]),
html[data-modus="drop"] .shop-section .results-line:not([hidden]) { display: flex; }
html[data-modus="drop"] .shop-section .empty-results:not([hidden]) { display: block; }

/* Shop auf dem Laptop (06.10.2026, Michas „angenehmer auf dem Laptop-Bildschirm“): vorher lagen 480 px zwischen Abschnittsanfang
   und erster Reihe und die Karten waren 410 × 520 px groß, auf 1440 × 790 sah man nur ihren oberen Rand. Jetzt: kompakter Kopf,
   schmalere Filterleiste, vier Spalten ab 1100 px, fünf ab 1700 px. Unter 981 px gilt alles wie bisher. */
@media (min-width: 981px) {
  .shop-section { padding-top: 52px; padding-bottom: 56px; }
  .shop-heading { padding: 16px 0 20px; }
  .shop-heading h2 { font-size: clamp(40px, 4.2vw, 62px); }
  .shop-heading h2 span { margin-top: 10px; }
  html[data-modus="drop"] .shop-section .shop-heading { margin-bottom: 0; }
  .category-row { gap: 6px 24px; padding: 12px 0 8px; }
  .category-tab { font-size: 13px; }
  .shop-toolbar { padding: 10px 0 9px; }
  .results-line { padding: 12px 0 4px; }
}
@media (min-width: 1100px) {
  .product-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 30px 14px; }
}
@media (min-width: 1700px) {
  .product-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

/* Zwei Reihen und Pfeil (shop-falten.js): gefaltet ist das Raster bis knapp in die dritte Reihe hoch, darunter verblasst der
   Anschnitt hinter dem Knopf. clip-path statt overflow, damit Schatten und Schilder an den Seiten nicht abgeschnitten werden. */
.product-grid.is-gefaltet { clip-path: inset(-40px -40px 0 -40px); }
.product-grid.is-wachsend { transition: max-height .8s cubic-bezier(.6, 0, .2, 1); }
.product-card.is-aufgeklappt { animation: falt-auf .7s cubic-bezier(.2, .8, .2, 1) calc(.12s + var(--falt-i, 0) * 60ms) backwards; }
@keyframes falt-auf { from { opacity: 0; transform: translateY(26px); } }
.shop-mehr { position: relative; z-index: 2; display: flex; justify-content: center; margin-top: -112px; padding-top: 74px; background: linear-gradient(180deg, transparent, var(--black) 62%); pointer-events: none; }
.shop-mehr[hidden] { display: none; }
.shop-mehr.is-offen { margin-top: 0; padding-top: 34px; background: none; }
.shop-mehr::before { position: absolute; right: 0; bottom: 21px; left: 0; height: 1px; background: var(--line-soft); content: ""; }
.shop-mehr-knopf { position: relative; display: inline-flex; align-items: center; gap: 14px; padding: 9px 9px 9px 20px; border: 1px solid var(--line); border-radius: 999px; color: var(--paper); background: var(--black); font: 9px/1 var(--mono); letter-spacing: .16em; cursor: pointer; pointer-events: auto; transition: border-color .25s, background-color .25s; }
.shop-mehr-knopf:hover { border-color: var(--paper); }
.shop-mehr-knopf:focus-visible { outline: 1px solid var(--paper); outline-offset: 4px; }
.shop-mehr-pfeil { display: grid; width: 26px; height: 26px; place-items: center; border-radius: 50%; color: var(--black); background: var(--paper); }
.shop-mehr-pfeil svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform .35s cubic-bezier(.3, 1.4, .5, 1); }
.shop-mehr:not(.is-offen) .shop-mehr-pfeil svg { animation: falt-wink 2.2s ease-in-out infinite; }
.shop-mehr-knopf:hover .shop-mehr-pfeil svg { animation: none; transform: translateY(2px); }
.shop-mehr.is-offen .shop-mehr-pfeil svg { animation: none; transform: rotate(180deg); }
@keyframes falt-wink { 0%, 60%, 100% { transform: none; } 75% { transform: translateY(3px); } 88% { transform: translateY(-1px); } }
@media (max-width: 680px) {
  .shop-mehr { margin-top: -96px; padding-top: 62px; }
  .shop-mehr-knopf { font-size: 8px; }
}
@media (prefers-reduced-motion: reduce) {
  .product-card.is-aufgeklappt, .shop-mehr-pfeil svg { animation: none !important; }
}

/* Lesbarkeit der Karten (06.10.2026, Michas „Titel und so muss besser erkennbar sein“): etwas größer und heller als
   in styles.css; verkaufte Karten sind nur noch am Foto und Stempel gedämpft, nicht mehr am Text. */
.product-brand { color: #bdbdb8; font-size: 9px; }
.product-title { margin: 7px 0 6px; font-size: 15.5px; font-weight: 600; }
.product-size { color: #ababa6; font-size: 10px; }
.product-size i { color: #66665f; }
.condition-tag { color: #96968f; font-size: 8px; }
.product-price { color: #f0f0ec; font-size: 12px; }
.sold-note { color: #b3b3ad; font-size: 8.5px; }
/* Kurzbeschreibung aus dem Dashboard (06.10.2026): eine leise Zeile Fließtext zwischen Titel und Größe, höchstens 70 Zeichen.
   In der Detailansicht steht sie unter dem Titel (.dialog-kurz), die lange Beschreibung bleibt darunter. */
.product-kurz { display: block; max-width: 100%; margin: -1px 0 7px; color: #c2c2bd; font: 400 12px/1.4 var(--sans); overflow-wrap: anywhere; }
.dialog-kurz { margin: 10px 0 0; color: #c8c8c3; font: 400 14px/1.45 var(--sans); overflow-wrap: anywhere; }
.dialog-kurz[hidden] { display: none; }
:root[data-theme="light"] .product-kurz { color: var(--ink-body); }
:root[data-theme="light"] .dialog-kurz { color: var(--ink-soft); }
@media (max-width: 680px) {
  .product-brand { font-size: 7.5px; }
  .product-kurz { margin: -1px 0 6px; font-size: 10.5px; line-height: 1.35; }
  .dialog-kurz { font-size: 13px; }
  .product-title { margin: 6px 0 5px; font-size: 12.5px; }
  .product-size { font-size: 8.5px; }
  .condition-tag { font-size: 7px; }
  .product-price { font-size: 10px; }
  .sold-note { gap: 5px; font-size: 7.5px; letter-spacing: .05em; white-space: nowrap; }
}
@media (max-width: 370px) {
  .product-brand { font-size: 7px; }
  .product-title { font-size: 12px; }
  .sold-note { font-size: 7px; letter-spacing: .03em; }
}

/* Bildstrecke in der Detailansicht (06.10.2026): waagerecht wischen oder scrollen, rastet je Foto ein (store.js fillProductPhotos). */
.dialog-bahn { position: absolute; inset: 0; display: flex; overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.dialog-bahn::-webkit-scrollbar { display: none; }
.dialog-slide { position: relative; flex: 0 0 100%; height: 100%; overflow: hidden; scroll-snap-align: center; scroll-snap-stop: always; }
.dialog-slide.has-edges .dialog-photo-fill { display: none; }
.dialog-pfeil { position: absolute; z-index: 3; top: 50%; display: grid; width: 40px; height: 40px; place-items: center; margin-top: -20px; padding: 0; border: 1px solid rgba(239,242,242,.38); border-radius: 50%; color: #f5f6f2; background: rgba(17,19,20,.62); box-shadow: inset 0 1px 0 rgba(248,250,250,.12), 0 4px 14px rgba(0,0,0,.22); -webkit-backdrop-filter: blur(9px); backdrop-filter: blur(9px); font: 17px/1 var(--sans); cursor: pointer; transition: opacity .2s, transform .2s; }
.dialog-pfeil-zurueck { left: 12px; }
.dialog-pfeil-weiter { right: 12px; }
.dialog-pfeil:disabled { opacity: 0; pointer-events: none; }
.dialog-pfeil-zurueck:hover { transform: translateX(-2px); }
.dialog-pfeil-weiter:hover { transform: translateX(2px); }
.dialog-zahl { position: absolute; z-index: 3; top: 14px; right: 14px; padding: 5px 9px; border: 1px solid rgba(239,242,242,.3); color: #f5f6f2; background: rgba(17,19,20,.6); font: 9px/1 var(--mono); letter-spacing: .16em; pointer-events: none; }
:root[data-theme="light"] .dialog-pfeil,
:root[data-theme="light"] .dialog-zahl { border-color: rgba(17,17,17,.24); color: #1a1a18; background: rgba(250,249,245,.86); }
@media (max-width: 680px) {
  .dialog-pfeil { width: 34px; height: 34px; margin-top: -17px; font-size: 15px; }
  .dialog-pfeil-zurueck { left: 8px; }
  .dialog-pfeil-weiter { right: 8px; }
  .dialog-thumb { width: 42px; height: 42px; }
  /* Oben rechts liegt am Handy das Schließen-Kreuz der Detailansicht: der Zähler steht darum unten links über den Vorschaubildern. */
  .dialog-zahl { top: auto; right: auto; bottom: 62px; left: 10px; }
}

/* Fotos auf der Karte (06.10.2026): Bei mehreren Fotos macht store.js startCardPhotos() aus dem Kartenfoto eine Laufleiste
   (.card-bahn) mit einer Seite je Foto (.card-slide), dazu Pfeile beim Drüberfahren und Punkte.
   Am Handy wischt man, die Pfeile gibt es dort nicht.
   Neu gefasst am 06.11.2026 (Michas „nicht angenehm, nicht clean“): Der Rahmen hat das Format der Fotos (3:4), vorher malte
   paintPhotoEdges neben jedem Foto Randstreifen, die mitgewischt wurden.
   Am Ende der Leiste federt nichts nach (overscroll none), sonst blitzt beim Nachziehen der Grund hinter dem Foto auf.
   Die Fuge (gap) hält die Seiten auseinander: Die Karte ist am Handy oft 160,5 Punkte breit, ohne Fuge lugt beim Runden ein
   Pixel des nächsten Fotos am rechten Rand hervor. */
.product-image { aspect-ratio: 3 / 4; }
.product-image.has-strip::before, .product-image.has-strip::after { display: none; animation: none; }
.product-image .card-bahn { position: absolute; z-index: 2; inset: 0; display: flex; gap: 2px; overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; overscroll-behavior-x: none; scrollbar-width: none; touch-action: manipulation; -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
.product-image .card-bahn::-webkit-scrollbar { display: none; }
.product-image .card-slide { position: relative; display: block; flex: 0 0 100%; height: 100%; overflow: hidden; background: #141516; scroll-snap-align: start; scroll-snap-stop: always; }
:root[data-theme="light"] .product-image .card-slide { background: #e8e6e0; }
.card-pfeil { position: absolute; z-index: 3; top: 50%; display: grid; width: 34px; height: 34px; margin-top: -17px; place-items: center; padding: 0; border: 1px solid rgba(232,232,229,.38); border-radius: 50%; color: var(--paper); background: rgba(8,8,8,.62); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); opacity: 0; cursor: pointer; transition: opacity .2s, translate .2s, background-color .2s; }
.card-pfeil-zurueck { left: 10px; translate: -5px 0; }
.card-pfeil-weiter { right: 10px; translate: 5px 0; }
.card-pfeil svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.product-image-wrap:hover .card-pfeil:not(:disabled), .card-pfeil:focus-visible { opacity: 1; translate: 0 0; }
.card-pfeil:hover { background: rgba(8,8,8,.86); }
.card-pfeil:disabled { pointer-events: none; }
.card-punkte { position: absolute; z-index: 3; bottom: 12px; left: 12px; display: flex; align-items: center; gap: 4px; padding: 6px 8px; border-radius: 999px; background: rgba(8,8,8,.52); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); pointer-events: none; }
.card-punkte i { display: block; width: 5px; height: 5px; border-radius: 3px; background: rgba(245,246,242,.42); transition: width .25s, background-color .25s; }
.card-punkte i.is-an { width: 15px; background: #f5f6f2; }
:root[data-theme="light"] .card-pfeil { border-color: rgba(17,17,17,.22); color: #1a1a18; background: rgba(250,249,245,.86); }
:root[data-theme="light"] .card-pfeil:hover { background: #faf9f5; }
:root[data-theme="light"] .card-punkte { background: rgba(250,249,245,.82); }
:root[data-theme="light"] .card-punkte i { background: rgba(26,26,24,.3); }
:root[data-theme="light"] .card-punkte i.is-an { background: #1a1a18; }
/* Am Handy gibt es kein Drüberfahren: iOS lässt :hover nach dem Tippen stehen, und :active staucht das Foto, sobald der Finger
   aufsetzt. Beides ruckt am Anfang des Wischens. Herz, Schild und Punkte liegen ohne Unschärfe auf dem Foto, sonst rechnet das
   Handy sie beim Wischen in jedem Bild neu. Herz und Schild sind dazu fast deckend, auf weißen Fotos wären sie ein grauer Fleck. */
@media (hover: none) {
  .card-pfeil { display: none; }
  .product-image { transition: none; }
  .product-image:hover { filter: none; }
  .product-image:active { transform: none; }
  .product-image:hover .product-photo { transform: none; }
  .product-card :is(.favorite-button, .hot-badge, .card-punkte) { -webkit-backdrop-filter: none; backdrop-filter: none; }
  .product-card :is(.hot-badge, .favorite-button:not([aria-pressed="true"])) { background: rgba(17,19,20,.88); }
  :root[data-theme="light"] .product-card :is(.hot-badge, .favorite-button:not([aria-pressed="true"])) { background: rgba(250,249,245,.95); }
}
@media (max-width: 680px) {
  .card-punkte { bottom: 8px; left: 8px; gap: 3px; padding: 5px 6px; }
  .card-punkte i { width: 4px; height: 4px; }
  .card-punkte i.is-an { width: 11px; }
}
@media (prefers-reduced-motion: reduce) {
  .card-pfeil, .card-punkte i { transition: none; }
}

/* Leere Tasche (06.10.2026, store.js renderCartEmpty): Bügel an der Stange schwingt beim Öffnen ein und pendelt dann leise,
   das Preisschild schwingt etwas nach. Farben über currentColor und die Theme-Tokens, damit es hell wie dunkel passt. */
.cart-empty { min-height: 0; justify-content: flex-start; }
/* Nur dieser Teil rollt, der Knopf darunter bleibt immer ganz zu sehen. Die Maske lässt den Inhalt weich vor dem Knopf auslaufen. */
.leer-rollbar { display: flex; width: 100%; min-height: 0; flex: 1; flex-direction: column; align-items: center; padding: clamp(18px, 5vh, 54px) 0 26px; overflow: hidden auto; overscroll-behavior: contain; scrollbar-width: none; -webkit-mask-image: linear-gradient(#000 calc(100% - 26px), transparent); mask-image: linear-gradient(#000 calc(100% - 26px), transparent); }
.leer-rollbar::-webkit-scrollbar { display: none; }
.leer-rollbar > * { flex: none; }
.cart-empty .cart-continue { width: 100%; flex: none; margin-top: 2px; }
/* Der Bügel richtet sich nach der Höhe des Schirms: So passt am Handy alles samt Vorschlägen ohne Scrollen. */
.leer-buehne { width: min(100%, 250px, 27dvh); margin: 0 auto 4px; color: var(--paper); }
.leer-svg { display: block; width: 100%; height: auto; overflow: visible; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.leer-stange path:first-child { stroke-width: 2.4; opacity: .55; }
.leer-stange path:last-child { opacity: .55; }
.leer-buegel { transform-box: view-box; transform-origin: 120px 22px; animation: leer-pendeln 5.5s ease-in-out infinite alternate; }
.leer-schild { transform-box: view-box; transform-origin: 168px 115px; animation: leer-schild 3.8s ease-in-out infinite alternate; }
.leer-schild-form { fill: color-mix(in srgb, currentColor 7%, transparent); }
.leer-schild circle { fill: var(--black); }
.leer-schild-text { fill: currentColor; stroke: none; font: 700 7.5px var(--mono); letter-spacing: .12em; text-anchor: middle; }
.leer-schild-klein { fill: var(--muted); stroke: none; font: 6.5px var(--mono); text-anchor: middle; }
.cart-empty.is-einschwingen .leer-buegel { animation: leer-einschwingen 2.4s cubic-bezier(.3,.6,.3,1) both, leer-pendeln 5.5s 2.4s ease-in-out infinite alternate; }
.cart-empty.is-einschwingen .leer-schild { animation: leer-schild-ein 2.7s .08s cubic-bezier(.3,.6,.3,1) both, leer-schild 3.8s 2.8s ease-in-out infinite alternate; }
@keyframes leer-einschwingen { 0% { transform: rotate(17deg); } 17% { transform: rotate(-11deg); } 35% { transform: rotate(7deg); } 53% { transform: rotate(-4deg); } 71% { transform: rotate(2.2deg); } 87% { transform: rotate(-1.8deg); } 100% { transform: rotate(-1.4deg); } }
@keyframes leer-pendeln { from { transform: rotate(-1.4deg); } to { transform: rotate(1.4deg); } }
@keyframes leer-schild-ein { 0% { transform: rotate(-24deg); } 20% { transform: rotate(16deg); } 40% { transform: rotate(-9deg); } 60% { transform: rotate(5deg); } 80% { transform: rotate(-2deg); } 100% { transform: rotate(-3deg); } }
@keyframes leer-schild { from { transform: rotate(-3deg); } to { transform: rotate(3deg); } }
.leer-text h3 { margin: 6px 0 8px; font: 900 clamp(26px, 2.3vw, 32px)/1 var(--display); letter-spacing: -.045em; text-transform: uppercase; }
.leer-text p { max-width: 31ch; margin: 0 auto 26px; color: var(--muted); font: 10px/1.65 var(--mono); }
.leer-vorschlaege { width: 100%; margin: 0; text-align: left; }
.leer-zeile { display: flex; align-items: center; gap: 10px; margin: 0 0 10px; color: var(--muted); font: 8px/1 var(--mono); letter-spacing: .2em; }
.leer-zeile i { flex: 1; height: 1px; background: var(--line); }
.leer-liste { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.leer-stueck { display: grid; grid-template-columns: minmax(0, 1fr) auto; border: 1px solid var(--line); background: color-mix(in srgb, var(--paper) 3%, transparent); transition: border-color .2s, background-color .2s; }
.leer-stueck:hover { border-color: color-mix(in srgb, var(--paper) 42%, transparent); background: color-mix(in srgb, var(--paper) 6%, transparent); }
.leer-oeffnen { display: grid; grid-template-columns: 54px minmax(0, 1fr) auto; align-items: center; gap: 12px; min-width: 0; padding: 8px 12px 8px 8px; border: 0; color: inherit; background: none; text-align: left; cursor: pointer; }
.leer-bild { display: block; width: 54px; height: 54px; overflow: hidden; background: #f3f2ee; }
.leer-bild img { display: block; width: 100%; height: 100%; object-fit: cover; }
.leer-bild .leer-logo { padding: 9px; object-fit: contain; background: #141414; }
.leer-name { display: grid; gap: 5px; min-width: 0; }
.leer-name b { overflow: hidden; font: 500 12px/1.25 var(--sans); white-space: nowrap; text-overflow: ellipsis; }
.leer-name small { color: var(--muted); font: 8px/1.2 var(--mono); letter-spacing: .08em; }
.leer-preis { font: 10px var(--mono); white-space: nowrap; }
.leer-rein { display: grid; width: 48px; place-items: center; padding: 0; border: 0; border-left: 1px solid var(--line); color: var(--paper); background: none; cursor: pointer; transition: background-color .2s, color .2s; }
.leer-rein:hover, .leer-rein:focus-visible { color: var(--black); background: var(--paper); }
.leer-rein svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; }
.leer-oeffnen:focus-visible, .leer-rein:focus-visible { outline: 2px solid var(--paper); outline-offset: -2px; }
.cart-empty.is-einschwingen :is(.leer-text, .leer-vorschlaege .leer-zeile, .cart-continue) { animation: leer-auftauchen .5s .25s cubic-bezier(.2,.8,.25,1) both; }
.cart-empty.is-einschwingen .leer-stueck { animation: leer-auftauchen .5s cubic-bezier(.2,.8,.25,1) both; animation-delay: calc(.38s + var(--i, 0) * .08s); }
@keyframes leer-auftauchen { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
:root[data-theme="light"] .cart-drawer .leer-bild .leer-logo { background: #e6e4de; }
@media (max-height: 760px) {
  .leer-rollbar { padding-top: 12px; }
  .leer-text p { margin-bottom: 16px; }
}

/* Stück fliegt in die Tasche (06.11.2026, store.js addFromEmpty). Alles hängt an einer Uhr: 0 s Haken und Abgang, 0,64 s Landung. */
.tasche-abgang { position: absolute; z-index: 2; pointer-events: none; }
.tasche-abgang .leer-buehne { animation: tasche-buegel-weg .42s cubic-bezier(.5,0,.75,.45) both; }
.tasche-abgang :is(.leer-text, .leer-zeile, .cart-continue) { animation: tasche-blass .24s ease-in both; }
.tasche-abgang .leer-stueck { animation: tasche-sinkt .28s ease-in calc(.03s + var(--i, 0) * .04s) both; }
.tasche-abgang .leer-stueck.is-rein { animation: tasche-blass .2s ease-in .15s both; }
.tasche-abgang .is-rein .leer-bild { background: none; }
.tasche-abgang .is-rein .leer-bild img { visibility: hidden; }
.tasche-abgang .is-rein .leer-rein { color: var(--black); background: var(--paper); }
.tasche-abgang .is-rein .leer-rein path { stroke-width: 2.2; stroke-linejoin: round; stroke-dasharray: 1; animation: tasche-haken .2s ease-out both; }
.tasche-flug { position: absolute; z-index: 3; display: block; pointer-events: none; will-change: transform; }
.tasche-flug > span { display: block; width: 100%; height: 100%; will-change: transform; }
.tasche-flug .leer-bild { width: 100%; height: 100%; }
.cart-line.is-neu { position: relative; animation: tasche-setzt .34s ease-out .62s; }
.cart-line.is-neu .cart-thumb { animation: tasche-bild-da .3s cubic-bezier(.3,1.6,.5,1) .63s both; }
.cart-line.is-neu :is(.cart-line-info, .cart-line-price) { animation: tasche-zeile .42s cubic-bezier(.2,.8,.25,1) .44s both; }
.cart-line.is-neu::after { position: absolute; inset: 0; background: linear-gradient(100deg, transparent 38%, color-mix(in srgb, var(--paper) 20%, transparent) 50%, transparent 62%) no-repeat 130% 0 / 260% 100%; content: ""; pointer-events: none; animation: tasche-glanz .7s ease-out .66s both; }
.cart-summary.is-neu { animation: tasche-summe .6s cubic-bezier(.16,1,.3,1) .36s both; }
.cart-title-count.is-neu { display: inline-block; transform-origin: 0 60%; animation: tasche-zahl .46s cubic-bezier(.3,1.7,.5,1) .6s; }
@keyframes tasche-buegel-weg { 0% { transform: none; opacity: 1; } 22% { transform: translateY(7px) rotate(-6deg); opacity: 1; } 100% { transform: translateY(-105%) rotate(11deg); opacity: 0; } }
@keyframes tasche-blass { to { opacity: 0; } }
@keyframes tasche-sinkt { to { opacity: 0; transform: translateY(14px); } }
@keyframes tasche-haken { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes tasche-setzt { 0%, 100% { transform: none; } 35% { transform: translateY(3px); } }
@keyframes tasche-bild-da { 0% { opacity: 0; transform: scale(1.1); } 1% { opacity: 1; transform: scale(1.1); } 100% { opacity: 1; transform: none; } }
@keyframes tasche-zeile { from { opacity: 0; transform: translateX(16px); } to { opacity: 1; transform: none; } }
@keyframes tasche-glanz { from { background-position: 130% 0; } to { background-position: -30% 0; } }
@keyframes tasche-summe { from { opacity: 0; transform: translateY(48px); } to { opacity: 1; transform: none; } }
@keyframes tasche-zahl { from { transform: scale(1.3); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .leer-buegel, .leer-schild, .cart-empty.is-einschwingen .leer-buegel, .cart-empty.is-einschwingen .leer-schild,
  .cart-empty.is-einschwingen :is(.leer-text, .leer-vorschlaege .leer-zeile, .cart-continue, .leer-stueck) { animation: none; }
}


/* Kein „SCHNELLANSICHT“-Knopf mehr auf den Karten (08.10.2026, Michas Wunsch): Klick auf Bild oder Titel öffnet die
   Detailansicht ohnehin, der eingeblendete Knopf war doppelt. Markup bleibt (server.mjs), nur ausgeblendet. */
.product-card .quick-view { display: none; }

/* Merkliste bewegt sich weich (06.11.2026, store.js savedGlide). Beim Gleiten keine Rollbalken, und was geht, liegt als Kopie frei im Fenster. */
.saved-dialog.is-gleitet { overflow: hidden; }
.saved-weg { position: absolute; z-index: 1; margin: 0; pointer-events: none; }
