<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>USB Hub on SMotographers</title>
    <link>https://smotographers.com/de/tags/usb-hub/</link>
    <description>Recent content in USB Hub on SMotographers</description>
    <generator>Hugo</generator>
    <language>de-ch</language>
    <lastBuildDate>Mon, 08 Sep 2025 05:00:00 +0000</lastBuildDate>
    <atom:link href="https://smotographers.com/de/tags/usb-hub/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Ulanzi D200H USB Hub / Studio Deck – Produktvorstellung &amp; Unboxing</title>
      <link>https://smotographers.com/de/blog/06-sponsored-content/ulanzi-d200h/</link>
      <pubDate>Mon, 08 Sep 2025 05:00:00 +0000</pubDate>
      <guid>https://smotographers.com/de/blog/06-sponsored-content/ulanzi-d200h/</guid>
      <description>&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;&#xA;      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen=&#34;allowfullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube.com/embed/BidgQ8w7tWg?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;  &#xA;  &#xA;    &#xA;    &#xA;    &#xA;      &#xA;      &#xA;        &#xA;        &#xA;          &#xA;        &#xA;      &#xA;    &#xA;  &#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;price-grabber-widget&#34; id=&#34;price-grabber-1780344310732833073&#34;&gt;&#xA;  &lt;div class=&#34;price-grabber-header&#34; style=&#34;background: #23272f; color: #fff;&#34;&gt;&#xA;    &lt;h3 class=&#34;price-grabber-title&#34;&gt;Ulanzi D200H&lt;/h3&gt;&#xA;    &lt;div class=&#34;price-grabber-status&#34;&gt;&#xA;      &lt;span class=&#34;product-count&#34;&gt;1 Produkt&lt;/span&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&#xA;  &#xA;    &#xA;    &#xA;    &lt;div class=&#34;single-product-container&#34;&gt;&#xA;      &lt;div class=&#34;product-card single&#34;&gt;&#xA;        &lt;div class=&#34;product-card-content&#34;&gt;&#xA;          &lt;div class=&#34;product-image-container&#34;&gt;&#xA;            &#xA;              &lt;img class=&#34;product-image&#34; src=&#34;https://www.ulanzi.com/cdn/shop/files/1_1_11zon_e678237d-5cdf-4cec-896d-95a4067e58be.webp?v=1755757328&amp;amp;width=800&#34; alt=&#34;Ulanzi D200H Deck Dock&#34; loading=&#34;lazy&#34; /&gt;&#xA;            &#xA;          &lt;/div&gt;&#xA;          &#xA;          &lt;div class=&#34;price-container&#34;&gt;&#xA;            &lt;span class=&#34;current-price&#34; style=&#34;font-size:1.3rem;font-weight:700;&#34;&gt;99,99 EUR&lt;/span&gt;&#xA;            &lt;span class=&#34;price-label&#34; style=&#34;font-size:0.8rem;&#34;&gt;Aktueller Preis&lt;/span&gt;&#xA;          &lt;/div&gt;&#xA;          &#xA;          &lt;div class=&#34;product-details&#34;&gt;&#xA;            &lt;h4 class=&#34;product-name&#34; style=&#34;display:none;&#34;&gt;Ulanzi D200H Deck Dock&lt;/h4&gt;&#xA;            &#xA;            &#xA;            &#xA;            &lt;div class=&#34;action-buttons&#34;&gt;&#xA;              &lt;a href=&#34;https://www.ulanzi.de/products/d200h-deck-dock?variant=41845571321911#&amp;amp;aff=2632&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34; class=&#34;btn-primary compact-btn&#34;&gt;&#xA;                &lt;i class=&#34;fas fa-external-link-alt&#34;&gt;&lt;/i&gt;&#xA;                Zum Produkt&#xA;              &lt;/a&gt;&#xA;              &#xA;                &lt;span class=&#34;affiliate-disclaimer&#34; style=&#34;display:block;margin-top:0.5rem;font-size:0.85rem;color:#10b981;background:#ecfdf5;padding:0.4rem 0.8rem;border-radius:6px;border-left:3px solid #10b981;&#34;&gt;&#xA;                  &lt;i class=&#34;fas fa-handshake&#34;&gt;&lt;/i&gt; Affiliate-Link - Unterstützt unsere Arbeit&#xA;                &lt;/span&gt;&#xA;              &#xA;            &lt;/div&gt;&#xA;            &#xA;            &lt;div class=&#34;last-updated&#34;&gt;&#xA;              &lt;small&gt;&lt;i class=&#34;fas fa-clock&#34;&gt;&lt;/i&gt; Zuletzt aktualisiert: 20.05.2026 11:40&lt;/small&gt;&#xA;            &lt;/div&gt;&#xA;          &lt;/div&gt;&#xA;        &lt;/div&gt;&#xA;      &lt;/div&gt;&#xA;    &lt;/div&gt;&#xA;  &#xA;&lt;/div&gt;&#xA;&#xA;&lt;style&gt;&#xA; &#xA;.price-grabber-widget {&#xA;  margin: 0 0 2rem 0;&#xA;  font-family: inherit;&#xA;  background: #ffffff;&#xA;  border-radius: 12px;&#xA;  box-shadow: 0 2px 12px rgba(0,0,0,0.06);&#xA;  border: 1px solid #e5e7eb;&#xA;  overflow: hidden;&#xA;  transition: background-color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.price-grabber-widget {&#xA;  background: #f8fafc;  &#xA;  border-color: #e2e8f0;  &#xA;  box-shadow: 0 2px 12px rgba(0,0,0,0.06);&#xA;  color: #1f2937;  &#xA;}&#xA;&#xA; &#xA;.dark .price-grabber-widget {&#xA;  background: #1f2937;&#xA;  border-color: #374151;&#xA;  box-shadow: 0 2px 12px rgba(0,0,0,0.3);&#xA;  color: #f9fafb;&#xA;}&#xA;&#xA;.price-grabber-header {&#xA;  background: #3b82f6;  &#xA;  color: #fff;&#xA;  padding: 1.2rem 1.5rem;&#xA;  display: flex;&#xA;  justify-content: space-between;&#xA;  align-items: center;&#xA;}&#xA;&#xA; &#xA;.dark .price-grabber-header {&#xA;  background: #111827;&#xA;  border-bottom: 1px solid #374151;&#xA;}&#xA;&#xA;.price-grabber-title {&#xA;  margin: 0;&#xA;  font-size: 1.3rem;&#xA;  font-weight: 700;&#xA;  color: #fff;&#xA;}&#xA;&#xA;.product-count {&#xA;  background: rgba(255,255,255,0.08);&#xA;  padding: 0.4rem 0.9rem;&#xA;  border-radius: 16px;&#xA;  font-size: 0.85rem;&#xA;  font-weight: 500;&#xA;  color: #fff;&#xA;}&#xA;&#xA; &#xA;.product-carousel-container {&#xA;  position: relative;&#xA;  overflow: hidden;&#xA;  background: #ffffff;  &#xA;  transition: background-color 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .product-carousel-container {&#xA;  background: #1f2937;&#xA;}&#xA;&#xA;.product-carousel {&#xA;  display: flex;&#xA;  transition: transform 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);&#xA;  will-change: transform;&#xA;}&#xA;&#xA;.product-card {&#xA;  min-width: 100%;&#xA;  opacity: 0;&#xA;  transform: translateX(30px);&#xA;  transition: all 0.6s cubic-bezier(0.25, 0.8, 0.25, 1);&#xA;  background: rgb(255, 255, 255);  &#xA;  border-radius: 0;&#xA;  color: #1f2937;  &#xA;}&#xA;&#xA; &#xA;.dark .product-card {&#xA;  background: #1f2937;&#xA;  color: #f9fafb;&#xA;}&#xA;&#xA;.product-card.active {&#xA;  opacity: 1;&#xA;  transform: translateX(0);&#xA;}&#xA;&#xA;.product-card-content {&#xA;  display: grid;&#xA;  grid-template-columns: 320px 1fr;&#xA;  gap: 2.5rem;&#xA;  padding: 2.5rem;&#xA;  min-height: 450px;&#xA;  align-items: start;&#xA;}&#xA;&#xA;.product-card-content .product-image-container {&#xA;  grid-row: 1;&#xA;}&#xA;&#xA;.product-card-content .price-container {&#xA;  grid-row: 2;&#xA;  margin-top: -1rem;&#xA;}&#xA;&#xA;.product-card-content .product-details {&#xA;  grid-column: 2;&#xA;  grid-row: 1 / span 2;&#xA;}&#xA;&#xA;@media (max-width: 968px) {&#xA;  .product-card-content {&#xA;    grid-template-columns: 1fr;&#xA;    gap: 2rem;&#xA;    text-align: center;&#xA;    padding: 2rem;&#xA;  }&#xA;  &#xA;  .product-card-content .product-image-container,&#xA;  .product-card-content .price-container,&#xA;  .product-card-content .product-details {&#xA;    grid-column: 1;&#xA;    grid-row: auto;&#xA;  }&#xA;  &#xA;  .product-image-container {&#xA;    max-width: 280px;&#xA;    margin: 0 auto;&#xA;  }&#xA;  &#xA;  .product-card-content .price-container {&#xA;    margin-top: 0;&#xA;  }&#xA;}&#xA;&#xA;@media (max-width: 640px) {&#xA;  .product-card-content {&#xA;    padding: 1.5rem;&#xA;    gap: 1.5rem;&#xA;  }&#xA;}&#xA;&#xA; &#xA;.single-product-container .product-card {&#xA;  opacity: 1;&#xA;  transform: none;&#xA;}&#xA;&#xA; &#xA;.product-image-container {&#xA;  display: flex;&#xA;  justify-content: center;&#xA;  align-items: center;&#xA;  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);  &#xA;  border-radius: 16px;&#xA;  padding: 1.5rem;&#xA;  height: 300px;&#xA;  position: relative;&#xA;  overflow: hidden;&#xA;  border: 1px solid #f1f5f9;  &#xA;  transition: background 0.3s ease, border-color 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .product-image-container {&#xA;  background: linear-gradient(135deg, #1f2937 0%, #374151 100%);&#xA;  border-color: #374151;&#xA;}&#xA;&#xA;.product-image {&#xA;  width: 100%;&#xA;  height: 100%;&#xA;  object-fit: contain;&#xA;  border-radius: 12px;&#xA;  transition: transform 0.3s ease;&#xA;  position: relative;&#xA;  z-index: 1;&#xA;}&#xA;&#xA;.product-image:hover {&#xA;  transform: scale(1.05);&#xA;}&#xA;&#xA;.product-image-placeholder {&#xA;  display: flex;&#xA;  flex-direction: column;&#xA;  align-items: center;&#xA;  justify-content: center;&#xA;  color: #6b7280;  &#xA;  font-size: 0.9rem;&#xA;  height: 100%;&#xA;  font-weight: 500;&#xA;  transition: color 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .product-image-placeholder {&#xA;  color: #9ca3af;&#xA;}&#xA;&#xA;.product-image-placeholder i {&#xA;  font-size: 3.5rem;&#xA;  margin-bottom: 1rem;&#xA;  opacity: 0.6;&#xA;  color: #9ca3af;  &#xA;  transition: color 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .product-image-placeholder i {&#xA;  color: #6b7280;&#xA;}&#xA;&#xA; &#xA;.carousel-controls {&#xA;  display: flex;&#xA;  align-items: center;&#xA;  justify-content: center;&#xA;  padding: 0.75rem 1.5rem 1rem;  &#xA;  background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);  &#xA;  gap: 1rem;  &#xA;  border-top: 1px solid #f1f5f9;  &#xA;  transition: background 0.3s ease, border-color 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .carousel-controls {&#xA;  background: #1f2937;&#xA;  border-top-color: #374151;&#xA;}&#xA;&#xA;.carousel-btn {&#xA;  background: white;&#xA;  border: 2px solid #e5e7eb;  &#xA;  border-radius: 50%;&#xA;  width: 40px;  &#xA;  height: 40px;  &#xA;  display: flex;&#xA;  align-items: center;&#xA;  justify-content: center;&#xA;  cursor: pointer;&#xA;  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);&#xA;  color: #4b5563;  &#xA;  font-size: 1rem;  &#xA;  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);&#xA;}&#xA;&#xA; &#xA;.dark .carousel-btn {&#xA;  background: #374151;&#xA;  border-color: #4b5563;&#xA;  color: #d1d5db;&#xA;  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);&#xA;}&#xA;&#xA;.carousel-btn:hover {&#xA;  background: #6b7280;&#xA;  color: white;&#xA;  border-color: #6b7280;&#xA;  transform: scale(1.15);&#xA;  box-shadow: 0 4px 16px rgba(107, 114, 128, 0.3);&#xA;}&#xA;&#xA;.carousel-btn:active {&#xA;  transform: scale(1.05);&#xA;}&#xA;&#xA;.carousel-btn:disabled {&#xA;  opacity: 0.4;&#xA;  cursor: not-allowed;&#xA;  transform: none;&#xA;  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);&#xA;}&#xA;&#xA; &#xA;.dark .carousel-btn:disabled {&#xA;  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);&#xA;}&#xA;&#xA;.carousel-indicators {&#xA;  display: flex;&#xA;  gap: 0.5rem;  &#xA;  align-items: center;&#xA;}&#xA;&#xA;.indicator {&#xA;  width: 10px;  &#xA;  height: 10px;  &#xA;  border-radius: 50%;&#xA;  border: none;&#xA;  background: #cbd5e1;  &#xA;  cursor: pointer;&#xA;  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);&#xA;  position: relative;&#xA;}&#xA;&#xA; &#xA;.dark .indicator {&#xA;  background: #4b5563;&#xA;}&#xA;&#xA;.indicator:before {&#xA;  content: &#39;&#39;;&#xA;  position: absolute;&#xA;  top: 50%;&#xA;  left: 50%;&#xA;  width: 4px;  &#xA;  height: 4px;  &#xA;  background: white;&#xA;  border-radius: 50%;&#xA;  transform: translate(-50%, -50%);&#xA;  opacity: 0;&#xA;  transition: opacity 0.2s ease;&#xA;}&#xA;&#xA;.indicator.active {&#xA;  background: #6b7280;&#xA;  transform: scale(1.3);&#xA;}&#xA;&#xA;.indicator.active:before {&#xA;  opacity: 1;&#xA;}&#xA;&#xA;.indicator:hover:not(.active) {&#xA;  background: #94a3b8;  &#xA;  transform: scale(1.1);&#xA;}&#xA;&#xA; &#xA;.dark .indicator:hover:not(.active) {&#xA;  background: #6b7280;&#xA;}&#xA;&#xA; &#xA;.product-details {&#xA;  display: flex;&#xA;  flex-direction: column;&#xA;  gap: 1.25rem;&#xA;  justify-content: space-between;&#xA;}&#xA;&#xA;.product-name {&#xA;  font-size: 1.5rem;&#xA;  font-weight: 700;&#xA;  color: #1f2937;  &#xA;  margin: 0;&#xA;  line-height: 1.3;&#xA;  transition: color 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .product-name {&#xA;  color: #f9fafb;&#xA;}&#xA;&#xA;.price-container {&#xA;  display: flex;&#xA;  flex-direction: column;&#xA;  gap: 0.5rem;&#xA;  padding: 1rem 1.25rem;&#xA;  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);&#xA;  border-radius: 12px;&#xA;  border: 1px solid #cbd5e1;&#xA;  transition: background 0.3s ease, border-color 0.3s ease;&#xA;  text-align: center;&#xA;}&#xA;&#xA; &#xA;.dark .price-container {&#xA;  background: linear-gradient(135deg, #064e3b 0%, #065f46 100%);&#xA;  border-color: #047857;&#xA;}&#xA;&#xA;.current-price {&#xA;  font-size: 2.75rem;&#xA;  font-weight: 900;&#xA;  color: #007c1f;  &#xA;  line-height: 1;&#xA;  text-shadow: 0 2px 4px rgba(31, 41, 55, 0.1);&#xA;  transition: color 0.3s ease, text-shadow 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .current-price {&#xA;  color: #10b981;&#xA;  text-shadow: 0 2px 4px rgba(16, 185, 129, 0.3);&#xA;}&#xA;&#xA;.price-label {&#xA;  font-size: 0.9rem;&#xA;  color: #4b5563;&#xA;  font-weight: 600;&#xA;  text-transform: uppercase;&#xA;  letter-spacing: 0.05em;&#xA;  transition: color 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .price-label {&#xA;  color: #9ca3af;&#xA;}&#xA;&#xA; &#xA;.action-buttons {&#xA;  display: flex;&#xA;  gap: 0.5rem;&#xA;  margin-top: 0.5rem;&#xA;}&#xA;&#xA;.btn-primary, .btn-secondary {&#xA;  padding: 1.25rem 2rem;&#xA;  border-radius: 12px;&#xA;  text-decoration: none;&#xA;  font-weight: 700;&#xA;  display: inline-flex;&#xA;  align-items: center;&#xA;  gap: 0.875rem;&#xA;  transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);&#xA;  border: none;&#xA;  cursor: pointer;&#xA;  font-size: 0.9rem;&#xA;  flex: 1;&#xA;  justify-content: center;&#xA;  min-width: 160px;&#xA;  text-transform: uppercase;&#xA;  letter-spacing: 0.05em;&#xA;}&#xA;&#xA;.btn-primary.compact-btn, .btn-secondary.compact-btn {&#xA;  padding: 0.5rem 1rem;&#xA;  border-radius: 8px;&#xA;  font-size: 0.85rem;&#xA;  min-width: 90px;&#xA;  line-height: 1.1;&#xA;}&#xA;&#xA;.btn-primary {&#xA;  background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 100%);&#xA;  color: white;&#xA;  box-shadow: 0 6px 20px rgba(96, 165, 250, 0.4);&#xA;}&#xA;&#xA; &#xA;.btn-primary {&#xA;  background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 100%);&#xA;  color: white;&#xA;  box-shadow: 0 6px 20px rgba(96, 165, 250, 0.4);&#xA;}&#xA;&#xA;.btn-primary:hover {&#xA;  background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);&#xA;  transform: translateY(-3px);&#xA;  box-shadow: 0 10px 30px rgba(59, 130, 246, 0.5);&#xA;}&#xA;&#xA; &#xA;.dark .btn-primary {&#xA;  background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);&#xA;  color: white;&#xA;  box-shadow: 0 6px 20px rgba(59, 130, 246, 0.4);&#xA;}&#xA;&#xA;.dark .btn-primary:hover {&#xA;  background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%);&#xA;  transform: translateY(-3px);&#xA;  box-shadow: 0 10px 30px rgba(37, 99, 235, 0.5);&#xA;}&#xA;&#xA;.btn-secondary {&#xA;  background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);&#xA;  color: #374151;  &#xA;  border: 2px solid #d1d5db;&#xA;}&#xA;&#xA;.btn-secondary:hover {&#xA;  background: linear-gradient(135deg, #e2e8f0 0%, #cbd5e1 100%);&#xA;  transform: translateY(-2px);&#xA;  border-color: #9ca3af;&#xA;}&#xA;&#xA; &#xA;.dark .btn-secondary {&#xA;  background: linear-gradient(135deg, #4b5563 0%, #6b7280 100%);&#xA;  color: #f9fafb;&#xA;  border-color: #6b7280;&#xA;}&#xA;&#xA;.dark .btn-secondary:hover {&#xA;  background: linear-gradient(135deg, #6b7280 0%, #9ca3af 100%);&#xA;  border-color: #9ca3af;&#xA;}&#xA;&#xA; &#xA;.last-updated {&#xA;  color: #4b5563;&#xA;  font-size: 0.8rem;&#xA;  display: flex;&#xA;  align-items: center;&#xA;  gap: 0.5rem;&#xA;  padding: 0.75rem 1rem;&#xA;  background: #f8fafc;&#xA;  border-radius: 8px;&#xA;  font-weight: 500;&#xA;  transition: color 0.3s ease, background-color 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .last-updated {&#xA;  color: #9ca3af;&#xA;  background: #374151;&#xA;}&#xA;&#xA; &#xA;.no-products-container {&#xA;  padding: 3rem 2rem;&#xA;  text-align: center;&#xA;}&#xA;&#xA;.error-message {&#xA;  color: #ef4444;&#xA;  background: #fef2f2;&#xA;  border: 1px solid #fecaca;&#xA;  border-radius: 12px;&#xA;  padding: 2rem;&#xA;  font-size: 0.875rem;&#xA;  transition: background-color 0.3s ease, border-color 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .error-message {&#xA;  background: #7f1d1d;&#xA;  border-color: #991b1b;&#xA;  color: #fecaca;&#xA;}&#xA;&#xA;.error-message i {&#xA;  font-size: 2rem;&#xA;  margin-bottom: 1rem;&#xA;  display: block;&#xA;}&#xA;&#xA; &#xA;.product-features {&#xA;  margin: 0;&#xA;}&#xA;&#xA;.features-title {&#xA;  display: flex;&#xA;  align-items: center;&#xA;  gap: 0.5rem;&#xA;  font-size: 1.1rem;&#xA;  font-weight: 600;&#xA;  color: #1f2937;  &#xA;  margin-bottom: 0.5rem;&#xA;  transition: color 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .features-title {&#xA;  color: #f3f4f6;&#xA;}&#xA;&#xA;.features-list {&#xA;  list-style: none;&#xA;  padding: 0;&#xA;  margin: 0;&#xA;  display: grid;&#xA;  gap: 0.125rem;  &#xA;}&#xA;&#xA;.features-list.enhanced {&#xA;  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));&#xA;  gap: 0.125rem;  &#xA;}&#xA;&#xA;.features-list li {&#xA;  padding: 0.25rem 0.4rem;  &#xA;  background: #ffffff;  &#xA;  border-radius: 4px;  &#xA;  font-size: 0.85rem;&#xA;  color: #1f2937;  &#xA;  border: 1px solid #e5e7eb;  &#xA;  border-left: 3px solid #6b7280;  &#xA;  transition: background-color 0.3s ease, color 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .features-list li {&#xA;  background: #4b5563;&#xA;  color: #e5e7eb;&#xA;  border-color: #6b7280;&#xA;  border-left-color: #9ca3af;  &#xA;}&#xA;&#xA; &#xA;.affiliate-disclaimer {&#xA;  background: #ecfdf5 !important;  &#xA;  color: #047857 !important;  &#xA;  border-left: 3px solid #10b981 !important;  &#xA;  transition: background-color 0.3s ease, color 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .affiliate-disclaimer {&#xA;  background: #064e3b !important;&#xA;  color: #6ee7b7 !important;&#xA;  border-left-color: #10b981 !important;&#xA;}&#xA;&#xA; &#xA;.no-affiliate-disclaimer {&#xA;  background: #f1f5f9 !important;  &#xA;  color: #475569 !important;  &#xA;  transition: background-color 0.3s ease, color 0.3s ease;&#xA;}&#xA;&#xA; &#xA;.dark .no-affiliate-disclaimer {&#xA;  background: #374151 !important;&#xA;  color: #d1d5db !important;&#xA;}&#xA;&#xA; &#xA;@media (max-width: 640px) {&#xA;  .price-grabber-header {&#xA;    padding: 1rem;&#xA;    flex-direction: column;&#xA;    gap: 0.5rem;&#xA;    text-align: center;&#xA;  }&#xA;  &#xA;  .price-grabber-title {&#xA;    font-size: 1.25rem;&#xA;  }&#xA;  &#xA;  .product-card-content {&#xA;    padding: 1rem;&#xA;  }&#xA;  &#xA;  .current-price {&#xA;    font-size: 2rem;&#xA;  }&#xA;  &#xA;  .action-buttons {&#xA;    flex-direction: column;&#xA;  }&#xA;  &#xA;  .btn-primary, .btn-secondary {&#xA;    flex: none;&#xA;  }&#xA;  &#xA;  .features-list.enhanced {&#xA;    grid-template-columns: 1fr;&#xA;  }&#xA;}&#xA;&#xA;&#xA;&lt;/style&gt;&#xA;&#xA;&lt;script&gt;&#xA;&#xA;(function() {&#xA;  function checkThemeCompatibility() {&#xA;    &#xA;    const isDark = document.documentElement.classList.contains(&#39;dark&#39;);&#xA;    console.log(&#39;Theme state detected:&#39;, isDark ? &#39;dark&#39; : &#39;light&#39;);&#xA;    &#xA;    &#xA;    const widgets = document.querySelectorAll(&#39;.price-grabber-widget&#39;);&#xA;    widgets.forEach(widget =&gt; {&#xA;      &#xA;      widget.style.opacity = &#39;0.99&#39;;&#xA;      setTimeout(() =&gt; {&#xA;        widget.style.opacity = &#39;&#39;;&#xA;      }, 10);&#xA;    });&#xA;  }&#xA;  &#xA;  &#xA;  document.addEventListener(&#39;DOMContentLoaded&#39;, checkThemeCompatibility);&#xA;  &#xA;  &#xA;  const observer = new MutationObserver((mutations) =&gt; {&#xA;    mutations.forEach((mutation) =&gt; {&#xA;      if (mutation.type === &#39;attributes&#39; &amp;&amp; mutation.attributeName === &#39;class&#39;) {&#xA;        checkThemeCompatibility();&#xA;      }&#xA;    });&#xA;  });&#xA;  &#xA;  &#xA;  observer.observe(document.documentElement, { &#xA;    attributes: true, &#xA;    attributeFilter: [&#39;class&#39;] &#xA;  });&#xA;})();&#xA;&#xA;&#xA;window.moveCarousel = function(widgetId, direction) {&#xA;  const carousel = document.getElementById(`carousel-${widgetId}`);&#xA;  const cards = carousel.querySelectorAll(&#39;.product-card&#39;);&#xA;  const indicators = carousel.parentElement.querySelectorAll(&#39;.indicator&#39;);&#xA;  &#xA;  let currentIndex = 0;&#xA;  cards.forEach((card, index) =&gt; {&#xA;    if (card.classList.contains(&#39;active&#39;)) {&#xA;      currentIndex = index;&#xA;    }&#xA;  });&#xA;  &#xA;  let newIndex = currentIndex + direction;&#xA;  if (newIndex &lt; 0) newIndex = cards.length - 1;&#xA;  if (newIndex &gt;= cards.length) newIndex = 0;&#xA;  &#xA;  &#xA;  cards[currentIndex].classList.remove(&#39;active&#39;);&#xA;  cards[newIndex].classList.add(&#39;active&#39;);&#xA;  &#xA;  &#xA;  indicators[currentIndex].classList.remove(&#39;active&#39;);&#xA;  indicators[newIndex].classList.add(&#39;active&#39;);&#xA;  &#xA;  &#xA;  carousel.style.transform = `translateX(-${newIndex * 100}%)`;&#xA;};&#xA;&#xA;window.goToSlide = function(widgetId, targetIndex) {&#xA;  const carousel = document.getElementById(`carousel-${widgetId}`);&#xA;  const cards = carousel.querySelectorAll(&#39;.product-card&#39;);&#xA;  const indicators = carousel.parentElement.querySelectorAll(&#39;.indicator&#39;);&#xA;  &#xA;  let currentIndex = 0;&#xA;  cards.forEach((card, index) =&gt; {&#xA;    if (card.classList.contains(&#39;active&#39;)) {&#xA;      currentIndex = index;&#xA;    }&#xA;  });&#xA;  &#xA;  &#xA;  cards[currentIndex].classList.remove(&#39;active&#39;);&#xA;  cards[targetIndex].classList.add(&#39;active&#39;);&#xA;  &#xA;  &#xA;  indicators[currentIndex].classList.remove(&#39;active&#39;);&#xA;  indicators[targetIndex].classList.add(&#39;active&#39;);&#xA;  &#xA;  &#xA;  carousel.style.transform = `translateX(-${targetIndex * 100}%)`;&#xA;};&#xA;&#xA;&#xA;window.startCarouselAutoRotation = function(widgetId, interval = 8000) {&#xA;  const carousel = document.getElementById(`carousel-${widgetId}`);&#xA;  if (!carousel) return;&#xA;  &#xA;  const cards = carousel.querySelectorAll(&#39;.product-card&#39;);&#xA;  if (cards.length &lt;= 1) return;&#xA;  &#xA;  setInterval(() =&gt; {&#xA;    window.moveCarousel(widgetId, 1);&#xA;  }, interval);&#xA;};&#xA;&#xA;(function() {&#xA;  &#xA;  const CORS_PROXIES = [&#xA;    &#39;https://api.allorigins.win/raw?url=&#39;,&#xA;    &#39;https://corsproxy.io/?&#39;,&#xA;    &#39;https://cors-anywhere.herokuapp.com/&#39;,&#xA;    &#39;https://api.codetabs.com/v1/proxy?quest=&#39;&#xA;  ];&#xA;  &#xA;  &#xA;  class ProductExtractor {&#xA;    constructor(url) {&#xA;      this.url = url;&#xA;      this.domain = new URL(url).hostname.toLowerCase();&#xA;      this.currentProxyIndex = 0;&#xA;    }&#xA;    &#xA;    async extractData() {&#xA;      &#xA;      for (let i = 0; i &lt; CORS_PROXIES.length; i++) {&#xA;        try {&#xA;          const proxyUrl = CORS_PROXIES[i] + encodeURIComponent(this.url);&#xA;          const response = await fetch(proxyUrl, {&#xA;            headers: {&#xA;              &#39;User-Agent&#39;: &#39;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36&#39;&#xA;            }&#xA;          });&#xA;          &#xA;          if (!response.ok) {&#xA;            throw new Error(`HTTP ${response.status}`);&#xA;          }&#xA;          &#xA;          const html = await response.text();&#xA;          const parser = new DOMParser();&#xA;          const doc = parser.parseFromString(html, &#39;text/html&#39;);&#xA;          &#xA;          const data = this.extractFromDocument(doc);&#xA;          if (data.name || data.price) {&#xA;            return data;&#xA;          }&#xA;          &#xA;          throw new Error(&#39;Keine Produktdaten gefunden&#39;);&#xA;        } catch (error) {&#xA;          console.warn(`Proxy ${i + 1} fehlgeschlagen:`, error);&#xA;          if (i === CORS_PROXIES.length - 1) {&#xA;            throw new Error(&#39;Alle Proxy-Services fehlgeschlagen&#39;);&#xA;          }&#xA;        }&#xA;      }&#xA;    }&#xA;    &#xA;    extractFromDocument(doc) {&#xA;      &#xA;      const structuredData = this.extractStructuredData(doc);&#xA;      if (structuredData.name || structuredData.price) {&#xA;        console.log(&#39;Strukturierte Daten gefunden:&#39;, structuredData);&#xA;        return structuredData;&#xA;      }&#xA;      &#xA;      const extractors = {&#xA;        digitec: this.extractDigitecData.bind(this),&#xA;        galaxus: this.extractGalaxusData.bind(this),&#xA;        amazon: this.extractAmazonData.bind(this),&#xA;        brack: this.extractBrackData.bind(this),&#xA;        mediamarkt: this.extractMediaMarktData.bind(this),&#xA;        default: this.extractGenericData.bind(this)&#xA;      };&#xA;      &#xA;      &#xA;      let extractor = extractors.default;&#xA;      for (const [domain, extractorFunc] of Object.entries(extractors)) {&#xA;        if (this.domain.includes(domain)) {&#xA;          extractor = extractorFunc;&#xA;          break;&#xA;        }&#xA;      }&#xA;      &#xA;      return extractor(doc);&#xA;    }&#xA;    &#xA;    extractStructuredData(doc) {&#xA;      const data = {};&#xA;      &#xA;      &#xA;      const metaTags = {&#xA;        &#xA;        price: [&#xA;          &#39;meta[property=&#34;product:price:amount&#34;]&#39;,&#xA;          &#39;meta[property=&#34;og:price:amount&#34;]&#39;,&#xA;          &#39;meta[name=&#34;price&#34;]&#39;,&#xA;          &#39;meta[property=&#34;price&#34;]&#39;,&#xA;          &#39;meta[itemprop=&#34;price&#34;]&#39;&#xA;        ],&#xA;        &#xA;        originalPrice: [&#xA;          &#39;meta[property=&#34;product:original_price:amount&#34;]&#39;,&#xA;          &#39;meta[property=&#34;og:original_price:amount&#34;]&#39;,&#xA;          &#39;meta[name=&#34;original_price&#34;]&#39;&#xA;        ],&#xA;        &#xA;        name: [&#xA;          &#39;meta[property=&#34;og:title&#34;]&#39;,&#xA;          &#39;meta[property=&#34;product:title&#34;]&#39;,&#xA;          &#39;meta[name=&#34;title&#34;]&#39;,&#xA;          &#39;meta[property=&#34;twitter:title&#34;]&#39;,&#xA;          &#39;meta[itemprop=&#34;name&#34;]&#39;&#xA;        ],&#xA;        &#xA;        image: [&#xA;          &#39;meta[property=&#34;og:image&#34;]&#39;,&#xA;          &#39;meta[property=&#34;product:image&#34;]&#39;,&#xA;          &#39;meta[name=&#34;image&#34;]&#39;,&#xA;          &#39;meta[property=&#34;twitter:image&#34;]&#39;,&#xA;          &#39;meta[itemprop=&#34;image&#34;]&#39;&#xA;        ],&#xA;        &#xA;        description: [&#xA;          &#39;meta[property=&#34;og:description&#34;]&#39;,&#xA;          &#39;meta[name=&#34;description&#34;]&#39;,&#xA;          &#39;meta[property=&#34;twitter:description&#34;]&#39;,&#xA;          &#39;meta[itemprop=&#34;description&#34;]&#39;&#xA;        ],&#xA;        &#xA;        currency: [&#xA;          &#39;meta[property=&#34;product:price:currency&#34;]&#39;,&#xA;          &#39;meta[property=&#34;og:price:currency&#34;]&#39;,&#xA;          &#39;meta[name=&#34;currency&#34;]&#39;&#xA;        ]&#xA;      };&#xA;      &#xA;      &#xA;      for (const [key, selectors] of Object.entries(metaTags)) {&#xA;        for (const selector of selectors) {&#xA;          const element = doc.querySelector(selector);&#xA;          if (element &amp;&amp; element.getAttribute(&#39;content&#39;)) {&#xA;            data[key] = element.getAttribute(&#39;content&#39;).trim();&#xA;            break;&#xA;          }&#xA;        }&#xA;      }&#xA;      &#xA;      &#xA;      const jsonLdScripts = doc.querySelectorAll(&#39;script[type=&#34;application/ld+json&#34;]&#39;);&#xA;      jsonLdScripts.forEach(script =&gt; {&#xA;        try {&#xA;          const jsonData = JSON.parse(script.textContent);&#xA;          const productData = this.extractFromJsonLd(jsonData);&#xA;          Object.assign(data, productData);&#xA;        } catch (e) {&#xA;          console.warn(&#39;JSON-LD parsing fehler:&#39;, e);&#xA;        }&#xA;      });&#xA;      &#xA;      &#xA;      const microdataProduct = doc.querySelector(&#39;[itemscope][itemtype*=&#34;Product&#34;]&#39;);&#xA;      if (microdataProduct) {&#xA;        const microdataData = this.extractFromMicrodata(microdataProduct);&#xA;        Object.assign(data, microdataData);&#xA;      }&#xA;      &#xA;      &#xA;      const dataAttributes = this.extractFromDataAttributes(doc);&#xA;      Object.assign(data, dataAttributes);&#xA;      &#xA;      &#xA;      if (data.price &amp;&amp; data.currency) {&#xA;        data.price = `${data.currency} ${data.price}`;&#xA;      }&#xA;      &#xA;      return data;&#xA;    }&#xA;    &#xA;    extractFromJsonLd(jsonData) {&#xA;      const data = {};&#xA;      &#xA;      &#xA;      if (Array.isArray(jsonData)) {&#xA;        for (const item of jsonData) {&#xA;          const itemData = this.extractFromJsonLd(item);&#xA;          Object.assign(data, itemData);&#xA;        }&#xA;        return data;&#xA;      }&#xA;      &#xA;      if (jsonData[&#39;@type&#39;] === &#39;Product&#39; || jsonData.type === &#39;Product&#39;) {&#xA;        if (jsonData.name) data.name = jsonData.name;&#xA;        if (jsonData.image &amp;&amp; Array.isArray(jsonData.image)) {&#xA;          data.image = jsonData.image[0];&#xA;        } else if (jsonData.image) {&#xA;          data.image = jsonData.image;&#xA;        }&#xA;        &#xA;        &#xA;        if (jsonData.offers) {&#xA;          const offers = Array.isArray(jsonData.offers) ? jsonData.offers[0] : jsonData.offers;&#xA;          if (offers.price) data.price = offers.price;&#xA;          if (offers.priceCurrency) data.currency = offers.priceCurrency;&#xA;          if (offers.highPrice) data.originalPrice = offers.highPrice;&#xA;        }&#xA;        &#xA;        if (jsonData.description) {&#xA;          data.features = [jsonData.description.substring(0, 100)];&#xA;        }&#xA;      }&#xA;      &#xA;      return data;&#xA;    }&#xA;    &#xA;    extractFromMicrodata(element) {&#xA;      const data = {};&#xA;      &#xA;      const nameEl = element.querySelector(&#39;[itemprop=&#34;name&#34;]&#39;);&#xA;      if (nameEl) data.name = nameEl.textContent.trim();&#xA;      &#xA;      const priceEl = element.querySelector(&#39;[itemprop=&#34;price&#34;]&#39;);&#xA;      if (priceEl) data.price = priceEl.textContent.trim();&#xA;      &#xA;      const imageEl = element.querySelector(&#39;[itemprop=&#34;image&#34;]&#39;);&#xA;      if (imageEl) data.image = imageEl.src || imageEl.getAttribute(&#39;content&#39;);&#xA;      &#xA;      return data;&#xA;    }&#xA;    &#xA;    extractFromDataAttributes(doc) {&#xA;      const data = {};&#xA;      &#xA;      &#xA;      const dataSelectors = [&#xA;        { attr: &#39;data-price&#39;, key: &#39;price&#39; },&#xA;        { attr: &#39;data-original-price&#39;, key: &#39;originalPrice&#39; },&#xA;        { attr: &#39;data-product-name&#39;, key: &#39;name&#39; },&#xA;        { attr: &#39;data-product-title&#39;, key: &#39;name&#39; },&#xA;        { attr: &#39;data-product-image&#39;, key: &#39;image&#39; },&#xA;        { attr: &#39;data-currency&#39;, key: &#39;currency&#39; }&#xA;      ];&#xA;      &#xA;      for (const { attr, key } of dataSelectors) {&#xA;        const element = doc.querySelector(`[${attr}]`);&#xA;        if (element &amp;&amp; element.getAttribute(attr)) {&#xA;          data[key] = element.getAttribute(attr).trim();&#xA;        }&#xA;      }&#xA;      &#xA;      return data;&#xA;    }&#xA;    &#xA;    extractDigitecData(doc) {&#xA;      console.log(&#39;Extracting Digitec data...&#39;);&#xA;      return {&#xA;        name: this.getTextContent(doc, [&#xA;          &#39;[data-cy=&#34;product-name&#34;]&#39;,&#xA;          &#39;.pdp-product-name&#39;,&#xA;          &#39;h1[data-cy=&#34;product-name&#34;]&#39;,&#xA;          &#39;.ProductSummary_name&#39;,&#xA;          &#39;.product-title&#39;,&#xA;          &#39;h1&#39;&#xA;        ]),&#xA;        price: this.getTextContent(doc, [&#xA;          &#39;[data-cy=&#34;price-current&#34;]&#39;,&#xA;          &#39;.price-current&#39;,&#xA;          &#39;.ProductSummary_price .price&#39;,&#xA;          &#39;.price .price-value&#39;,&#xA;          &#39;.offer-price strong&#39;&#xA;        ]),&#xA;        originalPrice: this.getTextContent(doc, [&#xA;          &#39;[data-cy=&#34;price-old&#34;]&#39;,&#xA;          &#39;.price-old&#39;,&#xA;          &#39;.price-struck&#39;&#xA;        ]),&#xA;        image: this.getImageSrc(doc, [&#xA;          &#39;[data-cy=&#34;product-image&#34;] img&#39;,&#xA;          &#39;.ProductImages img&#39;,&#xA;          &#39;.product-image img&#39;,&#xA;          &#39;.gallery-main img&#39;,&#xA;          &#39;.product-gallery img&#39;&#xA;        ]),&#xA;        features: this.getFeatures(doc, [&#xA;          &#39;.ProductSpecifications .specification-item&#39;,&#xA;          &#39;.specifications-table td&#39;,&#xA;          &#39;.product-highlights li&#39;,&#xA;          &#39;.features li&#39;&#xA;        ])&#xA;      };&#xA;    }&#xA;    &#xA;    extractGalaxusData(doc) {&#xA;      return this.extractDigitecData(doc); &#xA;    }&#xA;    &#xA;    extractAmazonData(doc) {&#xA;      return {&#xA;        name: this.getTextContent(doc, [&#xA;          &#39;#productTitle&#39;,&#xA;          &#39;.product-title&#39;,&#xA;          &#39;h1.a-size-large&#39;&#xA;        ]),&#xA;        price: this.getTextContent(doc, [&#xA;          &#39;.a-price-whole&#39;,&#xA;          &#39;.a-price .a-offscreen&#39;,&#xA;          &#39;.apexPriceToPay .a-price-whole&#39;,&#xA;          &#39;.a-price-current&#39;&#xA;        ]),&#xA;        originalPrice: this.getTextContent(doc, [&#xA;          &#39;.a-text-price .a-offscreen&#39;,&#xA;          &#39;.priceBlockStrikePriceString&#39;&#xA;        ]),&#xA;        image: this.getImageSrc(doc, [&#xA;          &#39;#landingImage&#39;,&#xA;          &#39;.imgTagWrapper img&#39;,&#xA;          &#39;#main-image&#39;&#xA;        ]),&#xA;        features: this.getFeatures(doc, [&#xA;          &#39;#feature-bullets ul li span&#39;,&#xA;          &#39;.aplus-v2 .aplus-standard .aplus-module .aplus-standard-text&#39;&#xA;        ])&#xA;      };&#xA;    }&#xA;    &#xA;    extractBrackData(doc) {&#xA;      return {&#xA;        name: this.getTextContent(doc, [&#xA;          &#39;.product-name&#39;,&#xA;          &#39;h1&#39;,&#xA;          &#39;.title&#39;&#xA;        ]),&#xA;        price: this.getTextContent(doc, [&#xA;          &#39;.price-actual&#39;,&#xA;          &#39;.current-price&#39;&#xA;        ]),&#xA;        image: this.getImageSrc(doc, [&#xA;          &#39;.product-image-main img&#39;,&#xA;          &#39;.product-gallery img&#39;&#xA;        ])&#xA;      };&#xA;    }&#xA;    &#xA;    extractMediaMarktData(doc) {&#xA;      return {&#xA;        name: this.getTextContent(doc, [&#xA;          &#39;.pdp-product-name&#39;,&#xA;          &#39;h1&#39;&#xA;        ]),&#xA;        price: this.getTextContent(doc, [&#xA;          &#39;.price-current&#39;,&#xA;          &#39;.price&#39;&#xA;        ]),&#xA;        image: this.getImageSrc(doc, [&#xA;          &#39;.product-image img&#39;&#xA;        ])&#xA;      };&#xA;    }&#xA;    &#xA;    extractGenericData(doc) {&#xA;      &#xA;      return {&#xA;        name: this.getTextContent(doc, [&#xA;          &#39;h1&#39;,&#xA;          &#39;.product-title&#39;,&#xA;          &#39;.product-name&#39;,&#xA;          &#39;[data-testid=&#34;product-title&#34;]&#39;,&#xA;          &#39;.title&#39;,&#xA;          &#39;[itemprop=&#34;name&#34;]&#39;,&#xA;          &#39;.pdp-product-name&#39;&#xA;        ]),&#xA;        price: this.getTextContent(doc, [&#xA;          &#39;.price&#39;,&#xA;          &#39;.current-price&#39;,&#xA;          &#39;.product-price&#39;,&#xA;          &#39;[data-testid=&#34;price&#34;]&#39;,&#xA;          &#39;.price-current&#39;,&#xA;          &#39;[itemprop=&#34;price&#34;]&#39;,&#xA;          &#39;.offer-price&#39;,&#xA;          &#39;.sale-price&#39;,&#xA;          &#39;.final-price&#39;&#xA;        ]),&#xA;        originalPrice: this.getTextContent(doc, [&#xA;          &#39;.original-price&#39;,&#xA;          &#39;.list-price&#39;,&#xA;          &#39;.regular-price&#39;,&#xA;          &#39;.price-old&#39;,&#xA;          &#39;.was-price&#39;,&#xA;          &#39;.strikethrough&#39;&#xA;        ]),&#xA;        image: this.getImageSrc(doc, [&#xA;          &#39;.product-image img&#39;,&#xA;          &#39;.product-gallery img&#39;,&#xA;          &#39;img[alt*=&#34;product&#34;]&#39;,&#xA;          &#39;main img&#39;,&#xA;          &#39;[itemprop=&#34;image&#34;]&#39;,&#xA;          &#39;.hero-image img&#39;&#xA;        ]),&#xA;        features: this.getFeatures(doc, [&#xA;          &#39;.features li&#39;,&#xA;          &#39;.specifications li&#39;,&#xA;          &#39;.product-features li&#39;,&#xA;          &#39;.highlights li&#39;,&#xA;          &#39;.key-features li&#39;&#xA;        ])&#xA;      };&#xA;    }&#xA;    &#xA;    getTextContent(doc, selectors) {&#xA;      for (const selector of selectors) {&#xA;        try {&#xA;          const element = doc.querySelector(selector);&#xA;          if (element &amp;&amp; element.textContent &amp;&amp; element.textContent.trim()) {&#xA;            return element.textContent.trim();&#xA;          }&#xA;        } catch (e) {&#xA;          console.warn(&#39;Selector fehler:&#39;, selector, e);&#xA;        }&#xA;      }&#xA;      return null;&#xA;    }&#xA;    &#xA;    getImageSrc(doc, selectors) {&#xA;      for (const selector of selectors) {&#xA;        try {&#xA;          const element = doc.querySelector(selector);&#xA;          if (element &amp;&amp; element.src) {&#xA;            return element.src;&#xA;          }&#xA;        } catch (e) {&#xA;          console.warn(&#39;Image selector fehler:&#39;, selector, e);&#xA;        }&#xA;      }&#xA;      return null;&#xA;    }&#xA;    &#xA;    getFeatures(doc, selectors) {&#xA;      const features = [];&#xA;      for (const selector of selectors) {&#xA;        try {&#xA;          const elements = doc.querySelectorAll(selector);&#xA;          elements.forEach(el =&gt; {&#xA;            const text = el.textContent.trim();&#xA;            if (text &amp;&amp; !features.includes(text) &amp;&amp; features.length &lt; 5) {&#xA;              features.push(text);&#xA;            }&#xA;          });&#xA;          if (features.length &gt;= 3) break;&#xA;        } catch (e) {&#xA;          console.warn(&#39;Features selector fehler:&#39;, selector, e);&#xA;        }&#xA;      }&#xA;      return features;&#xA;    }&#xA;  }&#xA;  &#xA;  &#xA;  class PriceGrabber {&#xA;    constructor(element) {&#xA;      this.element = element;&#xA;      this.url = element.dataset.url;&#xA;      this.currency = element.dataset.currency || &#39;CHF&#39;;&#xA;      this.autoScrape = element.dataset.autoScrape !== &#39;false&#39;;&#xA;      &#xA;      &#xA;      this.manualData = {&#xA;        price: element.dataset.manualPrice,&#xA;        originalPrice: element.dataset.manualOriginalPrice,&#xA;        image: element.dataset.manualImage,&#xA;        name: element.dataset.manualName,&#xA;        features: element.dataset.manualFeatures ? element.dataset.manualFeatures.split(&#39;|&#39;) : []&#xA;      };&#xA;      &#xA;      this.init();&#xA;    }&#xA;    &#xA;    async init() {&#xA;      &#xA;      if (this.hasManualData()) {&#xA;        this.updateUI(this.manualData);&#xA;        return;&#xA;      }&#xA;      &#xA;      if (!this.url) {&#xA;        this.showError(&#39;Keine URL angegeben&#39;);&#xA;        return;&#xA;      }&#xA;      &#xA;      if (!this.autoScrape) {&#xA;        this.showManualDataInfo();&#xA;        return;&#xA;      }&#xA;      &#xA;      try {&#xA;        await this.loadProductData();&#xA;      } catch (error) {&#xA;        this.showError(error.message);&#xA;      }&#xA;    }&#xA;    &#xA;    hasManualData() {&#xA;      return this.manualData.price || this.manualData.name || this.manualData.image;&#xA;    }&#xA;    &#xA;    async loadProductData() {&#xA;      const extractor = new ProductExtractor(this.url);&#xA;      const data = await extractor.extractData();&#xA;      &#xA;      if (!data.name &amp;&amp; !data.price) {&#xA;        throw new Error(&#39;Produktdaten konnten nicht extrahiert werden&#39;);&#xA;      }&#xA;      &#xA;      this.updateUI(data);&#xA;    }&#xA;    &#xA;    updateUI(data) {&#xA;      &#xA;      const statusIndicator = this.element.querySelector(&#39;.status-indicator&#39;);&#xA;      statusIndicator.className = &#39;status-indicator success&#39;;&#xA;      statusIndicator.innerHTML = this.hasManualData() ? &#xA;        &#39;&lt;i class=&#34;fas fa-check-circle&#34;&gt;&lt;/i&gt; Manuell&#39; : &#xA;        &#39;&lt;i class=&#34;fas fa-check-circle&#34;&gt;&lt;/i&gt; Aktuell&#39;;&#xA;      &#xA;      &#xA;      if (data.name) {&#xA;        const nameElement = this.element.querySelector(&#39;.product-name&#39;);&#xA;        nameElement.textContent = data.name;&#xA;      }&#xA;      &#xA;      &#xA;      if (data.image) {&#xA;        const imageElement = this.element.querySelector(&#39;.product-image&#39;);&#xA;        imageElement.src = data.image;&#xA;        imageElement.alt = data.name || &#39;Produktbild&#39;;&#xA;        imageElement.classList.remove(&#39;placeholder&#39;);&#xA;      }&#xA;      &#xA;      &#xA;      if (data.price) {&#xA;        const priceElement = this.element.querySelector(&#39;.current-price&#39;);&#xA;        const cleanPrice = this.formatPrice(data.price);&#xA;        priceElement.textContent = cleanPrice;&#xA;        &#xA;        &#xA;        if (data.originalPrice) {&#xA;          const originalPriceElement = this.element.querySelector(&#39;.original-price&#39;);&#xA;          originalPriceElement.textContent = this.formatPrice(data.originalPrice);&#xA;          originalPriceElement.style.display = &#39;inline&#39;;&#xA;          &#xA;          &#xA;          const discount = this.calculateDiscount(data.originalPrice, data.price);&#xA;          if (discount &gt; 0) {&#xA;            const discountElement = this.element.querySelector(&#39;.discount-badge&#39;);&#xA;            discountElement.textContent = `-${discount}%`;&#xA;            discountElement.style.display = &#39;inline&#39;;&#xA;          }&#xA;        }&#xA;      }&#xA;      &#xA;      &#xA;      if (data.features &amp;&amp; data.features.length &gt; 0) {&#xA;        const featuresList = this.element.querySelector(&#39;.features-list&#39;);&#xA;        featuresList.innerHTML = data.features&#xA;          .slice(0, 5)&#xA;          .map(feature =&gt; `&lt;li&gt;${feature}&lt;/li&gt;`)&#xA;          .join(&#39;&#39;);&#xA;      }&#xA;      &#xA;      &#xA;      const updateTimeElement = this.element.querySelector(&#39;.update-time&#39;);&#xA;      updateTimeElement.textContent = this.hasManualData() ? &#xA;        &#39;Manuell eingegeben&#39; : &#xA;        new Date().toLocaleString(&#39;de-DE&#39;);&#xA;    }&#xA;    &#xA;    formatPrice(priceString) {&#xA;      if (!priceString) return &#39;--&#39;;&#xA;      &#xA;      &#xA;      const numbers = priceString.match(/[\d.,]+/);&#xA;      if (!numbers) return priceString;&#xA;      &#xA;      const cleanPrice = numbers[0].replace(&#39;,&#39;, &#39;.&#39;);&#xA;      const price = parseFloat(cleanPrice);&#xA;      &#xA;      if (isNaN(price)) return priceString;&#xA;      &#xA;      return new Intl.NumberFormat(&#39;de-CH&#39;, {&#xA;        style: &#39;currency&#39;,&#xA;        currency: this.currency&#xA;      }).format(price);&#xA;    }&#xA;    &#xA;    calculateDiscount(originalPrice, currentPrice) {&#xA;      const original = parseFloat(originalPrice.match(/[\d.,]+/)?.[0]?.replace(&#39;,&#39;, &#39;.&#39;) || 0);&#xA;      const current = parseFloat(currentPrice.match(/[\d.,]+/)?.[0]?.replace(&#39;,&#39;, &#39;.&#39;) || 0);&#xA;      &#xA;      if (original &gt; current &amp;&amp; original &gt; 0) {&#xA;        return Math.round(((original - current) / original) * 100);&#xA;      }&#xA;      return 0;&#xA;    }&#xA;    &#xA;    showManualDataInfo() {&#xA;      const statusIndicator = this.element.querySelector(&#39;.status-indicator&#39;);&#xA;      statusIndicator.className = &#39;status-indicator info&#39;;&#xA;      statusIndicator.innerHTML = &#39;&lt;i class=&#34;fas fa-info-circle&#34;&gt;&lt;/i&gt; Auto-Scraping deaktiviert&#39;;&#xA;      &#xA;      const content = this.element.querySelector(&#39;.price-grabber-content&#39;);&#xA;      content.innerHTML += `&lt;div class=&#34;info-message&#34;&gt;&#xA;        &lt;strong&gt;Automatisches Laden deaktiviert&lt;/strong&gt;&lt;br&gt;&#xA;        Verwenden Sie die manuellen Parameter für Produktdaten.&#xA;      &lt;/div&gt;`;&#xA;    }&#xA;    &#xA;    showError(message) {&#xA;      const statusIndicator = this.element.querySelector(&#39;.status-indicator&#39;);&#xA;      statusIndicator.className = &#39;status-indicator error&#39;;&#xA;      statusIndicator.innerHTML = &#39;&lt;i class=&#34;fas fa-exclamation-triangle&#34;&gt;&lt;/i&gt; Fehler&#39;;&#xA;      &#xA;      const content = this.element.querySelector(&#39;.price-grabber-content&#39;);&#xA;      content.innerHTML += `&lt;div class=&#34;error-message&#34;&gt;&#xA;        &lt;strong&gt;Fehler beim Laden der Produktdaten:&lt;/strong&gt;&lt;br&gt;&#xA;        ${message}&lt;br&gt;&#xA;        &lt;small&gt;&#xA;          &lt;strong&gt;Tipp:&lt;/strong&gt; Verwenden Sie manuelle Parameter für statische Daten:&lt;br&gt;&#xA;          &lt;code&gt;price=&#34;1299.00&#34; name=&#34;Canon EOS R5&#34; image=&#34;image-url.jpg&#34;&lt;/code&gt;&#xA;        &lt;/small&gt;&#xA;      &lt;/div&gt;`;&#xA;    }&#xA;  }&#xA;  &#xA;  &#xA;  document.addEventListener(&#39;DOMContentLoaded&#39;, function() {&#xA;    const widgets = document.querySelectorAll(&#39;.price-grabber-widget&#39;);&#xA;    widgets.forEach(widget =&gt; new PriceGrabber(widget));&#xA;    &#xA;    &#xA;    initializeCarousels();&#xA;  });&#xA;  &#xA;  &#xA;  function initializeCarousels() {&#xA;    const carousels = document.querySelectorAll(&#39;.product-carousel&#39;);&#xA;    carousels.forEach(carousel =&gt; {&#xA;      const widgetId = carousel.id.replace(&#39;carousel-&#39;, &#39;&#39;);&#xA;      const cards = carousel.querySelectorAll(&#39;.product-card&#39;);&#xA;      &#xA;      &#xA;      if (cards.length &gt; 1) {&#xA;        addTouchSupport(carousel, widgetId);&#xA;        &#xA;        &#xA;        addKeyboardSupport(carousel, widgetId);&#xA;        &#xA;        &#xA;        &#xA;      }&#xA;    });&#xA;  }&#xA;  &#xA;  &#xA;  function addTouchSupport(carousel, widgetId) {&#xA;    let startX = 0;&#xA;    let startY = 0;&#xA;    let currentX = 0;&#xA;    let currentY = 0;&#xA;    let isDragging = false;&#xA;    let horizontalGesture = false;&#xA;&#xA;    carousel.addEventListener(&#39;touchstart&#39;, function(e) {&#xA;      if(e.touches.length!==1) return;&#xA;      startX = e.touches[0].clientX;&#xA;      startY = e.touches[0].clientY;&#xA;      currentX = startX; currentY = startY;&#xA;      isDragging = true;&#xA;      horizontalGesture = false;&#xA;    }, {passive:true});&#xA;&#xA;    carousel.addEventListener(&#39;touchmove&#39;, function(e) {&#xA;      if (!isDragging || e.touches.length!==1) return;&#xA;      currentX = e.touches[0].clientX;&#xA;      currentY = e.touches[0].clientY;&#xA;      const diffX = Math.abs(currentX - startX);&#xA;      const diffY = Math.abs(currentY - startY);&#xA;      &#xA;      if(!horizontalGesture &amp;&amp; (diffX &gt; 10 || diffY &gt; 10)) {&#xA;        horizontalGesture = diffX &gt; diffY; &#xA;      }&#xA;      &#xA;      if(horizontalGesture) {&#xA;        e.preventDefault(); &#xA;      }&#xA;    }, {passive:false});&#xA;&#xA;    carousel.addEventListener(&#39;touchend&#39;, function(e) {&#xA;      if (!isDragging) return;&#xA;      isDragging = false;&#xA;      if(!horizontalGesture) return; &#xA;      const diff = startX - currentX;&#xA;      const threshold = 50; &#xA;      if (Math.abs(diff) &gt; threshold) {&#xA;        if (diff &gt; 0) {&#xA;          window.moveCarousel(widgetId, 1);&#xA;        } else {&#xA;          window.moveCarousel(widgetId, -1);&#xA;        }&#xA;      }&#xA;    }, {passive:true});&#xA;  }&#xA;  &#xA;  &#xA;  function addKeyboardSupport(carousel, widgetId) {&#xA;    carousel.setAttribute(&#39;tabindex&#39;, &#39;0&#39;);&#xA;    carousel.addEventListener(&#39;keydown&#39;, function(e) {&#xA;      switch(e.key) {&#xA;        case &#39;ArrowLeft&#39;:&#xA;          e.preventDefault();&#xA;          window.moveCarousel(widgetId, -1);&#xA;          break;&#xA;        case &#39;ArrowRight&#39;:&#xA;          e.preventDefault();&#xA;          window.moveCarousel(widgetId, 1);&#xA;          break;&#xA;      }&#xA;    });&#xA;  }&#xA;  &#xA;  &#xA;  if (typeof MutationObserver !== &#39;undefined&#39;) {&#xA;    const observer = new MutationObserver(function(mutations) {&#xA;      mutations.forEach(function(mutation) {&#xA;        mutation.addedNodes.forEach(function(node) {&#xA;          if (node.nodeType === 1) { &#xA;            const widgets = node.querySelectorAll ? node.querySelectorAll(&#39;.price-grabber-widget&#39;) : [];&#xA;            widgets.forEach(widget =&gt; new PriceGrabber(widget));&#xA;            &#xA;            &#xA;            const newCarousels = node.querySelectorAll ? node.querySelectorAll(&#39;.product-carousel&#39;) : [];&#xA;            newCarousels.forEach(carousel =&gt; {&#xA;              const widgetId = carousel.id.replace(&#39;carousel-&#39;, &#39;&#39;);&#xA;              const cards = carousel.querySelectorAll(&#39;.product-card&#39;);&#xA;              if (cards.length &gt; 1) {&#xA;                addTouchSupport(carousel, widgetId);&#xA;                addKeyboardSupport(carousel, widgetId);&#xA;              }&#xA;            });&#xA;          }&#xA;        });&#xA;      });&#xA;    });&#xA;    &#xA;    observer.observe(document.body, {&#xA;      childList: true,&#xA;      subtree: true&#xA;    });&#xA;  }&#xA;})();&#xA;&lt;/script&gt;&#xA;&lt;h2 id=&#34;partner&#34;&gt;Partner&lt;/h2&gt;&#xA;&lt;p&gt;Dieser Artikel ist in Zusammenarbeit mit &lt;a href=&#34;https://www.ulanzi.com&#34;&#xA;&#xA;&#xA;&#xA;&#xA; target=&#34;_blank&#34;&#xA; &#xA;&#xA;&#xA;&gt;&lt;strong&gt;Ulanzi&lt;/strong&gt;&lt;/a&gt; entstanden. Ich habe das Produkt für dieses Video kostenlos erhalten. Dies hat jedoch keinen Einfluss auf meine Meinung und die Bewertung des Produkts. Ich habe das Produkt unabhängig getestet und meine ehrliche Meinung dazu abgegeben.&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;brand-grid-container&#34;&gt;&#xA;&lt;div class=&#34;brand-single&#34;&gt;&#xA;&lt;a href=&#34;https://www.ulanzi.com&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34; aria-label=&#34;Visit Ulanzi&#34;&gt;&#xA;&#xA;&lt;img src=&#34;https://smotographers.com/images/sponsor-logos/ulanzi.jpg&#34; alt=&#34;Ulanzi Logo&#34; loading=&#34;lazy&#34; /&gt;&#xA;&#xA;&lt;/a&gt;&#xA;&#xA;&lt;div class=&#34;brand-name&#34;&gt;Ulanzi&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;style&gt;&#xA;.brand-grid-container {&#xA;    width: 100%;&#xA;    overflow: hidden;&#xA;}&#xA;.brand-grid {&#xA;    display: grid;&#xA;    gap: 1.5rem;&#xA;    padding: 1.5rem;&#xA;    justify-items: center;&#xA;    align-items: center;&#xA;    max-width: 1200px;&#xA;    margin: 0 auto;&#xA;}&#xA;.brand-single {&#xA;    text-align: center;&#xA;    max-width: 180px;&#xA;    cursor: pointer;&#xA;    transition: transform 0.3s ease;&#xA;}&#xA;.brand-single:hover {&#xA;    transform: translateY(-5px);&#xA;}&#xA;.brand-single img {&#xA;    max-width: 100%;&#xA;    height: auto;&#xA;    max-height: 80px;&#xA;    margin-bottom: 0.5rem;&#xA;    object-fit: contain;&#xA;}&#xA;.brand-name {&#xA;    font-weight: 600;&#xA;    color: #333;&#xA;    font-size: 0.9rem;&#xA;    line-height: 1.3;&#xA;    background: white;&#xA;    padding: 0.25rem 0.5rem;&#xA;    border-radius: 4px;&#xA;}&#xA;.brand-placeholder {&#xA;    width: 120px;&#xA;    height: 80px;&#xA;    background: #f0f0f0;&#xA;    display: flex;&#xA;    align-items: center;&#xA;    justify-content: center;&#xA;    border-radius: 4px;&#xA;    font-size: 0.8rem;&#xA;    padding: 0.5rem;&#xA;    color: #666;&#xA;}&#xA; &#xA;@media (max-width: 768px) {&#xA;    .brand-grid {&#xA;        grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)) !important;&#xA;        gap: 1rem;&#xA;        padding: 1rem;&#xA;    }&#xA;}&#xA;&lt;/style&gt;&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
