/* ============================================================
   pdp-b.css – VERSION B · premium above-the-fold
   Scoped to .pdp-b so Version A (index.html) + shared pdp.css
   stay untouched. Design language: restraint, hierarchy, air.
   • Farbe = VARIANTE (eigene Art.-Nr.) – außerhalb der Konfig,
     steuert die Optionen.
   • Konfiguration = ERFORDERLICH – geführt über einen ruhigen
     Fortschritts-Spine, KEIN gesperrter Button, KEINE Warnung.
   • CTA = immer aktiv & morphend: „Weiter …" → „In den Warenkorb".
   ============================================================ */

/* Match the LIVE product page grid (edelstahl-tuerklingel.de): the mw-container is
   a fixed 1600px, and the product row is two equal Bootstrap columns (col-sm-6 /
   col-sm-6) with a ~64px gutter between gallery and info. Cap --container at 1600
   (overrides the design system's 1760/2040 growth) and use a 50/50 hero grid. */
:root { --container: 100rem; }   /* 1600px */

/* ── Semantic text tokens (mirrors the About-us model: role-named inks layered
   over the graphite scale). Muted ink = graphite-600 (#6A6A6A), which is AA-safe
   on white – NOT the DS numeric #7A7A82, which fails AA. On-dark text uses one
   small set (strong/muted) instead of nine ad-hoc opacities. ── */
:root {
  --text-primary:   var(--color-digital-black);   /* #1A171B – titles, key copy */
  --text-secondary: var(--color-graphite-700);     /* #54545C – readable secondary copy */
  --text-muted:     var(--color-graphite-600);     /* #6A6A6A – captions / metadata / labels */
  --on-dark-strong: rgba(255, 255, 255, 0.85);     /* emphasis / labels on dark */
  --on-dark-muted:  rgba(255, 255, 255, 0.65);     /* secondary text on dark */
}
/* match the live mw-container box model exactly: 1600 container − 100px inline
   padding each side = 1400px content */
@media (min-width: 1440px) { .container { padding-inline: 100px; } }
.pdp-b .pdp-hero__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 4rem; }

/* ── Wide screens: thumbnails as a fixed 2-row grid – fewer per row, larger tiles,
   NO inner scroll (a nested scroll area fights the page scroll). Extra images live
   behind an "Alle Bilder" lightbox opened from the button below the grid.
   The media column stays sticky (base pdp.css), so the image block pins on scroll.
   Desktop only (≥ 56.25rem); the mobile scroll-strip is untouched.
   Selector carries .pdp-media so it beats the base `.pdp-b .pdp-thumbs button`
   tile size that sits later in the file at equal specificity. ── */
@media (min-width: 56.25rem) {
  .pdp-b .pdp-media .pdp-thumbs {
    display: grid; grid-template-columns: repeat(5, 1fr); gap: 0.6rem;
    max-width: none; padding: 0; overflow: visible;
    -webkit-mask-image: none; mask-image: none; }
  .pdp-b .pdp-media .pdp-thumbs li { flex: initial; scroll-snap-align: none; }
  .pdp-b .pdp-media .pdp-thumbs::after { display: none; }   /* the mobile fade-clearance spacer has no place in the desktop grid */
  .pdp-b .pdp-media .pdp-thumbs li:nth-child(n+11) { display: none; }   /* first 10 inline; rest in the lightbox */
  .pdp-b .pdp-media .pdp-thumbs button { width: 100%; height: auto; aspect-ratio: 1; padding: 0.5rem; }
  .pdp-b .pdp-media .pdp-thumbs__all:not([hidden]) { display: inline-flex; }
}

/* "Alle N Bilder ansehen" button. Hidden by default (mobile keeps the strip);
   JS un-hides it on desktop only when there are more images than fit inline.
   The reviews "Alle N Bewertungen ansehen" CTA mirrors this style. */
.pdp-b .pdp-thumbs__all { display: none; align-items: center; justify-content: center; gap: 0.4rem;
  margin-top: 0.75rem; width: 100%; padding: 0.6rem 1rem; cursor: pointer;
  font: inherit; font-size: 0.75rem; font-weight: 700; color: var(--color-teal);
  background: var(--color-white); border: 1px solid var(--color-graphite-200);
  border-radius: var(--radius); transition: border-color .15s, background .15s; }   /* 4px, matching the thumbnails (was --radius-lg / 8px) */
.pdp-b .pdp-thumbs__all:hover { border-color: var(--color-teal); background: var(--color-teal-50); }
.pdp-b .pdp-thumbs__all svg { width: 1.05rem; height: 1.05rem; }

/* ── Lightbox – full-screen gallery of every product image. The page is locked
   behind it, so the modal's own scroll never conflicts with the page. ── */
/* Full-screen viewer: one large image centred on a dim backdrop, prev/next arrows, a
   position counter, and a sliding thumbnail strip along the bottom to jump anywhere. */
.pdp-lightbox { position: fixed; inset: 0; z-index: 1000; display: none; }
.pdp-lightbox[aria-hidden="false"] { display: block; }
.pdp-lightbox__backdrop { position: absolute; inset: 0; background: rgba(12,14,17,0.92);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
.pdp-lightbox__panel { position: absolute; inset: 0; display: flex; flex-direction: column;
  padding: clamp(0.75rem, 2vw, 1.5rem); gap: clamp(0.75rem, 2vw, 1.25rem); }
.pdp-lightbox__bar { flex: none; display: flex; align-items: center; justify-content: space-between; color: var(--color-white); }
.pdp-lightbox__counter { font-size: 0.875rem; font-weight: 700; letter-spacing: 0.03em; color: var(--on-dark-strong); font-variant-numeric: tabular-nums; }
.pdp-lightbox__close { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; cursor: pointer;
  background: none; border: 0; color: var(--color-white); transition: color .15s ease, transform .15s ease; }
.pdp-lightbox__close:hover { color: var(--on-dark-strong); transform: scale(1.08); }
.pdp-lightbox__close:focus-visible { outline: 2px solid var(--color-white); outline-offset: 2px; }
.pdp-lightbox__close svg { width: 1.25rem; height: 1.25rem; }
.pdp-lightbox__stage { position: relative; flex: 1 1 auto; min-height: 0; display: flex; align-items: center; justify-content: center; overflow: hidden; }
.pdp-lightbox__img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; border-radius: var(--radius-lg);
  background: var(--color-white); box-shadow: 0 24px 60px -20px rgba(0,0,0,0.65); }
/* nav arrows – design-system slider arrow: square var(--radius), translucent dark fill + white outline, inverts on hover (never circular) */
.pdp-lightbox__nav { position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  display: grid; place-items: center; width: 2.75rem; height: 2.75rem; cursor: pointer;
  background: rgba(0,0,0,0.28); border: 1px solid rgba(255,255,255,0.85); border-radius: var(--radius); color: var(--color-white);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); transition: background .15s ease, color .15s ease, transform .12s ease; }
@media (hover: hover) { .pdp-lightbox__nav:hover { background: var(--color-white); color: var(--color-digital-black); } }
.pdp-lightbox__nav:active { background: var(--color-white); color: var(--color-digital-black); transform: translateY(-50%) scale(0.94); }
.pdp-lightbox__nav:focus-visible { outline: 2px solid var(--color-white); outline-offset: 2px; }
.pdp-lightbox__nav svg { width: 1.4rem; height: 1.4rem; }
.pdp-lightbox__nav--prev { left: clamp(0.5rem, 1.5vw, 1rem); }
.pdp-lightbox__nav--next { right: clamp(0.5rem, 1.5vw, 1rem); }
.pdp-lightbox__strip { flex: none; display: flex; gap: 0.5rem; overflow-x: auto; padding: 0.25rem;
  scrollbar-width: none; -ms-overflow-style: none; scroll-behavior: smooth; justify-content: center; }
.pdp-lightbox__strip::after { content: ""; flex: 0 0 0.25rem; }   /* tiny trailing pad for the last thumb */
.pdp-lightbox__strip::-webkit-scrollbar { display: none; }
.pdp-lightbox__thumb { flex: 0 0 auto; width: 4.5rem; height: 4.5rem; padding: 0; cursor: pointer; overflow: hidden;
  background: var(--color-white); border: 2px solid transparent; border-radius: var(--radius); opacity: 0.5;
  transition: opacity .15s ease, border-color .15s ease; }
.pdp-lightbox__thumb:hover { opacity: 0.85; }
.pdp-lightbox__thumb[aria-current="true"] { opacity: 1; border-color: var(--color-white); }
.pdp-lightbox__thumb:focus-visible { outline: 2px solid var(--color-white); outline-offset: 2px; opacity: 1; }
.pdp-lightbox__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 48rem) {
  .pdp-lightbox__nav { width: 2.75rem; height: 2.75rem; }
  .pdp-lightbox__nav svg { width: 1.3rem; height: 1.3rem; }
  .pdp-lightbox__thumb { width: 3.5rem; height: 3.5rem; }
  .pdp-lightbox__strip { justify-content: flex-start; }   /* many thumbs → left-anchored scroll on mobile */
}

/* ── Fold rhythm: fewer, larger beats – more air between the stacked blocks ── */
.pdp-b .pdp-buybox { gap: 2rem; }   /* roomier section rhythm – was cramped at 1.6rem */
/* extra separation before the configurator, so product info reads apart from it */
.pdp-b .cfgb { margin-top: 0.15rem; }   /* match the title→rating gap so both block edges breathe equally */

/* ── Identity ── */
.pdp-b .pdp-eyebrow { font-size: 0.75rem; letter-spacing: 0.22em; }
.pdp-b .pdp-title {
  /* Responsive product title: 18 (mobile) → 24 (tablet) → 27 (desktop); weight 700, -0.02em. */
  font-size: 1.125rem; line-height: 1.25; letter-spacing: -0.02em; font-weight: 700;   /* 18px (mobile) */
  max-width: none; margin: 0; text-wrap: wrap;   /* greedy fill (not "pretty", which shortens lines) */
}
@media (min-width: 48rem) { .pdp-b .pdp-title { font-size: 1.5rem; } }   /* 24px – tablet */
@media (min-width: 62rem) { .pdp-b .pdp-title { font-size: 1.6875rem; } }   /* 27px – desktop (per request) */
/* Mobile: the multi-segment title wraps to ~3 lines — loosen the leading + tracking so it breathes instead of reading as a tight stack. */
@media (max-width: 47.9375rem) { .pdp-b .pdp-title { line-height: 1.4; letter-spacing: -0.01em; } }
.pdp-b .pdp-title .pdp-title__sep { color: var(--color-graphite-600); font-weight: 300; margin: 0 0.3em; }

/* Credential line – one calm row replaces two loud badges */
/* tighten the gap between the breadcrumb and the product title (hero top padding) */
.pdp-b .pdp-hero { padding-top: 1rem; padding-bottom: var(--sx-rhythm); }   /* bottom padding on the section rhythm so the hero→first-section gap matches the rest */
/* rating/share sits right under the title (the header's 2rem gap left it floating) */
.pdp-b .pdp-hero__head { gap: 0.6rem; }
.bx-cred { display: flex; align-items: center; flex-wrap: wrap; gap: 0.6rem 0.9rem; margin-top: 0.15rem; }
.bx-cred__rate { display: inline-flex; align-items: center; gap: 0.5rem; text-decoration: none; }
.bx-cred__rate .pdp-stars { color: var(--color-star); }
.bx-cred__rate .pdp-rate__count { font-size: 0.75rem; color: var(--color-graphite-600); }
.bx-cred__rate .pdp-rate__count b { color: var(--color-digital-black); font-weight: 700; }
.bx-cred__rate:hover .pdp-rate__count { color: var(--color-digital-black); }
.bx-cred__badge {
  display: inline-flex; align-items: center; text-align: center;
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--color-graphite-700); padding: 0.28rem 0.55rem; line-height: 1.15;
  border: 1px solid var(--color-graphite-200); border-radius: var(--radius-pill);
  background: var(--color-white);
}
.bx-cred__badge--hik { color: var(--text-muted); }
/* ── Share – plain teal text link (not a button) ── */
.bx-share {
  margin-left: auto; flex-shrink: 0; display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.25rem 0; border: 0; background: none; cursor: pointer; color: var(--color-teal);
  font-family: inherit; font-size: 0.875rem; font-weight: 700; letter-spacing: 0.01em;
}
.bx-share svg { width: 1.05rem; height: 1.05rem; }
.bx-share__t { line-height: 1; }
.bx-share:hover, .bx-share[aria-expanded="true"] { color: var(--color-teal-600); }
.bx-share:hover .bx-share__t { text-decoration: underline; text-underline-offset: 3px; }

/* ── Share popover – floating menu below the link ── */
.bx-share-wrap { position: relative; display: inline-flex; margin-left: auto; flex-shrink: 0; }
/* .bx-cred carries an entrance transform → its own stacking context, which traps
   the menu behind later siblings. Lift it above them while the menu is open. */
.bx-cred.is-sharing { position: relative; z-index: 60; }
.bx-share-menu { position: absolute; top: calc(100% + 0.5rem); right: 0; z-index: 1;
  width: 13.5rem; padding: 0.4rem; display: flex; flex-direction: column; gap: 0.1rem;
  background: var(--color-white); border: 1px solid var(--color-graphite-300); border-radius: var(--radius-lg);
  box-shadow: 0 0.9rem 1.6rem rgba(26,23,27,0.15), 0 0.2rem 0.5rem rgba(26,23,27,0.08);
  transform-origin: top right; animation: shareIn .16s cubic-bezier(.2,.8,.2,1); }
/* caret ties the window to its trigger – points up into the "Produkt teilen" link,
   sitting under the label so the popover reads as one unit with the link it belongs to */
.bx-share-menu::before { content: ""; position: absolute; top: -0.36rem; right: 1.15rem;
  width: 0.72rem; height: 0.72rem; background: var(--color-white);
  border-left: 1px solid var(--color-graphite-300); border-top: 1px solid var(--color-graphite-300);
  border-top-left-radius: 2px; transform: rotate(45deg); }
.bx-share-menu[hidden] { display: none; }
@keyframes shareIn { from { opacity: 0; transform: translateY(-0.3rem) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
.bx-share-menu__item { position: relative; display: flex; align-items: center; gap: 0.7rem; width: 100%;
  padding: 0.6rem 0.5rem; border: 0; background: none; border-radius: var(--radius); cursor: pointer;   /* 0.4rem menu pad + 0.5rem = 0.9rem, aligning icon & chevron with the header */
  font-family: inherit; font-size: 0.75rem; font-weight: 600; color: var(--color-digital-black);
  text-align: left; text-decoration: none; transition: background .14s ease, color .14s ease; }
.bx-share-menu__item:hover, .bx-share-menu__item:focus-visible { background: var(--color-teal-50); color: var(--color-teal); outline: none; }
.bx-share-menu__item svg { width: 1.1rem; height: 1.1rem; color: var(--color-graphite-500); flex: none; transition: color .14s ease; }
.bx-share-menu__item:hover svg, .bx-share-menu__item:focus-visible svg { color: var(--color-teal); }
/* trailing chevron – same colour as the leading icon (graphite-500 → teal on hover) */
.bx-share-menu__chev { margin-left: auto; width: 0.85rem !important; height: 0.85rem !important; }
.bx-share-menu__item.is-copied, .bx-share-menu__item.is-copied svg { color: var(--color-green); background: none; }
@media (prefers-reduced-motion: reduce) { .bx-share-menu { animation: none; } }
/* maximize the rating stars */
.bx-cred .pdp-stars svg { width: 1.4rem; height: 1.4rem; }
.bx-cred__rate .pdp-rate__count { font-size: 0.875rem; }

/* ── Media stage: no background, no frame – product floats on the page ── */
.pdp-b .pdp-media__stage {
  border-radius: 0;
  background: none;
  box-shadow: none;
  overflow: visible;   /* keep the product's soft shadow from being clipped */
}
.pdp-b .pdp-media__img { filter: none; }   /* image is an opaque white square – a shadow would outline it like a frame */
/* Media view toggle icons – optical sizing. The "Fotos" glyph is a dense outline
   (frame + sun + mountains) that fills its box corner-to-corner; the "3D" cube is
   a sparse hexagonal outline with empty corners, so it reads lighter and looks
   smaller at the same box size. Nudge the cube up ~12% so the two glyphs carry
   equal visual weight. */
.pdp-b .pdp-media__toggle button:last-child svg { width: 0.95rem; height: 0.95rem; }
/* flush the floating toggle to the media column's left edge so it lines up with the
   breadcrumb / page content above (base pdp.css insets it 0.75rem) */
.pdp-b .pdp-media__toggle { left: 0; }

/* ── View toggle ──────────────────────────────────────────────────────────────
   DESKTOP keeps ONE segmented control (the base white pill with Fotos + 3D joined as
   segments, selected = teal – see pdp.css); we only add life: the "3D" segment's cube
   turns once in 3D (rotateY + perspective) on load. The cube inherits its segment's
   colour (grey when idle, white when selected, teal on the mobile chip).
   MOBILE collapses the control to a single standalone chip – see the max-width:560px
   block. */
.pdp-b .pdp-media__toggle button:last-child svg {
  transform-origin: 50% 50%;
  animation: media3d-spin 1.3s ease-in-out;   /* one turn on load, then settles */
}
@keyframes media3d-spin {
  from { transform: perspective(80px) rotateY(0deg); }
  to   { transform: perspective(80px) rotateY(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .pdp-b .pdp-media__toggle button:last-child svg { animation: none; }
}
.pdp-b .pdp-thumbs button { width: 4.5rem; height: 4.5rem; border-radius: var(--radius); box-sizing: border-box; }
/* selection recolours & thickens the existing border to a clean 2px teal – same
   treatment as the colour swatches; border-box keeps the footprint identical */
.pdp-b .pdp-thumbs button[aria-current="true"] { border-width: 2px; border-color: var(--color-teal); box-shadow: none; }

/* Live engraving overlay on the hero media */
.pdp-b .pdp-media__engrave {
  position: absolute; left: 50%; bottom: 19%; transform: translateX(-50%);
  font-size: clamp(0.72rem, 1.5vw, 1rem); letter-spacing: 0.12em; font-weight: 600;
  color: var(--engrave-ink, rgba(20,22,25,0.66));
  padding: 0.15rem 0.6rem; border-radius: var(--radius-sm);
  pointer-events: none; white-space: nowrap; transition: opacity .25s ease, color .25s ease;
}
.pdp-b .pdp-media__engrave:empty { display: none; }

/* ── Key facts: brand · dimensions · article no. – minimal, iconless, no box
   (.pdp-b scope beats the base .pdp-specs dt/dd rules in pdp.css) ── */
.pdp-b .pdp-specs { display: grid; grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr)); gap: 0.8rem 1.5rem;
  align-items: start; margin: 0.15rem 0; padding: 0; border: 0; background: none; }
/* Three facts distributed across the row: brand hugs the left edge, dimensions
   centered, article-no. hugs the right edge (mobile re-flows to rows below). */
.pdp-b .pdp-specs__item { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; align-items: flex-start; text-align: left; }
.pdp-b .pdp-specs__item:nth-child(2) { align-items: center; text-align: center; }   /* Breite × Höhe – centered */
.pdp-b .pdp-specs__item:last-child { align-items: flex-end; text-align: right; }   /* Artikelnummer – right-aligned */
/* Engraved caption / confident value – labels borrow the brand eyebrow DNA
   (uppercase, tracked, tiny) so the facts read like a precision data-plate, not
   loose text. The caption recedes; the value carries the weight. */
.pdp-b .pdp-specs__label { margin: 0; font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--color-graphite-600); }   /* 11px engraved caption across breakpoints */
.pdp-b .pdp-specs__value { margin: 0; font-size: 1rem; font-weight: 700; color: var(--color-digital-black);
  font-variant-numeric: tabular-nums; }
/* minimal hairline dividers between the three key facts (desktop; mobile keeps its
   horizontal row dividers) – border centered in the gutter via even side padding */
@media (min-width: 561px) {
  .pdp-b .pdp-specs { column-gap: 0; }
  .pdp-b .pdp-specs__item { padding-inline: 1.5rem; }
  .pdp-b .pdp-specs__item:first-child { padding-left: 0; }
  .pdp-b .pdp-specs__item:last-child { padding-right: 0; }
  .pdp-b .pdp-specs__item + .pdp-specs__item { border-left: 1px solid var(--color-graphite-200); }
}
/* labels held at a consistent 12px muted signpost across breakpoints (values stay a fixed 16px, weight 700) */

/* ── AUSFÜHRUNG · Farbe (Variante) ── */
.bx-color { display: flex; flex-direction: column; gap: 0.7rem; }
.bx-color__head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.bx-color__label { font-size: 0.875rem; color: var(--color-graphite-700); }
.bx-color__label b { color: var(--color-digital-black); font-weight: 700; }
.bx-color__art {
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em; color: var(--text-muted);
  background: var(--color-paper); border: 1px solid var(--color-graphite-200);
  padding: 0.2rem 0.5rem; border-radius: var(--radius); font-variant-numeric: tabular-nums;
}
.bx-color__art b { color: var(--color-digital-black); }
/* Colour variants as a labelled grid – every name is visible at once (mobile has
   no hover). One single row of 8, so the swatches scale down to fit. */
.bx-swatches { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 0.45rem; overflow: visible; }
.pdp-b .pdp-swatch { width: auto; height: auto; padding: 0; border: 0; background: none; border-radius: 0;
  overflow: visible; box-shadow: none; display: flex; flex-direction: column; align-items: center; gap: 0.3rem; transition: none; }
/* square, no grey fill, no frame border – image covers edge-to-edge */
.pdp-b .pdp-swatch img { width: 100%; height: auto; aspect-ratio: 1; object-fit: cover; padding: 0;
  background: var(--color-white); border: 1px solid var(--color-graphite-300); border-radius: var(--radius); box-sizing: border-box; }
/* selection shown by a clean OUTER teal ring – doesn't cut into the image, keeps
   every frame identical in size (outline adds no layout box) */
/* selection recolours the existing border to the brand teal – no extra ring */
.pdp-b .pdp-swatch:hover img { border-color: var(--color-graphite-400); }
.pdp-b .pdp-swatch[aria-pressed="true"] img { border-width: 2px; border-color: var(--color-teal); }

/* ── Selected swatch · high-visibility state (v2 · v3 · v4) ──────────────────
   A lone 2px teal border read poorly on dark finishes (Eisenglimmer, Tiefschwarz).
   The teal border below is made authoritative so it reliably reads as chosen. The
   filled check badge is an EXTRA cue reserved for v4's material swatches only (they
   have no product photo, so the badge helps confirm the pick); v2/v3 keep the plain
   teal border. v1 stays as-is. */
.pdp-b .pdp-swatch { position: relative; }
.flow-b .pdp-swatch[aria-pressed="true"] img,
.flow-c .pdp-swatch[aria-pressed="true"] img,
.flow-d .pdp-swatch[aria-pressed="true"] {
  border-width: 2px; border-color: var(--color-teal);   /* teal inner edge (authoritative – wins the cascade) */
}

.pdp-swatch__check {
  position: absolute; top: 0.3rem; right: 0.3rem; z-index: 3;
  width: 1rem; height: 1rem; display: none; place-items: center;
  background: var(--color-teal); color: var(--color-white); border-radius: 50%;
  box-shadow: 0 0 0 2px var(--color-white), 0 1px 3px rgba(26,23,27,0.35);
  animation: swatch-check-in .3s cubic-bezier(.22,1,.36,1);
}
.pdp-swatch__check svg { width: 0.66rem; height: 0.66rem; }
.flow-d .pdp-swatch[aria-pressed="true"] .pdp-swatch__check { display: grid; }   /* v4 material swatches only */
@keyframes swatch-check-in { 0% { transform: scale(0); opacity: 0; } 60% { transform: scale(1.15); opacity: 1; } 100% { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .pdp-swatch__check { animation: none; } }

/* ============================================================
   V4 (flow-d) – material-texture swatches. Every finish renders its actual colour +
   surface texture (a square, pre-cropped WebP) instead of the small product photo.
   All 8 finishes are covered. Pure visual skin – selection, magic-line and touch
   behaviour are unchanged. Hidden unless ?flow=d.
   ============================================================ */
.flow-d .pdp-swatch {
  aspect-ratio: 1; width: 100%; box-sizing: border-box; overflow: hidden;
  border: 1px solid var(--color-graphite-300); border-radius: var(--radius);
  background-repeat: no-repeat; background-size: cover; background-position: center;
}
.flow-d .pdp-swatch img { display: none; }
.flow-d .pdp-swatch:hover { border-color: var(--color-graphite-400); }
.flow-d .pdp-swatch[aria-pressed="true"] { border-width: 2px; border-color: var(--color-teal); }
/* square material swatches – each webp is pre-cropped to the plate surface, so cover+center is enough */
.flow-d .pdp-swatch[data-article="31101"] { background-image: url("assets/materials/anthrazit.webp"); }      /* Anthrazit */
.flow-d .pdp-swatch[data-article="31102"] { background-image: url("assets/materials/verkehrsweiss.webp"); }   /* Verkehrsweiß */
.flow-d .pdp-swatch[data-article="31103"] { background-image: url("assets/materials/graualuminium.webp"); }   /* Graualuminium */
.flow-d .pdp-swatch[data-article="31104"] { background-image: url("assets/materials/eisenglimmer.webp"); }    /* Eisenglimmer */
.flow-d .pdp-swatch[data-article="31105"] { background-image: url("assets/materials/tiefschwarz.webp"); }     /* Tiefschwarz */
.flow-d .pdp-swatch[data-article="31106"] { background-image: url("assets/materials/edelstahl.webp"); }       /* Edelstahl */
.flow-d .pdp-swatch[data-article="31107"] { background-image: url("assets/materials/linen-tex-black.webp"); } /* Linen Tex Black */
.flow-d .pdp-swatch[data-article="31108"] { background-image: url("assets/materials/wunschfarbe.webp"); }     /* Wunschfarbe – RAL fan */

/* v4 opener: the labelled-list field (shared markup, styled in the flow-c block) sits
   UNDER the swatch grid here – not above as in v3. .bx-color is a flex column, so we
   reorder its children with `order` and leave the shared DOM untouched.
   Visible order: head · swatches · list-field · RAL picker · note. */
.flow-d .bx-color__head { order: 0; }
.flow-d .pdp-swatches   { order: 1; }
.flow-d .bx-listfield   { order: 2; }
.flow-d #ralPick        { order: 3; }
.flow-d .bx-color__note { order: 4; }

.bx-color__note { font-size: 0.75rem; line-height: 1.5; color: var(--text-muted); margin: 0; max-width: 46ch; }
.bx-color__note b { color: var(--color-graphite-700); font-weight: 600; }

/* colour-preview dot in the "Farbe – …" label (shows the exact RAL hex once picked) */
.bx-color__dot { display: inline-block; width: 0.85rem; height: 0.85rem; border-radius: 50%;
  border: 1px solid rgba(0,0,0,0.18); vertical-align: baseline; margin-right: 0.1rem; }
/* the explicit display above outranks the UA [hidden] rule – restore hiding so the dot
   only appears once a Wunschfarbe RAL tone is picked (not for standard finishes) */
.bx-color__dot[hidden] { display: none; }

/* ── WUNSCHFARBE · premium RAL picker ─────────────────────────────────
   Collapsed: a combobox trigger that previews the chosen tone.
   Expanded:  a card with search + result count, colour-family filter, swatch grid. */
.ralpick { display: none; margin-top: 0.5rem; }
.ralpick.is-shown { display: block; }
@keyframes ralpick-shake { 0%,100%{transform:none} 20%{transform:translateX(-5px)} 40%{transform:translateX(5px)} 60%{transform:translateX(-3px)} 80%{transform:translateX(3px)} }

/* collapsed trigger – combobox */
.ralpick__trigger { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  padding: 0.5rem 0.75rem; background: var(--color-white); cursor: pointer; text-align: left; font: inherit;
  border: 1px solid var(--color-graphite-300); border-radius: var(--radius-lg);
  transition: border-color .26s ease, box-shadow .26s ease, border-radius .26s ease; }
.ralpick__trigger:hover { border-color: var(--color-graphite-400); }
.ralpick__trigger:focus-visible { outline: none; border-color: var(--color-teal); box-shadow: 0 0 0 3px rgba(1,82,83,0.12); }
/* open: the trigger becomes the header of one connected unit – teal border, squared
   bottom, no separate glow, so it fuses seamlessly with the panel below */
.ralpick.is-open .ralpick__trigger { border-color: var(--color-teal); box-shadow: none;
  border-bottom-color: transparent; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.ralpick__trighead { display: flex; align-items: center; gap: 0.65rem; min-width: 0; }
.ralpick__swatch { flex: none; width: 2.25rem; height: 2.25rem; border-radius: calc(var(--radius-lg) - 0.15rem);
  display: grid; place-items: center; box-shadow: inset 0 0 0 1px rgba(0,0,0,0.12); }
.ralpick__swatch--empty { display: none; }
.ralpick__swatch svg { width: 1.3rem; height: 1.3rem; }
.ralpick__trigtext { display: flex; flex-direction: column; gap: 0.05rem; min-width: 0; }
.ralpick__triglabel { font-size: 0.875rem; font-weight: 700; color: var(--color-digital-black); line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ralpick__trigsub { font-size: 0.75rem; color: var(--color-graphite-600); line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ralpick__chev { flex: none; width: 1.25rem; height: 1.25rem; color: var(--color-graphite-500);
  transition: transform .22s ease, color .18s ease; }
.ralpick__trigger:hover .ralpick__chev { color: var(--color-teal); }
.ralpick.is-open .ralpick__chev { transform: rotate(180deg); color: var(--color-teal); }
.ralpick.is-invalid .ralpick__trigger { animation: ralpick-shake .4s ease; border-color: var(--color-red); box-shadow: 0 0 0 3px rgba(212,41,36,0.14); }

/* expanded panel – smooth height expand/collapse via grid-template-rows (0fr ↔ 1fr):
   animates the real content height with no JS measuring, joined seamlessly under the
   trigger as one elevated unit. */
.ralpick__panel { display: grid; grid-template-rows: 0fr; opacity: 0; margin-top: 0;
  background: var(--color-white); border: 1px solid transparent; border-top: 0;
  border-radius: 0 0 var(--radius-lg) var(--radius-lg); box-shadow: none; will-change: grid-template-rows;
  transition: grid-template-rows .32s cubic-bezier(.4,0,.2,1), opacity .22s ease .02s,
              border-color .26s ease, box-shadow .32s ease; }
.ralpick__panelinner { overflow: hidden; min-height: 0; }
.ralpick__panelpad { padding: 0.85rem; }
.ralpick.is-open .ralpick__panel { grid-template-rows: 1fr; opacity: 1;
  border-color: var(--color-teal); box-shadow: var(--shadow-soft); }
@media (prefers-reduced-motion: reduce) {
  .ralpick__panel, .ralpick__trigger, .ralpick__chev { transition: none; }
}

/* search */
.ralpick__search { position: relative; display: flex; align-items: center; gap: 0.5rem; height: 2.6rem;
  padding: 0 0.45rem 0 0.75rem; background: var(--color-paper);
  border: 1px solid var(--color-graphite-200); border-radius: var(--radius); transition: border-color .15s ease, box-shadow .15s ease, background .15s ease; }
.ralpick__search:focus-within { border-color: var(--color-teal); background: var(--color-white); box-shadow: 0 0 0 3px rgba(1,82,83,0.10); }
.ralpick__searchicon { flex: none; width: 1.05rem; height: 1.05rem; color: var(--color-graphite-500); }
.ralpick__input { flex: 1 1 auto; min-width: 0; height: 100%; border: 0; background: none; outline: none;
  font: inherit; font-size: 1rem; color: var(--color-digital-black); padding: 0; }   /* 16px – anything smaller makes iOS auto-zoom (and shift the layout) on focus */
.ralpick__input::-webkit-search-cancel-button { display: none; }
.ralpick__count { flex: none; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.01em; color: var(--color-graphite-600);
  padding: 0.15rem 0.5rem; background: var(--color-white); border: 1px solid var(--color-graphite-200);
  border-radius: var(--radius-pill); white-space: nowrap; }
.ralpick__clear { flex: none; display: grid; place-items: center; width: 1.75rem; height: 1.75rem;
  border: 0; background: none; color: var(--color-graphite-500); cursor: pointer; border-radius: var(--radius); }
.ralpick__clear:hover { color: var(--color-graphite-800); background: var(--color-graphite-100); }
.ralpick__clear svg { width: 1rem; height: 1rem; }
/* the class display above outranks the UA [hidden] rule – restore hiding so the clear
   (×) only shows once text is entered, matching the page's general search bar */
.ralpick__clear[hidden] { display: none; }

/* colour-family filter – minimal borderless chips; quiet grey hover, soft teal-tint active */
/* strip + flanking scroll chevrons */
.ralpick__famsbar { display: flex; align-items: center; gap: 0.2rem; margin: 0.8rem 0 0.7rem; }
.ralpick__famnav { flex: none; display: none; place-items: center; width: 1.85rem; height: 1.85rem; padding: 0;
  color: var(--color-graphite-600); background: var(--color-white); cursor: pointer; box-shadow: none;
  border: 1px solid var(--color-graphite-200); border-radius: var(--radius);
  transition: color .15s ease, background .15s ease, border-color .15s ease; }
.ralpick__famnav.is-shown { display: grid; }              /* revealed only when the strip overflows that way */
.ralpick__famnav:hover { color: var(--color-white); background: var(--color-teal); border-color: var(--color-teal); }
.ralpick__famnav svg { width: 1rem; height: 1rem; }
.ralpick__fams { flex: 1 1 auto; min-width: 0; display: flex; gap: 0.35rem; padding: 0.15rem 0.1rem 0.4rem; overflow-x: auto;
  overscroll-behavior-x: contain; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
/* no edge fade – the flanking chevrons are the scroll affordance, so the strip stays crisp */
.ralpick__fams::-webkit-scrollbar { display: none; }
/* desktop: draggable strip – grab cursor + no text selection while dragging */
@media (hover: hover) {
  .ralpick__fams { cursor: grab; }
  .ralpick__fams.is-dragging { cursor: grabbing; user-select: none; }
  .ralpick__fams.is-dragging .ralpick__fam { cursor: grabbing; }
}
/* resting: defined outlined chip; hover: crisper edge; active: on-brand teal-tint fill
   + teal ring + a soft teal halo on the dot – a clear, premium selected state */
.ralpick__fam { flex: none; display: inline-flex; align-items: center; gap: 0.45rem; padding: 0.38rem 0.78rem;
  font: inherit; font-size: 0.75rem; font-weight: 600; letter-spacing: -0.005em; color: var(--color-graphite-700);
  cursor: pointer; white-space: nowrap; background: var(--color-white);
  border: 1px solid var(--color-graphite-200); border-radius: var(--radius-pill);
  transition: color .15s ease, background .15s ease, border-color .15s ease, box-shadow .15s ease; }
.ralpick__fam:hover { color: var(--color-digital-black); border-color: var(--color-graphite-400); }
.ralpick__fam.is-active { color: var(--color-teal); font-weight: 700; background: rgba(1,82,83,0.07);
  border-color: rgba(1,82,83,0.32); box-shadow: none; }   /* border + tint carry it – no drop shadow */
.ralpick__fam.is-active .ralpick__famdot { box-shadow: inset 0 0 0 1px rgba(0,0,0,0.18), 0 0 0 2px rgba(1,82,83,0.16); }
.ralpick__famdot { flex: none; width: 0.58rem; height: 0.58rem; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0,0,0,0.18); }

/* paged slider – replaces the internal scroll so there is no nested scrollbar to
   conflict with the page. Swatches page horizontally (Prev/Next, swipe); vertical
   gestures fall through to the page (touch-action: pan-y). */
.ralpick__viewport { overflow: hidden; height: 20rem; touch-action: pan-y; }
.ralpick__track { display: flex; height: 100%; will-change: transform;
  transition: transform .34s cubic-bezier(.4,0,.2,1); }
.ralpick__page { flex: 0 0 100%; min-width: 0; display: grid; gap: 0.5rem; align-content: start;
  padding: 0.25rem; box-sizing: border-box; }
/* pager – design-system square arrows + page counter */
.ralpick__pager { display: flex; align-items: center; justify-content: center; gap: 0.9rem; margin-top: 0.7rem; }
.ralpick__pager[hidden] { display: none; }
/* pager arrows – same design-system slider arrow as the image lightbox (square var(--radius),
   1px outline, inverts on hover), sized to match; the outline/fill use teal here since the
   picker sits on a light panel (the lightbox uses white on its dark backdrop) */
.ralpick__pagebtn { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; cursor: pointer;
  color: var(--color-graphite-700); background: transparent;
  border: 1px solid var(--color-graphite-300); border-radius: var(--radius);
  transition: background .15s ease, border-color .15s ease, color .15s ease; }
.ralpick__pagebtn:hover:not(:disabled) { background: var(--color-teal); border-color: var(--color-teal); color: var(--color-white); }
.ralpick__pagebtn:disabled { opacity: 0.4; cursor: default; }
.ralpick__pagebtn svg { width: 1.25rem; height: 1.25rem; }
.ralpick__pageinfo { font-size: 0.75rem; font-weight: 600; color: var(--color-graphite-600); min-width: 3.75rem; text-align: center; }

.ral-chip { position: relative; display: flex; flex-direction: column; justify-content: flex-end; gap: 0.1rem;
  height: 4.5rem; padding: 0.45rem 0.55rem; text-align: left; cursor: pointer; background: var(--chip); border: 0;
  border-radius: var(--radius); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.10);
  transition: transform .16s ease, box-shadow .16s ease; }
.ral-chip:hover { transform: translateY(-2px); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.10), 0 6px 14px -6px rgba(0,0,0,0.45); }
.ral-chip:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--color-white), inset 0 0 0 4px var(--color-teal); }
/* selected: brand-teal border on the tile's rounded edge (so it carries the default
   radius and can't be clipped by the picker's scroll container), a white separator ring
   between it and the tile's existing palette hairline so the teal stays legible/accessible
   on ANY RAL tone (framed by the light panel gap outside and the white ring inside) */
.ral-chip.is-selected { box-shadow:
  inset 0 0 0 2px var(--color-teal),
  inset 0 0 0 4px var(--color-white),
  inset 0 0 0 5px rgba(0,0,0,0.10); }
.ral-chip__code { font-size: 0.75rem; font-weight: 800; line-height: 1.1; }
.ral-chip__name { font-size: 0.75rem; line-height: 1.15; opacity: 0.9; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }

.ralpick__empty { display: none; margin: 0.6rem 0 0; padding: 1.25rem 1rem; text-align: center; font-size: 0.75rem;
  color: var(--color-graphite-600); background: var(--color-paper); border-radius: var(--radius); }
.ralpick__empty:not([hidden]) { display: block; }

/* ── KONFIGURATION panel ── */
.cfgb { display: flex; flex-direction: column; gap: 0.9rem; padding: 1.35rem; border-radius: var(--radius-lg);
  background: var(--color-paper); border: 1px solid var(--color-graphite-200); }

/* ── Config lock – until a colour (= article) is chosen the configurator is hidden
   entirely (colour determines the options; nothing valid to configure yet). This
   also keeps the price + CTA visible on entry instead of below a tall open panel. ── */
.cfgb.is-locked { display: none; }

/* Colour requirement – a single crisp red ring that expands once and fades. Visible
   but calm: no shake, no per-swatch motion. The persistent "Bitte Farbe wählen" label
   carries the message. Re-triggered on every attempt by JS (remove→reflow→add). */
.bx-swatches { border-radius: var(--radius-lg); }
.bx-swatches.is-invalid { animation: bx-swatch-alert .7s ease-out both; }
@keyframes bx-swatch-alert {
  0%   { box-shadow: 0 0 0 0 rgba(212,41,36,0.5); }
  100% { box-shadow: 0 0 0 8px rgba(212,41,36,0); }
}
@media (prefers-reduced-motion: reduce) {
  .bx-swatches.is-invalid { animation: none !important; box-shadow: 0 0 0 2px var(--color-red); }
}

/* ── Progress spine – premium "configuration meter", pinned to the top through the flow ── */
.cfgb-bar { display: flex; flex-direction: column; gap: 0.85rem;
  position: sticky; top: 6.5rem; z-index: 6;
  margin: -1.35rem -1.35rem 0; padding: 1.15rem 1.35rem 0.9rem;
  background: var(--color-paper); border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  border-bottom: 1px solid var(--color-graphite-200); box-shadow: 0 8px 14px -10px rgba(10,20,20,0.18); }
.cfgb-bar__row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.cfgb-bar__title { font-size: 1rem; font-weight: 700; letter-spacing: -0.015em; color: var(--color-digital-black);
  display: inline-flex; align-items: center; gap: 0.5rem; }
.cfgb-bar__count { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.01em; color: var(--color-teal);
  font-variant-numeric: tabular-nums; white-space: nowrap; transition: color .3s ease; }
.cfgb-bar__count b { font-size: 0.875rem; }
.cfgb-bar.is-ready .cfgb-bar__count { color: var(--color-green); }

/* (The old icon-and-line stepper styles lived here. That component is retired
   – .cfgb-bar is display:none – and its rules leaked label/node colors into
   the dock ribbon, which reuses the same class names. Deleted, not overridden.) */

/* ── Step cards (progressive disclosure, refined) ── */
.stepr { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.stepr__item { position: relative; background: var(--color-white); border: 1px solid var(--color-graphite-200);
  border-radius: var(--radius); transition: border-color .25s ease, box-shadow .25s ease; }
.stepr__item.is-active { border-color: var(--color-teal); box-shadow: 0 0.5rem 1.5rem rgba(1,82,83,0.08); }
.stepr__item.is-done { border-color: var(--color-graphite-200); }
.stepr__head { width: 100%; display: flex; align-items: center; gap: 0.8rem; background: none; border: 0;
  padding: 0.95rem 1rem; cursor: pointer; font-family: inherit; text-align: left; }
/* state node: empty ring → teal ring (active) → filled teal + check (done) */
.stepr__node { width: 1.85rem; height: 1.85rem; flex-shrink: 0; border-radius: 34%; border: 0;
  background: var(--color-graphite-100); display: grid; place-items: center;
  transition: background .25s ease, box-shadow .25s ease, color .25s ease; }
.stepr__node > * { grid-area: 1 / 1; }
.stepr__node b { display: none; }
.stepr__num { font-size: 0.75rem; font-weight: 800; color: var(--text-muted); line-height: 1; transition: color .25s ease; }
.stepr__check { width: 0.95rem; height: 0.95rem; display: none; color: var(--color-white); }
.stepr__item.is-active .stepr__node { background: var(--color-teal-50); box-shadow: 0 0 0 3px rgba(1,82,83,0.12); }
.stepr__item.is-active .stepr__num { color: var(--color-teal); }
.stepr__item.is-done .stepr__node { background: var(--color-teal); }
.stepr__item.is-done .stepr__num { display: none; }
.stepr__item.is-done .stepr__check { display: block; }
/* validation flash */
.stepr__item.is-flash { animation: cfgb-flash .6s ease; }
@keyframes cfgb-flash { 0%,100%{box-shadow:0 0.5rem 1.5rem rgba(1,82,83,0.08)} 30%{box-shadow:0 0 0 3px rgba(1,82,83,0.28)} }
.stepr__titles { display: flex; flex-direction: column; gap: 0.12rem; min-width: 0; flex: 1; }
.stepr__title { font-size: 0.875rem; font-weight: 700; color: var(--color-digital-black); display: flex; align-items: center; gap: 0.5rem; }
.stepr__pick { font-size: 0.75rem; color: var(--color-graphite-600); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stepr__item.is-active .stepr__pick { display: none; }
.stepr__item:not(.is-done):not(.is-active) .stepr__pick { color: var(--color-teal); font-weight: 600; }
.stepr__edit { font-size: 0.75rem; font-weight: 700; color: var(--color-teal); flex-shrink: 0; display: none; }
.stepr__item.is-done .stepr__edit { display: inline; }
.stepr__item.is-active .stepr__edit { display: none; }
.stepr__chev { width: 1.1rem; height: 1.1rem; color: var(--color-graphite-400); flex-shrink: 0;
  transition: transform .35s cubic-bezier(.2,.7,.2,1), color .2s ease; }
.stepr__item.is-active .stepr__chev { transform: rotate(180deg); color: var(--color-teal); }
.stepr__item.is-done .stepr__chev { display: none; }
/* body height morph */
.stepr__body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .45s cubic-bezier(.2,.7,.2,1); }
.stepr__item.is-active .stepr__body { grid-template-rows: 1fr; }
.stepr__inner { overflow: hidden; min-height: 0; }
.stepr__pad { padding: 0.1rem 1rem 1.2rem; display: flex; flex-direction: column; gap: 1rem; }
/* staggered reveal */
.stepr__item.is-active .stepr__pad > * { opacity: 0; transform: translateY(0.5rem); animation: cfgb-rise .5s cubic-bezier(.2,.7,.2,1) forwards; }
.stepr__item.is-active .stepr__pad > *:nth-child(1) { animation-delay: .05s; }
.stepr__item.is-active .stepr__pad > *:nth-child(2) { animation-delay: .13s; }
.stepr__item.is-active .stepr__pad > *:nth-child(3) { animation-delay: .21s; }
@keyframes cfgb-rise { to { opacity: 1; transform: none; } }

/* Gravur segmented control */
.cfgb-seg { display: inline-flex; background: var(--color-paper); border: 1px solid var(--color-graphite-200);
  border-radius: var(--radius); padding: 0.2rem; gap: 0.2rem; }
.cfgb-seg button { border: 0; background: none; cursor: pointer; font-family: inherit; font-size: 0.875rem; font-weight: 600;
  color: var(--color-graphite-700); padding: 0.5rem 1rem; border-radius: calc(var(--radius) - 0.0625rem); transition: background .18s, color .18s; }
.cfgb-seg button[aria-pressed="true"] { background: var(--color-white); color: var(--color-teal); box-shadow: var(--shadow-soft); }
.cfgb-field { display: none; flex-direction: column; gap: 0.9rem; }
.cfgb-field.is-shown { display: flex; }

/* Required / optional sub-groups inside a step */
.cfgb-group { display: flex; flex-direction: column; gap: 0.6rem; }
.cfgb-group__label { display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.75rem; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); }
.cfgb-group__req { font-size: 0.5625rem; font-weight: 800; letter-spacing: 0.1em; color: var(--color-teal);
  background: var(--color-teal-50); border-radius: var(--radius-pill); padding: 0.12rem 0.45rem; }
.cfgb-group__tag { font-size: 0.5625rem; font-weight: 800; letter-spacing: 0.1em; color: var(--text-muted);
  background: var(--color-graphite-100); border-radius: var(--radius-pill); padding: 0.12rem 0.45rem; }
/* optional add-ons separated from the required set by a hairline */
.cfgb-group--opt { margin-top: 0.5rem; padding-top: 1.05rem; border-top: 1px solid var(--color-graphite-200); }

/* ── BUY BLOCK ── */
.cfgb-checkout { display: flex; flex-direction: column; gap: 1.6rem;
  margin-top: -0.4rem; }   /* trim the 2rem buybox gap above so it matches the 1.6rem gap below the accordion */
.cfgb-checkout__row { display: flex; align-items: center; gap: 1.1rem; }
.cfgb-total { display: flex; flex-direction: column; flex-shrink: 0; gap: 0.1rem; }
.cfgb-total__label { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); }
.cfgb-total__amount { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.025em; color: var(--color-digital-black); font-variant-numeric: tabular-nums; }
.cfgb-total__amount.is-bump,
.pdp-price__amount.is-bump { animation: cfg-bump .4s ease; }
@keyframes cfg-bump { 0%{transform:none} 30%{transform:translateY(-2px) scale(1.04)} 100%{transform:none} }

/* tighten the big price number's line box so the block's line spacing reads
   evenly (default 1.5 line-height added ~8px leading above/below the amount,
   making its neighbouring gaps look larger than the rest) */
.pdp-b .pdp-price { gap: 0.45rem; }
.pdp-b .pdp-price__row { line-height: 1.05; display: flex; align-items: baseline; gap: 0.4rem; }
.pdp-b .pdp-price__amount { line-height: 1.05; }

/* "ab" (starting-at) prefix – shown next to the price before a colour is chosen */
.pdp-price__from { font-size: 1rem; font-weight: 600; color: var(--color-graphite-600); }
.sheet__pricefrom { font-size: 0.75rem; font-weight: 600; color: var(--color-graphite-600); }
/* tight line box on the label too, so the gap below the accordion isn't inflated
   by leading – keeps the block's three outer gaps visually identical */
.pdp-b .pdp-price .cfgb-price__label { line-height: 1; }

/* "Preis wie konfiguriert" price line */
.cfgb-price { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.15rem 0.7rem; }
.cfgb-price__label { flex-basis: 100%; font-size: 0.8125rem; font-weight: 700; letter-spacing: normal; text-transform: none; color: var(--color-graphite-600); }
.cfgb-price__meta { font-size: 0.75rem; color: var(--color-graphite-600); }
.cfgb-price__meta a { color: var(--color-teal); text-decoration: underline; }

/* ── Lead price block ── a plain (no card) left-aligned block fixed above the swatches,
   shown both before and after colour. Sized to hold its own next to the swatches. */
.pdp-price--lead { display: flex; flex-direction: column; align-items: flex-start; text-align: left;
  gap: 0.3rem; margin-top: -0.3rem; }
.pdp-price--lead .pdp-price__amount { font-size: 2rem; letter-spacing: -0.025em; line-height: 1.05; }
.pdp-price--lead .cfgb-price__label { font-size: 0.8125rem; letter-spacing: normal; }
.pdp-price--lead .pdp-price__meta { font-size: 0.875rem; }
.pdp-price--lead .pdp-avail__status { font-size: 0.875rem; }

/* ── Angebot (offer) indicator ─────────────────────────────────────────────
   A minimal, premium sale cue for the price panel. Metzler Rot is the brand's
   designated sale/discount colour, used sparingly: a tinted pill + a solid-red
   −% chip (the number is the pre-attentive hook), the struck-through original
   price inline, and a quiet validity line. No starburst, no shouting. */
/* Angebot – ONE reusable sale badge: a single solid-red unit (eye-catching) carrying the
   discount AND the validity date, modernised with squared corners and a white hairline
   dividing the two. Self-contained → drop it into any page/surface (price panel, product
   card, set summary). Only the price-panel context tucks it into the top-right corner on
   desktop; on mobile it flows at the top of the block. */
.pdp-offer { display: inline-flex; align-items: center; gap: 0.5rem; align-self: flex-start; margin-bottom: 0.15rem;
  padding: 0.32rem 0.62rem; background: var(--color-red); color: var(--color-white);
  border-radius: var(--radius); font-size: 0.75rem; line-height: 1.1; letter-spacing: 0.01em; white-space: nowrap; }
.pdp-offer__clock { width: 0.85rem; height: 0.85rem; flex: none; }
.pdp-offer__pct { font-weight: 800; font-size: 0.8125rem; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.pdp-offer__dur { font-weight: 500; font-size: 0.75rem; opacity: 0.92;
  padding-left: 0.5rem; border-left: 1px solid rgba(255, 255, 255, 0.35); }
@media (min-width: 561px) {
  .pdp-price--lead .pdp-offer { position: absolute; top: 1rem; right: 1.15rem; z-index: 1; align-self: auto; margin: 0; }
}

/* current price + struck original share the row */
.pdp-price--lead .pdp-price__row { flex-wrap: wrap; }
.pdp-price__was { font-size: 1.125rem; font-weight: 600; color: var(--color-graphite-500);
  text-decoration: line-through; text-decoration-thickness: 1px; font-variant-numeric: tabular-nums; }
/* In-stock status carries a small dot – a pre-attentive cue the eye reads as
   "available" before it reads the words. Uses currentColor so dot = text green. */
.pdp-b .pdp-avail__status { display: inline-flex; align-items: center; gap: 0.45rem; }
.pdp-b .pdp-avail__status::before { content: ""; width: 0.5rem; height: 0.5rem; flex: none;
  border-radius: 50%; background: currentColor; }

/* ── Offer panel ──────────────────────────────────────────────────────────
   The commercial decision (price · tax · shipping · availability) is the fold's
   single focal point. It borrows Metzler's own signature panel language – the
   teal left-accent bar + white→paper gradient used on the brand's FAQ/config
   surfaces – so it reads as premium and unmistakably on-brand, not a grey box. */
.pdp-b .pdp-price--lead {
  position: relative; overflow: hidden;
  gap: 0.45rem; margin-top: 0;
  padding: 1.1rem 1.25rem 1.15rem 1.5rem;
  background: var(--color-paper);
  border: 1px solid var(--color-graphite-200);
  border-radius: var(--radius-lg);
}
/* signature teal accent bar – the brand's "this is the important thing" marker */
.pdp-b .pdp-price--lead::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 0.1875rem;
  background: var(--color-teal);
}
/* Price caption in the brand eyebrow voice (teal · uppercase · tracked) – labels
   the panel so the number reads as a deliberate, configured price. Gated on
   :not([hidden]) so the JS reveal (hidden = !finish) still governs it: the "ab"
   starting price shows label-less, "Preis wie konfiguriert" appears once a colour
   is chosen. */
.pdp-b .pdp-price--lead .cfgb-price__label:not([hidden]) {
  display: block; margin: 0 0 0.05rem; line-height: 1.3;
  font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.15em;
  text-transform: uppercase; color: var(--color-teal);
}
/* internal hairline separates "what it costs" (price · tax · shipping) from
   "when you get it" (availability). The row is a flex line: delivery status on
   the left, the EU energy-class badge right-aligned – so it fills the space that
   would otherwise sit blank, and the badge lives in the price panel's flow. */
.pdp-b .pdp-price--lead .pdp-avail {
  width: 100%; margin-top: 0.15rem; padding-top: 0.7rem;
  border-top: 1px solid var(--color-graphite-200);
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
}

/* ── EU-Energielabel ─────────────────────────────────────────────────────────
   Official compact class badge (G_Left.svg) shown in the vicinity of the price
   (VO (EU) 2019/2015), in-flow on the availability row and linking to the
   Produktdatenblatt. No floating panel – the badge itself carries class + scale. */
.pdp-b .pdp-nrg {
  flex: none; display: inline-flex; line-height: 0; border-radius: var(--radius-sm);
  transition: transform .12s ease;
}
.pdp-b .pdp-nrg:hover { transform: translateY(-1px); }
.pdp-b .pdp-nrg:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 3px; }
.pdp-b .pdp-nrg__arrow { display: block; width: auto; height: 1.6rem; }

/* Preisdetails & Menge accordion lives in the checkout now (after the config); hide it
   until a colour is chosen – nothing to detail yet */
#bAcc { display: none; }                              /* hidden until a paid item is added */
.cfgb-checkout.is-priced #bAcc { display: block; }    /* revealed on the first surcharge */

/* Delivery – two-column spec table: [icon + label] │ [value].
   Rows divided by hairlines, columns split by a vertical rule (label ~40%). */
.bx-delivery { display: flex; flex-direction: column;
  border: 1px solid var(--color-graphite-200); border-radius: var(--radius-lg);
  background: var(--color-white); overflow: hidden; box-shadow: 0 1px 2px rgba(26,23,27,0.05); }
.bx-delivery__row { display: grid; grid-template-columns: minmax(7.5rem, 0.42fr) 1fr; align-items: stretch; }
.bx-delivery__row + .bx-delivery__row { border-top: 1px solid var(--color-graphite-200); }
.bx-delivery__key { display: flex; align-items: center; gap: 0.5rem; padding: 0.75rem 0.9rem;
  font-size: 0.875rem; font-weight: 700; color: var(--color-digital-black); }
.bx-delivery__key svg { width: 1.2rem; height: 1.2rem; flex: none; color: var(--color-graphite-600); }
.bx-delivery__val { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem;
  padding: 0.75rem 0.95rem; border-left: 1px solid var(--color-graphite-200);
  font-size: 0.875rem; color: var(--color-graphite-700); min-width: 0; }
.bx-delivery__val b, .bx-delivery__val .ph { font-weight: 700; color: var(--color-digital-black); }
.bx-delivery__free { color: var(--color-green) !important; }
.bx-delivery__details { color: var(--color-teal); font-weight: 600; text-decoration: underline;
  text-underline-offset: 2px; white-space: nowrap; }
.bx-delivery__details:hover { color: var(--color-teal-600); }

/* Primary action – always live (validate on click, never lock) */
.cfgb-cta { width: 100%; gap: 0.55rem; background: var(--color-teal); box-shadow: 0 0.375rem 0.9rem rgba(1,82,83,0.15); }
.cfgb-cta:hover { background: var(--color-teal-hover); }

/* quantity box sits beside the CTA, matched to its height */
.cfgb-buyrow { display: flex; align-items: stretch; gap: 0.6rem; }
.cfgb-buyrow .cfgb-cta { flex: 1 1 auto; width: auto; height: 3rem; }
/* before a colour is chosen: hide the quantity stepper (CTA spans full width) */
.cfgb-checkout.is-precolor .cfgb-buyrow__qty { display: none; }
/* premium stepper: teal glyphs, hairline-divided segments, tactile states */
.cfgb-buyrow__qty { flex: none; display: inline-flex; align-items: stretch; gap: 0; height: 3rem;
  border: 1px solid var(--color-graphite-300); border-radius: var(--radius); overflow: hidden;
  background: var(--color-white); box-shadow: 0 1px 2px rgba(26,23,27,0.06); }
.cfgb-buyrow__qty button { width: 2.75rem; height: 100%; border: 0; background: none; cursor: pointer;
  display: grid; place-items: center; font-size: 1.4rem; font-weight: 400; line-height: 1;
  color: var(--color-teal); transition: background .15s, color .15s; }
.cfgb-buyrow__qty button:hover { background: var(--color-teal-50); }
.cfgb-buyrow__qty button:active { background: var(--color-teal-75); }
.cfgb-buyrow__qty button:disabled { color: var(--color-graphite-400); background: none; cursor: not-allowed; }
.cfgb-buyrow__qty > span { min-width: 2.1rem; display: grid; place-items: center; padding: 0 0.2rem;
  font-size: 1rem; font-weight: 700; color: var(--color-digital-black); font-variant-numeric: tabular-nums;
  border-left: 1px solid var(--color-graphite-200); border-right: 1px solid var(--color-graphite-200); }

.cfgb-reassure { display: flex; align-items: center; gap: 0.55rem; margin: 0; font-size: 0.75rem; color: var(--color-graphite-600); }
.cfgb-reassure svg { width: 1.05rem; height: 1.05rem; flex-shrink: 0; color: var(--color-teal); }
.cfgb-reassure .ph { color: var(--color-graphite-700); }
.pdp-b .pdp-avail__ship .ph { color: var(--color-graphite-700); }

/* Sticky bar CTA also morphs */
.pdp-stickybar__cta[data-mode="configure"] { background: var(--color-teal); }
.pdp-stickybar__cta[data-mode="configure"]:hover { background: var(--color-teal-hover); }

/* Lighter payment strip */
.pdp-b .pdp-pay img { height: 1.45rem; opacity: 0.85; }

/* required / optional tags (spine + step titles + option) */
.cfgb-bar__req, .stepr__req { font-size: 0.75rem; font-weight: 800; letter-spacing: normal; text-transform: capitalize;
  color: var(--color-teal); background: var(--color-teal-50); border-radius: var(--radius-pill); padding: 0.14rem 0.45rem; vertical-align: middle; }
.stepr__opt { font-size: 0.75rem; font-weight: 800; letter-spacing: normal; text-transform: capitalize;
  color: var(--color-green-600); background: var(--color-green-50); border-radius: var(--radius-pill); padding: 0.14rem 0.45rem; vertical-align: middle; }
/* "beliebt" status tag – same calm pill interface as the category-page feature
   pills (light fill, thin border, sentence case, medium weight, no shadow),
   carrying a restrained teal tint instead of a loud uppercase chip. */
.cfg-opt__tag { display: inline-block; margin-left: 0.4rem; vertical-align: middle;
  font-size: 0.75rem; font-weight: 600; letter-spacing: normal; text-transform: capitalize; line-height: 1.3;
  color: var(--color-teal); background: var(--color-teal-50);
  border: 1px solid var(--color-teal-75); border-radius: var(--radius-pill); padding: 0.08rem 0.5rem; }


/* per-step guidance hint */
.cfgb-hint { display: flex; align-items: flex-start; gap: 0.5rem; margin: 0; font-size: 0.75rem; line-height: 1.5; color: var(--color-graphite-600); }
.cfgb-hint svg { width: 1rem; height: 1rem; flex-shrink: 0; color: var(--color-teal); margin-top: 0.1rem; }

/* per-step "Weiter" button */
.cfgb-next { align-self: flex-start; display: inline-flex; align-items: center; gap: 0.4rem; font-family: inherit;
  font-size: 0.875rem; font-weight: 700; color: var(--color-white); background: var(--color-digital-black); border: 0;
  border-radius: var(--radius); padding: 0.6rem 1.4rem; cursor: pointer; transition: background .16s, transform .16s; }
.cfgb-next::after { content: "→"; font-weight: 400; }
.cfgb-next:hover { background: var(--color-black); }

/* filtered-out option (Anschluss dependency) */
.cfg-opt.is-hidden { display: none; }

@media (max-width: 560px) {
  .cfgb-cta { justify-content: center; }

  /* ── SPECS → tidy spec-sheet rows (was an awkward 2-col grid wrapping 2+1) ── */
  .pdp-b .pdp-specs { display: flex; flex-direction: column; align-items: stretch; gap: 0; margin: 0.4rem 0; }
  .pdp-b .pdp-specs__item,
  .pdp-b .pdp-specs__item:nth-child(2),
  .pdp-b .pdp-specs__item:last-child {
    flex-direction: row; align-items: baseline; justify-content: space-between;
    gap: 1rem; padding: 0.6rem 0; text-align: left; }
  .pdp-b .pdp-specs__item + .pdp-specs__item { border-top: 1px solid var(--color-graphite-200); }
  .pdp-b .pdp-specs__value { text-align: right; }

  /* ── OPTION CARDS → compact horizontal rows (was full-width stacked squares) ── */
  .cfgb .cfg-opts { grid-template-columns: 1fr; gap: 0.5rem; }
  .cfgb .cfg-opts .cfg-opt { flex-direction: row; align-items: center; gap: 0.8rem; padding: 0.65rem 0.75rem; text-align: left; }
  .cfgb .cfg-opts .cfg-opt__thumb { width: 3.25rem; height: 3.25rem; flex: none; border-radius: var(--radius); }
  .cfgb .cfg-opts .cfg-opt__body { flex: 1 1 auto; min-width: 0; padding-right: 0; }
  .cfgb .cfg-opts .cfg-opt__desc { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .cfgb .cfg-opts .cfg-opt__price { margin: 0 0 0 auto; align-self: center; padding-top: 0; text-align: right; white-space: nowrap; }
  .cfgb .cfg-opts .cfg-opt__mark { display: none; }   /* selection shown by the card's teal ring – saves width on the narrow row */
  /* status tag: keep it clear of the small thumb in row layout */
  .cfgb .cfg-opts .cfg-opt.is-unavailable .cfg-opt__badge { top: 0.5rem; left: auto; right: 0.6rem; }

  /* trust badges on mobile: two equal-width white chips with a slightly tighter gap */
  .pdp-b .hl__badges { grid-template-columns: 1fr; }
  .pdp-b .hl__badge + .hl__badge { border-left: 0; border-top: 0; }
  .pdp-b .hl__badges--infeat { gap: 0.6rem; }
  .pdp-b .hl__badges--infeat .hl__badge { flex: 1 1 0; padding: 0.45rem 0.5rem; }

  /* ── COLOUR SWATCHES → 4-up grid. At 8-in-a-row they collapsed to ~35px:
     below the 44px tap target and visually the busiest element on the page.
     Two calm rows of thumbnail-sized tiles read as one tidy block. ── */
  .bx-swatches { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.65rem; }
  .pdp-b .pdp-swatch[aria-pressed="true"] img { border-width: 2px; }

  /* ── HERO TITLE → keep the DS .h1 mobile size (24px); just tighten the
     separator spacing so the long multi-segment name flows across lines ── */
  .pdp-b .pdp-title .pdp-title__sep { margin: 0 0.2em; }

  /* ── VIEW TOGGLE sits ABOVE the photo, not over it. On the narrow stacked
     layout the centred image reaches the top-left corner, so the floating
     control covered it. Stack the stage (toggle → image) so the toggle reads
     as a clean control bar above a fully-visible product shot. ── */
  .pdp-b .pdp-media__stage { display: flex; flex-direction: column; align-items: center;
    gap: 0.7rem; aspect-ratio: auto; }
  /* Mobile: collapse the segmented control to a SINGLE standalone chip – hide the active
     view so only the alternative shows ("3D" on photos, "Fotos" on 3D), drop the pill
     wrapper, and give the "3D" chip an inviting teal accent. Stacked above the image. */
  .pdp-b .pdp-media__toggle button[aria-pressed="true"] { display: none; }
  .pdp-b .pdp-media__toggle { position: static; align-self: flex-start; background: none; border: 0; padding: 0; }
  .pdp-b .pdp-media__toggle button {
    padding: 0.5rem 0.9rem; border-radius: var(--radius);
    background: var(--color-white); border: 1px solid var(--color-graphite-300);
  }
  .pdp-b .pdp-media__toggle button:last-child {
    color: var(--color-teal); border-color: var(--color-teal); background: var(--color-teal-50);
    font-weight: 800; box-shadow: 0 1px 2px rgba(1,82,83,0.08);
  }
  .pdp-b .pdp-media__img { max-height: 52vh; }

  /* ── THUMBNAIL FILMSTRIP → lighter so it stops dominating the media block;
     smaller tiles also reveal more of the strip per swipe ── */
  .pdp-b .pdp-thumbs { gap: 0.5rem; }
  .pdp-b .pdp-thumbs button { width: 3.25rem; height: 3.25rem; }

  /* ── SPEC LABELS → 13px for comfortable legibility on mobile ── */
  .pdp-b .pdp-specs__label { font-size: 13px; }
}

@media (prefers-reduced-motion: reduce) {
  .stepr__body, .stepr__chev, .stepr__node, .stepr__item.is-active .stepr__pad > *,
  .cfgb-total__amount, .cfgb-cta, .pdp-b .pdp-media__engrave {
    transition: none !important; animation: none !important; opacity: 1 !important; transform: none !important;
  }
  .cfgb-bar__step, .cfgb-bar__step::before, .cfgb-bar__node, .cfgb-bar__num { transition: none !important; animation: none !important; }
}

/* ── Removed per request (hidden) ── */
.pdp-b .pdp-eyebrow,
.pdp-b .bx-color__note,
.pdp-b .pdp-trust,
.cfgb-next,
.cfgb-hint { display: none !important; }
.pdp-stickybar__cta svg { display: none; }          /* remove arrow from sticky CTA */

/* A/B prototype switcher – hidden on B so it never covers the fixed purchase bar */
.vswitch { display: none !important; }

/* Swatch names are NOT printed under every swatch (that crowded the page) –
   the selected name shows in the "Ausführung – …" header, and each swatch's
   name stays available via its img alt / hover preview. */
.bx-swatches .pdp-swatch::before,
.bx-swatches .pdp-swatch::after { display: none; }

/* ── Touch swatch treatment (only on no-hover devices, or ?touch=1 preview) ──
   Snap-scroller with a live caption: the "Ausführung – …" header follows the centred
   swatch via JS (hover isn't available on touch to reveal names). Swipe to browse
   the colour names, tap to select. */
.swtouch .bx-swatches { position: relative; display: flex; grid-template-columns: none; flex-wrap: nowrap; align-items: center;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  gap: 0.7rem; padding: 0.75rem 0; }   /* free scroll (no snap): the strip slides all the way to the last swatch.
     Snapping trapped it – snap-align:start put the last swatches' snap points past the
     max scroll, so it kept springing back and never reached the 6th–8th. */
.swtouch .bx-swatches::-webkit-scrollbar { display: none; }
/* Tiny trailing pad so the last swatch isn't jammed against the right edge. The active
   swatch is picked by SCROLL PROGRESS (see pdp-b.js) – first at rest, last at max
   scroll – so the strip no longer needs a viewport-wide gap to drag the final swatch to
   the left edge. That gap is what left the big blank space at the end. */
.swtouch .bx-swatches::after { content: ""; flex: 0 0 0.25rem; }
/* Fractional basis: always show ~4.5 tiles so the next swatch is ALWAYS partially
   clipped, on every screen width – the peek can no longer vanish when tiles happen
   to divide the viewport evenly. Clamped so tiles stay sensible on tiny phones /
   tablets (the edge-fade below is the width-independent backstop). */
/* Pure-percentage basis: each tile is 1/4.5 of the row (minus the 4 visible gaps),
   so the size tracks the DEVICE (container width), never the colour count, and the
   non-integer 4.5 guarantees the next swatch is always half-clipped when the palette
   overflows -> the carousel cue holds on every width. (Fits without a peek only when
   there are <=4 colours, i.e. nothing is hidden.) */
.swtouch .bx-swatches .pdp-swatch { flex: 0 0 calc((100% - 2.8rem) / 4.5); justify-content: center; }
/* Second, viewport-independent scrollability cue: fade whichever edge still has
   swatches off-screen (same pattern as .psx-nav). data-scroll is set in pdp-b.js. */
.swtouch .bx-swatches { --sw-fade: 2rem; }
.swtouch .bx-swatches[data-scroll="start"] { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - var(--sw-fade)), transparent 100%); mask-image: linear-gradient(90deg, #000 calc(100% - var(--sw-fade)), transparent 100%); }
.swtouch .bx-swatches[data-scroll="middle"] { -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--sw-fade), #000 calc(100% - var(--sw-fade)), transparent 100%); mask-image: linear-gradient(90deg, transparent 0, #000 var(--sw-fade), #000 calc(100% - var(--sw-fade)), transparent 100%); }
.swtouch .bx-swatches[data-scroll="end"] { -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--sw-fade)); mask-image: linear-gradient(90deg, transparent 0, #000 var(--sw-fade)); }
.swtouch .bx-swatches[data-scroll="none"] { -webkit-mask-image: none; mask-image: none; }
/* Symmetric slots above and below each swatch keep the image vertically centred in
   the row (content aligned above and below). Transparent – the active cue is the
   single travelling line below, not a per-swatch mark. */
.swtouch .bx-swatches .pdp-swatch::before,
.swtouch .bx-swatches .pdp-swatch::after {
  content: ""; display: block; flex: none; height: 2px; width: 1.6rem; background: transparent; }
/* Single short teal line that TRAVELS along the top of the strip in sync with the
   slide (its X is driven by scroll position in JS), as a live clue to where you are
   in the colour set. Absolute inside the scroller; JS offsets by scrollLeft so it
   glides across the viewport rather than scrolling away with the swatches. */
.bx-swline { display: none; }
.swtouch .bx-swline { display: block; position: absolute; top: 0.2rem; left: 0; z-index: 2;
  height: 2px; width: 2rem; border-radius: var(--radius-sm); background: var(--color-teal);
  pointer-events: none; will-change: transform; }

/* Desktop (hover-capable, non-touch): the SAME line as mobile – identical width and
   left-aligned placement above the active swatch, always visible – the only difference
   is that hover (not scroll) drives which swatch it sits on. Positioned by JS via
   translate to the swatch's offset (left edge). Unlike mobile (whose continuous scroll
   makes the motion smooth on its own), desktop hover is DISCRETE – so the line would
   teleport between swatches and read as jumpy. An eased transition makes it GLIDE between
   swatches instead (the "magic line" pattern). Easing is a calm decelerating ease-out
   (NO overshoot): when the pointer sweeps the row and the line re-targets on every swatch,
   an overshoot/spring would compound into jittery, hard-to-track motion – a clean settle
   keeps the movement legible and trackable. */
@media (hover: hover) {
  body:not(.swtouch) .bx-swatches { position: relative; }
  body:not(.swtouch) .bx-swline { display: block; position: absolute; top: -0.55rem; left: 0; z-index: 2;
    height: 2px; width: 2rem; border-radius: var(--radius-sm); background: var(--color-teal);
    opacity: 0; pointer-events: none; will-change: transform;
    transition: transform .48s cubic-bezier(.4, 0, .2, 1), opacity .22s ease; }   /* gentle both-ends ease (low initial velocity → no harsh jolt); longer so fast sweeps trail smoothly */
  body:not(.swtouch) .bx-swline.is-on { opacity: 1; }   /* shown only for a hovered/selected swatch – hidden at rest when no colour is chosen */
}

/* ── Swatch interaction — premium motion ──────────────────────────────────
   The labelled tile lifts to stand out: hovered/focused (desktop), selected at
   rest, or slid-over on touch (.is-labeled, set in pdp-b.js). Everything runs on
   the brand ease-out curve (calm deceleration, no overshoot); the pick is
   confirmed by a tactile press + a single scale-pop; keyboard focus gets a real
   ring. Transform / shadow / outline only — the footprint never shifts. */
.pdp-b .pdp-swatch { transition: transform .24s cubic-bezier(.22,1,.36,1); }
.pdp-b .pdp-swatch img { transition: border-color .2s cubic-bezier(.22,1,.36,1), box-shadow .24s cubic-bezier(.22,1,.36,1); }
@media (hover: hover) {
  body:not(.swtouch) .pdp-b .pdp-swatch:hover,
  body:not(.swtouch) .pdp-b .pdp-swatch:focus-visible,
  body:not(.swtouch) .pdp-b .bx-swatches:not(:hover) .pdp-swatch[aria-pressed="true"] { transform: translateY(-0.1875rem); }
  body:not(.swtouch) .pdp-b .pdp-swatch:hover img,
  body:not(.swtouch) .pdp-b .pdp-swatch:focus-visible img,
  body:not(.swtouch) .pdp-b .bx-swatches:not(:hover) .pdp-swatch[aria-pressed="true"] img { box-shadow: var(--shadow-md); }
  /* tactile press – the tile dips into the surface on pointer-down (fast, snappy) */
  body:not(.swtouch) .pdp-b .pdp-swatch:active { transform: translateY(-0.0625rem) scale(.95); transition-duration: .09s; }
  /* real keyboard focus ring – offset so it never clips the product image */
  body:not(.swtouch) .pdp-b .pdp-swatch:focus-visible img { outline: 2px solid var(--color-teal); outline-offset: 3px; }
  /* ALL versions: the selected tile no longer LIFTS at rest – its resting translate +
     shadow are dropped, so it sits flat. Only the lift is removed: the magic-line
     indicator above it and the normal hover lift are left untouched. */
  body:not(.swtouch) .pdp-b .bx-swatches:not(:hover) .pdp-swatch[aria-pressed="true"] { transform: none; }
  body:not(.swtouch) .pdp-b .bx-swatches:not(:hover) .pdp-swatch[aria-pressed="true"] img { box-shadow: none; }
}
.swtouch .pdp-b .pdp-swatch.is-labeled { transform: translateY(-0.125rem); }
.swtouch .pdp-b .pdp-swatch.is-labeled img { box-shadow: var(--shadow-md); }
/* selection confirmation – one subtle scale-pop the moment a tile becomes chosen
   (attribute-triggered: replays only on a real pick, not on hover or resize) */
.pdp-b .pdp-swatch[aria-pressed="true"] img { animation: swatch-pick .34s cubic-bezier(.22,1,.36,1); }
@keyframes swatch-pick { 0% { transform: scale(1); } 45% { transform: scale(1.08); } 100% { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) {
  .pdp-b .pdp-swatch, .pdp-b .pdp-swatch img { transition: none; animation: none; }
  body:not(.swtouch) .pdp-b .pdp-swatch:active { transform: none; }
}
@media (hover: hover) and (prefers-reduced-motion: reduce) {
  body:not(.swtouch) .bx-swline { transition: none; }
}

/* ── Preisdetails trigger (buy block) ── */
.cfgb-detailsbtn { display: flex; align-items: center; gap: 0.6rem; width: 100%; padding: 0.75rem 0.9rem;
  background: var(--color-paper); border: 1px solid var(--color-graphite-200); border-radius: var(--radius);
  cursor: pointer; font-family: inherit; font-size: 0.875rem; font-weight: 700; color: var(--color-digital-black);
  transition: border-color .16s, background .16s; }
.cfgb-detailsbtn:hover { border-color: var(--color-teal); background: var(--color-white); }
.cfgb-detailsbtn__chev { width: 1rem; height: 1rem; color: var(--color-graphite-700); flex-shrink: 0; margin-left: auto; }

/* ── Sticky bar: details button ── */
.pdp-stickybar__details { display: inline-flex; align-items: center; gap: 0.35rem; flex-shrink: 0; margin-left: auto;
  border: 1px solid var(--color-graphite-300); background: var(--color-white); border-radius: var(--radius);
  height: 2.75rem; padding: 0 1rem; cursor: pointer; font-family: inherit; font-size: 0.875rem; font-weight: 700; color: var(--color-graphite-700);
  transition: border-color .16s, color .16s; }
.pdp-stickybar__details:hover { border-color: var(--color-teal); color: var(--color-teal); }
.pdp-stickybar__details svg { width: 1rem; height: 1rem; }

/* ── Bottom-up price sheet ── */
.sheet { position: fixed; inset: 0; z-index: 400; visibility: hidden; transition: visibility 0s .34s; }
.sheet.is-open { visibility: visible; transition: visibility 0s 0s; }
.sheet__backdrop { position: absolute; inset: 0; background: rgba(20,22,25,0.45); opacity: 0; transition: opacity .3s ease; }
.sheet.is-open .sheet__backdrop { opacity: 1; }
.sheet__panel { position: absolute; left: 0; right: 0; bottom: 0; max-height: 82vh; display: flex; flex-direction: column;
  background: var(--color-white); border-radius: var(--radius-xl) var(--radius-xl) 0 0; box-shadow: 0 -0.25rem 1.25rem rgba(20,22,25,0.14);
  transform: translateY(100%); transition: transform .34s cubic-bezier(.2,.7,.2,1); }
.sheet.is-open .sheet__panel { transform: translateY(0); }
.sheet__grip { width: 2.5rem; height: 0.3rem; border-radius: var(--radius-pill); background: var(--color-graphite-200); margin: 0.7rem auto 0.1rem; }
.sheet__head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.5rem 1.25rem 0.75rem; border-bottom: 1px solid var(--color-graphite-200); margin-bottom: 0.25rem; }
.sheet__title { font-size: 1rem; font-weight: 700; letter-spacing: -0.01em; color: var(--color-digital-black); }
.sheet__close { width: 2.2rem; height: 2.2rem; display: grid; place-items: center end; padding: 0; border: 0; background: none; border-radius: 0; cursor: pointer; color: var(--color-graphite-600); }
.sheet__close svg { width: 1.1rem; height: 1.1rem; }
.sheet__close:hover { color: var(--color-digital-black); }
.sheet .cfgb-summary { border: 0; background: none; padding: 0 1.25rem 1.25rem; margin: 0; overflow-y: auto; }
/* one spacing unit (1.25rem = the container gutter) on every side of the footer:
   top gap under the divider, bottom to the edge, right to the edge, and the gap
   before the CTA all equal → uniform breathing room around the button. */
.sheet__foot { display: flex; align-items: center; justify-content: space-between; gap: 1.25rem; padding: 1.25rem; border-top: 1px solid var(--color-graphite-200); margin-top: 0; }
/* price yields width so the CTA never has to wrap; label wraps instead of the button */
.sheet__price { display: block; flex: 0 0 auto; }
/* product thumbnail beside the total (matches the sticky-bar thumb); the lead group
   keeps thumb + price together to the left of the CTA (row) and above it (mobile column). */
.sheet__foot-lead { display: flex; align-items: center; gap: 0.85rem; min-width: 0; }
/* Fixed square thumbnail sized to the price line-height and vertically centred (via the
   foot-lead's align-items:center). It matches the price number in the base state yet never
   stretches into a tall portrait when the price block grows to two lines (the
   "Preis wie konfiguriert" label sitting above the total). */
.sheet__thumb { width: 2.625rem; height: 2.625rem; flex-shrink: 0; border-radius: var(--radius); background: var(--color-paper); border: 1px solid var(--color-graphite-200); object-fit: contain; padding: 0.25rem; }
.sheet__pricelabel { display: block; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-graphite-600); line-height: 1.25; }
/* the explicit display:block above outranks the UA [hidden] rule – restore hiding so the
   "Preis wie konfiguriert" label / "ab" prefix stay mutually exclusive (only one shows) */
.sheet__pricelabel[hidden], .sheet__pricefrom[hidden] { display: none; }
.sheet__pricemeta { margin-left: 0.5rem; font-size: 0.75rem; line-height: 1.3; color: var(--color-graphite-700); white-space: nowrap; }
/* CTA stays on a single line and sizes to its content */
/* CTA sized to a prominent-but-not-dominant width and anchored right (price sits left);
   was flex:1 1 auto so it filled the whole footer and overpowered the layout. */
.sheet__foot .pdp-cta { flex: 0 0 auto; width: 17rem; height: 3rem; white-space: nowrap; background: var(--color-teal); box-shadow: none; }
.sheet__foot .pdp-cta:hover { background: var(--color-teal-hover); }
/* full-width bottom drawer – inner content comfortably centered on wide screens */
.sheet__head, .sheet .cfgb-summary, .sheet__foot { width: 100%; max-width: 64rem; margin-left: auto; margin-right: auto; }
/* hide the sticky purchase bar while the drawer is open (no duplicate price + CTA) */
body.cfg-sheet-open .pdp-stickybar { transform: translateY(110%) !important; }
/* Keyboard open (a config text field is focused): neutralise every pinned bar.
   iOS shrinks the VISUAL viewport (not the layout viewport) when the on-screen keyboard
   shows, which detaches all position:sticky/fixed bars so they float over the content
   (e.g. review thumbnails ended up above the site header). Keeping them truly pinned is
   not possible while the keyboard is up – a WebKit limitation – so instead:
   • sticky chrome (header, quickbar, section nav) drops to normal flow → it scrolls
     cleanly with the page instead of glitch-floating;
   • the fixed bars (purchase bar, config ribbon) are hidden.
   Everything is restored the instant the field blurs (.kbd-open removed). */
body.kbd-open .header,
body.kbd-open #quickbar,
body.kbd-open .psx-nav { position: static !important; }
body.kbd-open .pdp-stickybar,
body.kbd-open .cfgb-dock.is-fixed { display: none !important; }

/* ── Sticky progress bar: cover the bleed gap above when stuck ── */
.cfgb-sentinel { display: block; height: 0; }
.cfgb-bar::before { content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 3rem;
  background: var(--color-paper); opacity: 0; pointer-events: none; }
.cfgb-bar.is-stuck::before { opacity: 1; }
.cfgb-bar.is-stuck { box-shadow: 0 10px 18px -12px rgba(10,20,20,0.28); }

/* ============ Unified Step-Dock – single active step, zero redundancy ============ */
/* overflow:clip (not hidden) – still clips the rounded corners but doesn't
   create a scroll container, so the sticky dock below keeps working */
.pdp-b .cfgb { padding: 0; gap: 0; overflow: clip; }
/* No entrance transform on the config panel: a lingering transform would make .cfgb
   a containing block, so the fixed step-dock (desktop) / full-bleed bar (mobile) would
   resolve against .cfgb and get clipped instead of pinning to the viewport. opacity:1
   guarantees the panel is visible even if the shared rise animation doesn't play. */
.pdp-b .cfgb { transform: none; animation: none; opacity: 1; }
.cfgb-bar { display: none !important; }   /* retire the old icon-and-line stepper (sentinel stays: it drives the dock's is-stuck flag) */

.cfgb-dock { display: flex; flex-direction: column; padding: 0 1.35rem 1.15rem; background: var(--color-paper); border-bottom: 1px solid var(--color-graphite-200);
  position: sticky; top: 6.5rem; z-index: 7; }   /* pins below the 104px site header while scrolling the config */
/* stuck → compact: only the ribbon stays pinned (kicker + step title collapse) */
.cfgb-dock.is-stuck { padding: 0 1.35rem; box-shadow: 0 10px 18px -12px rgba(10,20,20,0.28); }
/* Desktop: fixed to the top while the config section is in the viewport. JS sets
   top (just below the green quickbar), left and width (config column) inline; z-index
   sits above the sticky quickbar (45) so the ribbon reads as its own bar. */
.cfgb-dock.is-fixed-dt { position: fixed; z-index: 46; border-radius: 0 0 var(--radius) var(--radius);
  padding-top: 0.7rem; background: var(--color-white); transform: translateZ(0); }   /* own compositing layer so iOS keeps the pinned ribbon above scrolling content; white breathing gap above so it isn't glued to the green bar */
/* the ::before paper backdrop (which caps the header↔dock seam in the sticky case)
   paints in the dock's z-46 context, so below the quickbar it would cover the green
   bar as a blank strip. The quickbar itself seals the seam here, so drop it. */
.cfgb-dock.is-fixed-dt::before { display: none; }
/* No jump at the sticky→fixed handoff: the fixed dock carries a 0.7rem top gap
   (white space above the ribbon over the quickbar), so the IN-FLOW desktop dock must
   carry the same top offset – otherwise the ribbon drops 0.7rem the instant it pins.
   Scoped to desktop (min-width 641px), where the fixed-dt behaviour applies. */
@media (min-width: 40.0625rem) { .cfgb-dock { padding-top: 0.7rem; } }
/* cap the strip above the pinned dock so scrolling options never peek through
   the header↔dock seam; the site header (higher z) covers the rest */
.cfgb-dock.is-stuck::before { content: ""; position: absolute; left: 0; right: 0; bottom: 100%;
  height: 50vh; background: var(--color-paper); z-index: -1; }
.cfgb-dock.is-stuck .cfgb-dock__meta,
.cfgb-dock.is-stuck .cfgb-dock__title { display: none; }
.cfgb-dock.is-stuck .cfgb-bar__track { margin: 0 -1.35rem; }
.cfgb-dock__meta { display: flex; align-items: center; justify-content: flex-end; gap: 0.5rem; }
.cfgb-dock__kicker { font-size: 0.75rem; font-weight: 800; letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-muted); }
/* required = red (universal "mandatory" signal); optional = green (universal "no action needed" signal) */
.cfgb-dock__flag { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.75rem; font-weight: 800;
  letter-spacing: normal; text-transform: capitalize; line-height: 1; color: var(--color-red);
  background: var(--color-red-50); border: 1px solid rgba(212,41,36,0.28); border-radius: var(--radius-pill);
  padding: 0.3rem 0.65rem; }
.cfgb-dock__flag::before { display: none; }   /* dot removed per request */
.cfgb-dock__flag.is-opt { color: var(--color-green-600); background: var(--color-green-50); border-color: rgba(0,153,81,0.28); }
.cfgb-dock__seg { display: flex; gap: 0.3rem; margin: 0.7rem 0 0.9rem; }

/* ===== Chevron step-ribbon – grey (ahead) → dark teal (done) → light green (current) ===== */
/* full-bleed band at the top of the card: no radius, no top/side padding
   (order:-1 lifts it above meta/title; negative side margins cancel dock padding) */
.cfgb-dock .cfgb-bar__track { display: flex; gap: 0; order: -1; margin: 0 -1.35rem 0.9rem; padding: 0;
  border-radius: 0; overflow: visible; }
.cfgb-dock .cfgb-bar__ico,
.cfgb-dock .cfgb-bar__check { display: none; }           /* no icons */
/* overlap each chevron into its neighbour's notch – the white seam shrinks to a 2px arrow line */
.cfgb-dock .cfgb-bar__step + .cfgb-bar__step { margin-left: -0.5rem; }

.cfgb-dock .cfgb-bar__step {
  /* flex-basis:auto – longer labels get proportionally wider chevrons.
     Number sits inline (left) of the label. */
  flex: 1 1 auto; min-width: 0; min-height: 2.9rem;
  display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 0.3rem;
  padding: 0.35rem 0.5rem 0.35rem 0.95rem; border: 0; cursor: pointer;
  font-family: inherit; background: var(--color-graphite-200); color: var(--color-graphite-700);
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 50%, calc(100% - 10px) 100%, 0 100%, 10px 50%);
  /* No transitions: this dock paints its active state on first render inside a
     just-shown container, which strands CSS transitions at their start value.
     Snapping states is both reliable and crisp for a stepper. */
}
.cfgb-dock .cfgb-bar__step:first-child {
  /* extra right padding offsets the 10px arrow tip on the right so the number
     centres in the visible chevron body, not the geometric box */
  padding-left: 0.9rem; padding-right: 1.5rem;
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 50%, calc(100% - 10px) 100%, 0 100%);
}
.cfgb-dock .cfgb-bar__step:last-child {
  /* extra left padding offsets the 10px notch on the left, same reasoning */
  padding-left: 1.5rem; padding-right: 0.9rem;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 10px 50%);
}

/* number – quiet, secondary to the label */
.cfgb-dock .cfgb-bar__num {
  flex: none; font-size: 0.75rem; font-weight: 800; line-height: 1;
  font-variant-numeric: tabular-nums; opacity: 0.66;
}

/* label – the primary information: always visible, wraps instead of clipping */
.cfgb-dock .cfgb-bar__label {
  min-width: 0; max-width: 100%; text-align: center; color: inherit;
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0; line-height: 1.15;
  white-space: normal; overflow-wrap: break-word; hyphens: auto;
}
/* standard middot divider between number and label – same "·" used across the UI
   (rating, price, availability); inherits each state's text colour */
.cfgb-dock .cfgb-bar__label::before { content: none; }   /* separator dropped to give the larger label more room in the ribbon */
/* scale the 12px base up gradually: a modest bump on small/medium screens so the
   ribbon labels aren't oversized, and only a touch larger on genuinely wide screens */
@media (min-width: 48rem) {
  .cfgb-dock .cfgb-bar__label { font-size: 0.8125rem; }   /* 13px */
}
@media (min-width: 75rem) {
  .cfgb-dock .cfgb-bar__label { font-size: 0.875rem; }    /* 14px */
  .cfgb-dock .cfgb-bar__num { font-size: 0.8125rem; }     /* 13px */
}

/* ahead (not yet reached) – quiet neutral */
.cfgb-dock .cfgb-bar__step:hover { background: var(--color-graphite-300); color: var(--color-graphite-800); }
.cfgb-dock .cfgb-bar__step:focus-visible { outline: 2px solid var(--color-teal); outline-offset: -3px; }

/* done – solid dark teal, white text (answered steps read as locked-in brand colour) */
.cfgb-dock .cfgb-bar__step.is-filled { background: var(--color-teal); color: var(--color-white); }
.cfgb-dock .cfgb-bar__step.is-filled:hover { background: var(--color-teal-600); color: var(--color-white); }
.cfgb-dock .cfgb-bar__step.is-filled .cfgb-bar__num { opacity: 1; }   /* crisp white on the dark fill */

/* current – light green, dark-teal text (the "you are here" segment stays airy) */
.cfgb-dock .cfgb-bar__step.is-current,
.cfgb-dock .cfgb-bar__step.is-current:hover { background: #CDE7E2; color: #01393A; }
.cfgb-dock .cfgb-bar__step.is-current .cfgb-bar__num { opacity: 1; }
.cfgb-dock .cfgb-bar__step.is-current .cfgb-bar__label { font-weight: 800; }

/* error – a required step wasn't answered when the user tried to proceed. The chevron
   takes the design system's error language (red-50 fill + Metzler-Rot text, same as the
   "erforderlich" pill) – a quiet third cue that points to WHERE in the flow the gap is,
   not a loud block. Wins over is-filled / is-current (declared after them); lifted above
   its neighbours so the tint isn't notched by the overlapping chevrons. Persists until
   the requirement is met; re-pulses gently on each failed attempt. */
.cfgb-dock .cfgb-bar__step.is-error,
.cfgb-dock .cfgb-bar__step.is-error:hover {
  position: relative; z-index: 2;
  background: var(--color-red-50); color: var(--color-red);
}
.cfgb-dock .cfgb-bar__step.is-error .cfgb-bar__num { opacity: 1; color: var(--color-red); }
.cfgb-dock .cfgb-bar__step.is-error .cfgb-bar__label { font-weight: 800; }
/* attention pulse on each failed attempt – a small scale beat (box-shadow can't be used:
   the chevron's clip-path would crop any glow). */
.cfgb-dock .cfgb-bar__step.is-error.is-error-pulse { animation: cfgb-tab-error 0.6s ease; }
@keyframes cfgb-tab-error {
  0%, 100% { transform: scale(1); }
  40%      { transform: scale(1.035); }
}
@media (prefers-reduced-motion: reduce) {
  .cfgb-dock .cfgb-bar__step.is-error.is-error-pulse { animation: none; }
}

/* small screens – number-only chevrons; just the current step keeps its label
   (buttons carry full aria-labels, so nothing is lost for screen readers) */
@media (max-width: 640px) {
  .cfgb-dock .cfgb-bar__step { min-height: 2.55rem; padding: 0.3rem 0.5rem 0.35rem 0.9rem; }
  .cfgb-dock .cfgb-bar__step:not(.is-current) .cfgb-bar__label { display: none; }
  .cfgb-dock .cfgb-bar__step.is-current { flex-grow: 3; }
  /* only the numbers + the current step's label show here, so scale them up from the
     12px base — they read as tiny on phones otherwise */
  .cfgb-dock .cfgb-bar__num { font-size: 0.875rem; }                        /* 14px chevron numbers */
  .cfgb-dock .cfgb-bar__step.is-current .cfgb-bar__label { font-size: 0.9375rem; }   /* 15px current label */

  /* Once the configurator scrolls under the site header, JS adds .is-fixed and the
     step ribbon detaches as a FULL-WIDTH bar pinned to the top, persisting across
     the whole page (sticky can't – it's bounded by .cfgb). The .cfgb-sentinel is
     grown to the dock's height so the content below doesn't jump. `top` is set by
     JS to the live header height so the bar sits flush beneath it. */
  .cfgb-dock.is-fixed {
    position: fixed; left: 0; right: 0; width: 100%; z-index: 80;
    padding: 0; border-bottom: 1px solid var(--color-graphite-200);
    box-shadow: 0 8px 16px -10px rgba(10,20,20,0.32);
    transform: translateZ(0);   /* own compositing layer: iOS keeps the pinned ribbon above scrolling content */
  }
  .cfgb-dock.is-fixed::before { display: none; }        /* no upward paper bleed over the header */
  .cfgb-dock.is-fixed .cfgb-bar__track { margin: 0; }   /* ribbon spans edge-to-edge, no compact gutters/gap */

  /* .cfgb hosts the fixed bar, so it must be fully "transparent" to stacking &
     positioning: any transform makes it the containing block for the fixed bar
     (breaking full-width), and any opacity<1 / transform makes it a stacking
     context that TRAPS the bar's z-index (so page content paints over it). Drop
     the entrance transforms/opacity here so the bar anchors to the viewport and
     its z-index escapes to the root, above all page content (below the header). */
  .pdp-b .cfgb { transform: none; animation: none; opacity: 1; }
}
.cfgb-segp { flex: 1; height: 0.375rem; padding: 0; border: 0; border-radius: var(--radius-pill); background: var(--color-graphite-200); cursor: pointer; overflow: hidden; position: relative; transition: background .2s; }
.cfgb-segp > i { position: absolute; inset: 0; display: block; transform: scaleX(0); transform-origin: left; background: var(--color-teal); transition: transform .45s cubic-bezier(.2,.8,.2,1); }
.cfgb-segp.is-done > i { transform: scaleX(1); }
.cfgb-segp.is-current > i { transform: scaleX(1); background: linear-gradient(90deg, #016d70, #01999b); }
.cfgb-segp.is-current { box-shadow: 0 0 0 3px rgba(1,82,83,0.10); }
.cfgb-segp:hover { background: var(--color-graphite-300); }
/* title row: step text on the left, ERFORDERLICH/OPTIONAL flag aligned on the right */
.cfgb-dock__title { margin: 0; display: flex; flex-direction: row; align-items: center; justify-content: space-between; gap: 1rem; }
.cfgb-dock__titletext { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.cfgb-dock__title .cfgb-dock__flag { flex: none; }
.cfgb-dock__n { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.01em; color: var(--color-graphite-600); }
/* numbered step title – number + name share a baseline (aligned) */
.cfgb-dock__name { display: inline-flex; align-items: baseline; gap: 0.5rem;
  font-size: 1.2rem; font-weight: 800; letter-spacing: -0.015em; color: var(--color-digital-black); line-height: 1.2; }
.cfgb-dock__name-num { flex: none; color: var(--color-graphite-600); font-weight: 800; font-variant-numeric: tabular-nums; }

.cfgb-stage { padding: 1.25rem 1.35rem 0.35rem; }
.pdp-b .cfgb .stepr { border: 0; margin: 0; padding: 0; gap: 0; }
.pdp-b .cfgb .stepr__item { display: none; border: 0; border-radius: 0; background: none; box-shadow: none; }
.pdp-b .cfgb .stepr__item.is-active { display: block; }
.pdp-b .cfgb .stepr__head { display: none !important; }
.pdp-b .cfgb .stepr__body { display: block !important; grid-template-rows: none !important; }
.pdp-b .cfgb .stepr__inner { overflow: visible; }
.pdp-b .cfgb .stepr__pad { padding: 0; }
/* The config-lock reveals the panel from display:none; the cfgb-rise entrance fade
   (opacity 0 → 1) does not reliably run on a display:none→shown reveal, which
   strands the option grid at opacity:0 and the cards vanish. Keep step content
   visible regardless of the entrance flourish. */
.pdp-b .cfgb .stepr__item.is-active .stepr__pad > * { opacity: 1 !important; transform: none !important; animation: none !important; }

/* ── Option A (mobile ≤48rem): vertical labeled accordion instead of the single-step
   wizard. Re-shows the fully-styled .stepr accordion (all steps visible, expand in
   place, one open at a time) and hides the wizard chrome (horizontal progress dock +
   Weiter/Zurück). Desktop keeps the wizard – untouched. ── */
@media (max-width: 48rem) {
  /* Full-bleed grey config surface: break out of the .container side gutter so the
     frame spans the viewport edge-to-edge – no rounded corners or side hairline.
     `calc(50% - 50vw)` resolves to exactly the container inset on each side. */
  .pdp-b .cfgb { margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw);
    border-radius: 0; border-left: 0; border-right: 0; }
  /* configuration progress bar – a compact step ribbon (numbered steps, completed =
     filled, current = highlighted). In-flow at the top of the config; via JS
     (bounded to the config section) it fixes full-width to the top, replacing the
     pinned quickbar while you scroll THROUGH the config. */
  .pdp-b .cfgb .cfgb-dock { display: flex; position: static; z-index: auto;
    padding: 0.9rem 1rem 1rem; background: none; border-bottom: 0; box-shadow: none; }
  .pdp-b .cfgb .cfgb-dock .cfgb-bar__track { margin: 0 -1rem; }   /* full-width ribbon: cancel the dock's 1rem side padding so the progress bar spans edge-to-edge */
  .pdp-b .cfgb .cfgb-dock__title { justify-content: space-between; align-items: flex-start; margin-top: 0.6rem; }
  /* required/optional flags sit far-right, top-aligned with the "Schritt X von 5"
     eyebrow line, instead of inline after the step title */
  .pdp-b .cfgb .stepr__title { justify-content: space-between; }
  /* fixed state → a solid, full-width bar that reads as part of the config
     (paper surface + hairline divider), pinned below the header. Not a floating chip. */
  .pdp-b .cfgb .cfgb-dock.is-fixed {
    /* z-index must clear the mobile quickbar (z-55) so the ribbon REPLACES it while you
       scroll through the config (was z-46 → the green quickbar painted over the ribbon's
       top edge). Stays below the site header (z-90). Matches the ≤640px rule's intent. */
    position: fixed; left: 0; right: 0; width: 100%; z-index: 80;
    padding: 0.7rem 1rem 0.75rem; background: var(--color-paper);
    border-bottom: 1px solid var(--color-graphite-300);
    box-shadow: 0 6px 14px -12px rgba(10,20,20,0.3); }
  .pdp-b .cfgb .cfgb-dock.is-fixed .cfgb-dock__title { margin-top: 0.5rem; }
  .pdp-b .cfgb .cfgb-nav { display: none; }
  .pdp-b .cfgb .cfgb-stage { padding: 0; }
  .pdp-b .cfgb .stepr { gap: 0.6rem; }
  .pdp-b .cfgb .stepr__item { display: block; border: 1px solid var(--color-graphite-200); border-radius: 0; background: var(--color-white); }
  .pdp-b .cfgb .stepr__item.is-active { border-color: var(--color-graphite-200); box-shadow: 0 0.5rem 1.5rem rgba(1,82,83,0.08); }   /* no green ring around the expanded section */
  .pdp-b .cfgb .stepr__head { display: flex !important; }
  /* the section-header "Erforderlich" (green) duplicates the required flag already
     shown in the progress dock above – drop it as redundant */
  .pdp-b .cfgb .stepr__req { display: none; }
  .pdp-b .cfgb .stepr__body { display: grid !important; grid-template-rows: 0fr !important; }
  .pdp-b .cfgb .stepr__item.is-active .stepr__body { grid-template-rows: 1fr !important; }
  .pdp-b .cfgb .stepr__inner { overflow: hidden; }
  .pdp-b .cfgb .stepr__pad { padding: 0.1rem 1rem 1.2rem; }
  /* options are horizontal rows on mobile – let the "Empfohlen" badge flow above the
     name instead of the absolute (desktop-card) position that overlapped the title */
  .pdp-b .cfgb .cfg-opt__rec { position: static; align-self: flex-start; margin: 0 0 0.3rem; }
}

.cfgb-nav { display: flex; gap: 0.75rem; padding: 1.3rem 1.35rem 1.4rem; }
.cfgb-nav__back { border: 1px solid var(--color-graphite-300); background: var(--color-white); color: var(--color-graphite-700);
  border-radius: var(--radius); padding: 0.8rem 1.4rem; font-family: inherit; font-size: 0.875rem; font-weight: 700; cursor: pointer;
  transition: border-color .15s, color .15s; }
.cfgb-nav__back:hover { border-color: var(--color-teal); color: var(--color-teal); }
.cfgb-nav__fwd { flex: 1; border: 0; background: var(--color-digital-black); color: var(--color-white); border-radius: var(--radius);
  padding: 0.8rem 1.4rem; font-family: inherit; font-size: 0.875rem; font-weight: 700; cursor: pointer;
  transition: background .15s; box-shadow: 0 0.125rem 0.375rem rgba(26,23,27,0.10); }
.cfgb-nav__fwd:hover { background: var(--color-black); }
.cfgb-nav__back[hidden], .cfgb-nav__fwd[hidden] { display: none; }

/* ── Color code – quiet label, restrained finish name ── */
.bx-color__label { font-size: 1rem; color: var(--color-graphite-600); }
.bx-color__label b { font-size: 1rem; color: var(--color-graphite-800); font-weight: 600; }

/* ── Payment methods – larger logos; wrap onto extra rows when they don't fit ── */
/* logos keep their natural size (no shrink-to-fit) and wrap centred, so on narrow
   screens they flow to a second row instead of squishing tiny */
.pdp-b .pdp-pay { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 0.4rem; max-width: 21rem; margin: 0 auto; }
.pdp-b .pdp-pay img { flex: 0 0 auto; height: 2.15rem; width: auto; max-width: 100%; object-fit: contain;
  opacity: 1; border: 0; border-radius: var(--radius);
  background: var(--color-white); padding: 0.25rem 0.35rem; box-sizing: border-box; }
/* Desktop (buybox is a two-column track): force a single row. The column is too narrow
   for 10 logos at full size, so drop the wrap + width cap, tighten the gap/padding, and
   let the logos size down just enough (object-fit keeps them crisp) to fit one line. */
@media (min-width: 56.25rem) {
  .pdp-b .pdp-pay { flex-wrap: nowrap; gap: 0.25rem; max-width: none; }
  .pdp-b .pdp-pay img { flex: 0 1 auto; min-width: 0; height: 2rem; padding: 0.18rem 0.25rem; }
}

/* ── Service & Beratung – cards mirror the Metzler contact-modal ".row":
   teal-tinted gradient icon box · bold title + grey sub · teal chevron, in a
   white card with a hairline teal-tinted border and a teal hover (left accent
   bar, gradient wash, lift). ── */
.svc { display: flex; flex-direction: column; gap: 0.625rem; }
  /* no extra margin/padding-top – the 2rem .pdp-buybox gap is the sole section rhythm,
     so the trust-card→service gap matches the service→payments gap */
.svc__item { position: relative; display: grid; grid-template-columns: 2rem 1fr auto; align-items: center; gap: 0.875rem;
  padding: 0.9rem 1rem; border: 1px solid rgba(1,82,83,0.1); border-radius: var(--radius-lg);
  background: var(--color-white); text-decoration: none; color: inherit; overflow: hidden; isolation: isolate;
  transition: border-color .35s cubic-bezier(.2,.8,.2,1), transform .35s cubic-bezier(.2,.8,.2,1); }
.svc__item::before { content: ""; position: absolute; inset: 0; z-index: -1; opacity: 0; transition: opacity .5s cubic-bezier(.2,.8,.2,1);
  background: linear-gradient(120deg, rgba(1,82,83,0) 0%, rgba(1,82,83,0.04) 45%, rgba(124,198,185,0.08) 100%); }
.svc__item::after { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: linear-gradient(180deg, var(--color-teal) 0%, #7cc6b9 100%); transform: scaleY(0); transform-origin: center;
  transition: transform .45s cubic-bezier(.2,.8,.2,1); }
.svc__icon { width: 2rem; height: 2rem; border-radius: var(--radius); display: grid; place-items: center; color: var(--color-teal);
  background: linear-gradient(135deg, #f0f6f6 0%, #e2edec 100%);
  box-shadow: inset 0 0 0 1px rgba(1,82,83,0.08), inset 0 1px 0 rgba(255,255,255,0.8);
  transition: transform .35s cubic-bezier(.2,.8,.2,1); }
.svc__icon svg { width: 1rem; height: 1rem; stroke-width: 1.5; }
.svc__text { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; transition: transform .45s cubic-bezier(.2,.8,.2,1); }
.svc__title { font-size: 1rem; font-weight: 700; line-height: 1.375; letter-spacing: -0.008em; color: var(--color-digital-black); transition: color .25s ease; }
.svc__sub { font-size: 0.75rem; font-weight: 400; line-height: 1.4; letter-spacing: 0.005em; color: var(--color-graphite-700); }
.svc__chev { flex: none; width: 1.375rem; height: 1.375rem; color: var(--color-teal); stroke-width: 1.5;
  transition: transform .35s cubic-bezier(.2,.8,.2,1); }
.svc__item:hover { border-color: rgba(1,82,83,0.35); transform: translateY(-1px); }
.svc__item:hover::before { opacity: 1; }
.svc__item:hover::after { transform: scaleY(1); }
.svc__item:hover .svc__icon { transform: scale(1.06); }
.svc__item:hover .svc__text { transform: translateX(4px); }
.svc__item:hover .svc__title { color: var(--color-teal); }
.svc__item:hover .svc__chev { transform: translateX(3px); }
.svc__item:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; }

/* ── Feature highlights – numbered editorial list. Strong title/description
   hierarchy, teal serial numbers, hairline dividers, roomy rhythm. No dot
   bullets, no icons, no grey box. ── */
.feat { position: relative; overflow: hidden; padding: 1.25rem;   /* uniform gutter on all four sides */
  background: var(--color-paper); border: 1px solid var(--color-graphite-300);   /* About-us gray codes: #F5F6FA bg · #DADADA border */
  border-radius: var(--radius-lg); box-shadow: none; }
.feat__list { position: relative; list-style: none; margin: 0; padding: 0; }
.feat__item { display: flex; flex-direction: column; gap: 0.1rem; padding: 0.6rem 0; }
.feat__item + .feat__item { border-top: 1px solid var(--color-graphite-300); }
/* first/last rows sit flush to the card's uniform gutter (no doubled-up padding) */
.feat__list > .feat__item:first-child { padding-top: 0; }
.feat__list > .feat__item:last-child { padding-bottom: 0; }
.feat__name { font-size: 0.875rem; font-weight: 700; line-height: 1.25; letter-spacing: -0.01em; color: var(--color-digital-black); }
.feat__desc { font-size: 0.8125rem; line-height: 1.4; color: var(--color-graphite-700); }   /* 13px body */

/* ── Trust badges – frame-free: prominent seal/flag + clean type, split by a
   single hairline divider ── */
.hl__badges { display: grid; grid-template-columns: 1fr 1fr; gap: 0; align-items: center; }

/* Assurance footer – two white chips on the card's grey surface. The chips lift the
   pair off the card as tangible trust marks; a full-bleed top hairline separates the
   footer from the feature list. */
.hl__badges--infeat { display: flex; align-items: stretch; gap: 0.75rem;
  margin: 1.25rem 0 0; padding: 1.25rem 0 0;   /* symmetric space around the divider; chips sit flush to the card's bottom gutter */
  background: transparent;
  border-top: 1px solid var(--color-graphite-300); }
.hl__badges--infeat .hl__badge { flex: 1 1 0; padding: 0.45rem 0.7rem; justify-content: center;
  background: var(--color-white);
  border: 1px solid var(--color-graphite-300); border-radius: var(--radius-lg);
  box-shadow: 0 1px 2px rgba(26,23,27,0.04); }
/* these are separate bordered chips – restore the left border the frame-free base rule removes */
.hl__badges--infeat .hl__badge + .hl__badge { border-left: 1px solid var(--color-graphite-300); }
/* chips separate themselves via the gap – no centre rule */

.hl__badge { display: flex; align-items: center; justify-content: center; gap: calc(0.7rem + 3px); padding: 0.35rem 0.9rem;
  border: 0; background: none; text-decoration: none; color: inherit; min-width: 0; }
.hl__badge + .hl__badge { border-left: 0; }
/* Match the two marks by VISIBLE size, not box size: the gold rosette only fills
   ~0.68 of its artwork box, the flag fills its coin edge-to-edge – so the seal box is
   sized ~1.47x larger to make the two read as equal-diameter marks. Both are round,
   both carry the same weight; the flag gets a single hairline ring, the self-framed
   seal needs none. */
.hl__badge-seal { flex: none; width: 2.2rem; height: 2.2rem; object-fit: contain; }   /* Garantie-hq.svg fills its viewBox, so a smaller box keeps the coin ~flag-sized (was 3.2rem for the old padded art) */
.hl__badge-seal--flag { width: 2rem; height: 2rem; border-radius: 50%;
  object-fit: cover; background: var(--color-white);
  box-shadow: inset 0 0 0 1px var(--color-graphite-200); }
  /* NOTE: no extra margin-right – both marks fill their boxes, so the flex `gap` alone
     keeps the icon→label distance identical on both badges (the old margin was for a
     previous seal graphic that didn't fill its box, and made the flag gap too wide). */
.hl__badge-txt { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; text-align: left; }
.hl__badge-pre { font-size: 0.75rem; font-weight: 600; color: var(--color-graphite-600); letter-spacing: 0.005em; }
.hl__badge-txt b { font-size: 0.875rem; font-weight: 800; letter-spacing: -0.012em; color: var(--color-digital-black); }

/* validation shake – gentle single nudge, not a jitter */
@keyframes cfgb-shake { 0%,100% { transform: translateX(0); } 30% { transform: translateX(-3px); } 65% { transform: translateX(3px); } }
.cfgb .stepr__pad.is-flash { animation: cfgb-shake .3s ease; }

/* invalid highlight – the red border draws the eye; one soft glow, no jump */
@keyframes cfgb-invalid-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(212,41,36,0.4); }
  100% { box-shadow: 0 0 0 6px rgba(212,41,36,0); }
}
/* fixed line-height so the engraving preview font (some scripts have tall metrics)
   doesn't change the input's height and jump the layout when switching styles.
   NOTE: this height must NOT leak onto .cfg-opts.is-invalid .cfg-opt – a stray
   comma once did that and collapsed the option cards to 52px during the flash. */
.pdp-b .cfg-input { line-height: 1.5; height: 3.25rem; box-sizing: border-box; }
.cfgb .cfg-input.is-invalid {
  border-color: var(--color-red) !important;
  animation: cfgb-invalid-pulse .7s ease-out 1;
}
/* NOTE: do NOT put `animation` on .cfg-opts itself – it's a .stepr__pad child that
   starts at opacity:0 and is revealed by the cfgb-rise entrance animation; overriding
   that would drop the option grid back to opacity:0 and the cards vanish on the flash.
   The invalid highlight goes on the .cfg-opt CARDS instead (grandchildren, unaffected):
   red border + one soft glow pulse – the original feedback. */
.cfgb .cfg-opts.is-invalid { border-radius: var(--radius-lg); }
/* minimal required signal: just a quiet red border (the .cfg-opt border-color .15s
   transition fades it in) – no glow ring, no pulse */
.cfgb .cfg-opts.is-invalid .cfg-opt { border-color: var(--color-red); }
/* badge: steady colour emphasis, no scale/jump */
/* same red-ring pulse as the colour-requirement cue (bx-swatch-alert) so every
   "required" signal reads consistently – same animation, same red */
.cfgb-dock__flag.is-pulse { animation: bx-swatch-alert .7s ease-out; }

/* ── Preisdetails – inline accordion in the buy block ── */
.cfgb-acc { border: 1px solid var(--color-graphite-200); border-radius: var(--radius); overflow: hidden; background: var(--color-white); }
.cfgb-acc .cfgb-detailsbtn { border: 0; border-radius: 0; background: var(--color-paper); }
.cfgb-acc .cfgb-detailsbtn:hover { background: var(--color-white); }
.cfgb-acc.is-open .cfgb-detailsbtn { background: var(--color-white); border-bottom: 1px solid var(--color-graphite-200); }
.cfgb-detailsbtn__chev { transition: transform .3s ease; }
.cfgb-acc.is-open .cfgb-detailsbtn__chev { transform: rotate(180deg); }
.cfgb-acc__body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .35s cubic-bezier(.2,.7,.2,1); }
.cfgb-acc.is-open .cfgb-acc__body { grid-template-rows: 1fr; }
.cfgb-acc__inner { overflow: hidden; min-height: 0; }
.cfgb-acc .cfgb-summary { border: 0; background: none; padding: 0.35rem 0.9rem 0.75rem; margin: 0; }

/* ── Inline per-product quantity (in the configuration, next to each entry) ── */
.cfg-choice { display: flex; flex-direction: column; }
.cfg-choice__qty { display: none; align-items: center; justify-content: flex-end; gap: 0.75rem;
  margin: 0.4rem 0 0.3rem; padding: 0.5rem 0.8rem; background: var(--color-teal-50); border-radius: var(--radius); }
.cfg-choice.is-open .cfg-choice__qty { display: flex; }
.cfg-choice__qtyl { display: none; }   /* "Menge" label redundant next to the stepper */

/* Zubehör: the choice wrapper IS the card, so the quantity stepper lives inside
   its border (was a detached box floating below) */
.cfgb .cfg-choice { border: 1px solid var(--color-graphite-300); border-radius: var(--radius-lg); background: var(--color-white); overflow: hidden; }
.cfgb .cfg-choice.is-open { border-color: var(--color-teal); box-shadow: inset 0 0 0 1px var(--color-teal); }
.cfgb .cfg-choice__qty { margin: 0; border-radius: 0; background: var(--color-paper); border-top: 1px solid var(--color-graphite-200); padding: 0.6rem 0.85rem; justify-content: center; }
/* stepper = one connected control (was two floating bordered boxes), like the main qty */
.cfgb .cfg-choice__qty .cfg-opt__qty { gap: 0; align-items: stretch; border: 1px solid var(--color-graphite-300);
  border-radius: var(--radius); overflow: hidden; background: var(--color-white); }
.cfgb .cfg-choice__qty .cfg-opt__qty button { width: 2.5rem; height: 2rem; border: 0; border-radius: 0; background: none;
  color: var(--color-teal); font-size: 1.125rem; }
.cfgb .cfg-choice__qty .cfg-opt__qty button:hover { background: var(--color-teal-50); }
.cfgb .cfg-choice__qty .cfg-opt__qty > span { min-width: 2.25rem; display: grid; place-items: center; padding: 0 0.35rem;
  border-left: 1px solid var(--color-graphite-200); border-right: 1px solid var(--color-graphite-200); }

/* ── Gravur font picker – grid of samples ("Muster") with a style name ── */
.pdp-b .cfg-fonts { display: grid; grid-template-columns: repeat(auto-fill, minmax(6.25rem, 1fr)); gap: 0.5rem; }
.pdp-b .cfg-font { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.15rem;
  padding: 0.6rem 0.5rem; min-height: 3.9rem; font-weight: 400; }
.pdp-b .cfg-font.is-selected { font-weight: 400; }   /* don't force-bold the sample */
.pdp-b .cfg-font__s { font-size: 1.2rem; line-height: 1.1; color: var(--color-digital-black); }
.pdp-b .cfg-font__n { font-size: 0.5625rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-muted); }
.pdp-b .cfg-font.is-selected .cfg-font__s,
.pdp-b .cfg-font.is-selected .cfg-font__n { color: var(--color-teal); }
.cfgb-mainqty { display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.6rem 0.9rem; border: 1px solid var(--color-graphite-200); border-radius: var(--radius); }
.cfgb-mainqty__l { font-size: 0.875rem; font-weight: 700; color: var(--color-digital-black); }
/* read-only qty in the price detail */
.sum-qty-ro { font-size: 0.8125rem; font-weight: 700; color: var(--color-graphite-600); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }

/* ── Product option cards → vertical tiles (image on top, text + price below) ── */
.cfgb .cfg-opts { display: grid; grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr)); gap: 0.6rem; }
/* height:auto (not 100%) – grid align-items:stretch equalises card heights per row */
.cfgb .cfg-opt { position: relative; flex-direction: column; align-items: stretch; gap: 0.5rem; padding: 0.85rem; text-align: left; }
.cfgb .cfg-opt__mark { position: absolute; top: 0.65rem; left: 0.65rem; margin: 0; z-index: 2; background: var(--color-white); }   /* selection control (radio/checkbox) → top-left */
/* keep the selection fill dead-centered in the mark box (robust vs grid/box-sizing drift) */
.cfgb .cfg-opt.is-selected .cfg-opt__mark::after { position: absolute; inset: 0; margin: auto; }
/* "Empfohlen" pill – same format as the availability badges, in primary teal */
.cfg-opt__rec {
  position: absolute; top: 0.6rem; left: 0.6rem; z-index: 3;
  display: inline-flex; align-items: center; max-width: calc(100% - 1.2rem);
  padding: 0.28rem 0.6rem; border-radius: var(--radius-pill); line-height: 1.2;
  font-size: 0.75rem; font-weight: 600; letter-spacing: normal; text-transform: none;
  border: 1px solid var(--color-teal); background: rgba(1,82,83,0.08); color: var(--color-teal);
}
/* square frame, no grey fill, no border – the image covers it edge-to-edge */
.cfgb .cfg-opt__thumb { width: 100%; aspect-ratio: 1; height: auto; display: grid; place-items: center; padding: 0; overflow: hidden;
  background: var(--color-white); border: 0; border-radius: var(--radius); }
.cfgb .cfg-opt__thumb img { grid-area: 1 / 1; width: 100%; height: 100%; object-fit: cover; padding: 0; }
.cfgb .cfg-opt__body { flex: 0 0 auto; min-width: 0; padding-right: 1.5rem; }
.cfgb .cfg-opt__desc { color: var(--color-graphite-700); }   /* rgb(84,84,92) – darker than base; weight unchanged */
.cfgb .cfg-opt__price { align-self: flex-start; margin-top: auto; padding-top: 0.15rem; text-align: left; }

/* ── TEST (Anschluss step only): radio top-left, info icon top-right, "Empfohlen"
   overlaid on the image so it never shifts the text → all cards share one
   image→title→desc→price flow (perfect alignment, no reserved-slot gap) ── */
#bAnschluss .cfg-opt__info { position: absolute; top: 0.5rem; right: 0.55rem; z-index: 2;
  width: 1.4rem; height: 1.4rem; display: grid; place-items: center; padding: 0;
  color: var(--color-graphite-500); background: var(--color-white); border-radius: 50%; }
#bAnschluss .cfg-opt__info svg { width: 1.2rem; height: 1.2rem; }
#bAnschluss .cfg-opt:hover .cfg-opt__info { color: var(--color-graphite-700); }
#bAnschluss .cfg-opt__body { padding-right: 0; }                        /* full width for long title/desc */
#bAnschluss .cfg-opt { overflow: hidden; }                             /* clip the bar to the card's rounded corners */
/* Both cards carry a full-width bottom bar, so grid-stretch keeps them EQUAL HEIGHT
   with the bar as part of each card – no taller card, no empty gap. The content above
   (title/desc/price) stays aligned; the price is pushed to just above the bar on both.
   Recommended bar keeps the original pill colours (light-teal fill, teal text, hairline). */
/* premium label treatment: uppercase, letter-spaced tags. The recommended bar keeps the
   teal tint but deepened so it clearly stands out (a tinted tag, NOT a solid CTA-like fill –
   keeps the config panel's tint language consistent); the alternative stays a quiet muted
   grey tag. */
#bAnschluss .cfg-opt__rec { position: static; z-index: auto; display: block;
  margin: 0 -0.85rem -0.85rem; padding: 0.5rem 0.85rem; max-width: none;
  border: 0; border-radius: 0; text-align: center;
  background: rgba(1,82,83,0.15); color: var(--color-teal);
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; }
/* non-recommended card's bar – neutral grey counterpart (keeps heights consistent) */
#bAnschluss .cfg-opt__rec--muted { background: rgba(26,23,27,0.05); color: var(--color-graphite-600); }
/* desktop: the label sits at the TOP edge of the card (order:-1 + negative top margin);
   the radio + info drop below it onto the image so they don't collide with the tag bar.
   Mobile keeps its own row layout untouched. */
@media (min-width: 48rem) {
  #bAnschluss .cfg-opt__rec { order: -1; margin: -0.85rem -0.85rem 0; }
  #bAnschluss .cfg-opt__mark { top: 2.6rem; }
  #bAnschluss .cfg-opt__info { top: 2.5rem; }
}
/* NB: no teal border on the recommended card – the teal "Empfohlen" bar is the signal;
   a border here would clash with the 2px teal border used for hover/selected state. */
/* inner option drops its own card chrome – the choice wrapper carries it now */
.cfgb .cfg-choice .cfg-opt { flex: 1 1 auto; border: 0; border-radius: 0; background: none; box-shadow: none; }
/* selected card: teal border/ring only – no grey fill */
.cfgb .cfg-opt.is-selected { background: var(--color-white); }
/* Uniform selection border: one crisp 2px teal border on every config card
   (Gravur/Anschluss carry it on the .cfg-opt, Innenstation/Zubehör on the
   .cfg-choice wrapper). Replaces the 1px-border + 1px-inset-ring combo so the
   weight is identical everywhere; border-box keeps the footprint stable. */
.cfgb .cfg-opts > .cfg-opt, .cfgb .cfg-choice { box-sizing: border-box; }
.cfgb .cfg-opts > .cfg-opt.is-selected,
.cfgb .cfg-choice.is-open { border-width: 2px; border-color: var(--color-teal); box-shadow: none; }
.cfgb .cfg-opt__thumb--icon { background: var(--color-white); }
.cfgb .cfg-opt__thumb svg { width: 2.4rem; height: 2.4rem; color: var(--color-graphite-400); grid-area: 1 / 1; }
/* "Ohne Innenstation" as a slim full-width row (no tile/icon) – the free baseline
   spanning above the upgrade cards, with a one-line note on what going without
   limits (SIP/Fritz only, no app). Still a real, selectable radio option, so the
   default / safe-fallback / selection logic all keep working unchanged. */
/* "Ohne Innenstation" explainer – a quiet note above the multi-select cards
   (choosing no station is simply leaving them all unselected) */
.cfg-innen-note { margin: 0 0 0.9rem; font-size: 0.75rem; line-height: 1.5; color: var(--color-graphite-700); }
.cfg-innen-note b { color: var(--color-digital-black); font-weight: 700; }
.cfgb .cfg-opts .cfg-opt--plain { grid-column: 1 / -1; flex-direction: row; align-items: center;
  gap: 0.85rem; padding: 0.8rem 1rem; }
/* relative (not static) so the absolutely-centered selection fill (::after, line ~982)
   stays inside the mark box instead of escaping to the row's centre */
.cfgb .cfg-opt--plain .cfg-opt__mark { position: relative; top: auto; left: auto; right: auto; margin: 0; flex: none; }
.cfgb .cfg-opt--plain .cfg-opt__body { flex: 1 1 auto; padding-right: 0; }
.cfgb .cfg-opt--plain .cfg-opt__price { margin: 0 0 0 auto; align-self: center; padding-top: 0; white-space: nowrap; }
/* Opt-out / "without" tile – a MEANINGFUL duotone medallion of the alternative,
   not a ⊘ ban mark (which read as "forbidden" for what is a valid, free choice):
   a phone for "Ohne Innenstation" (you answer on your phone), a plug for
   "Standard" power. Each is a graphite device with a teal accent inside a soft
   teal disc – one consistent, on-brand system across every opt-out. */
.cfgb .cfg-opt__thumb--none { background: radial-gradient(120% 100% at 50% 32%, var(--color-white) 0%, var(--color-teal-50) 100%); }
.cfgb .cfg-opt__thumb--none svg { width: 78%; height: 78%; grid-area: 1 / 1; }

/* ── Universal UNAVAILABLE state – one treatment for out-of-stock OR options
   incompatible with an earlier choice. The tile stays visible (so the reason is
   learnable) but is clearly inert: dimmed, non-selectable, no radio, and a single
   flat status chip in the corner – no rotated watermark stamp. ── */
.cfgb .cfg-opt.is-unavailable { cursor: not-allowed; }
.cfgb .cfg-opt.is-unavailable .cfg-opt__thumb { filter: grayscale(0.9); opacity: 0.5; }
.cfgb .cfg-opt.is-unavailable .cfg-opt__body,
.cfgb .cfg-opt.is-unavailable .cfg-opt__price { opacity: 0.5; }
.cfgb .cfg-opt.is-unavailable .cfg-opt__mark { visibility: hidden; }
/* status tag – same calm pill interface as the category-page feature pills:
   light OPAQUE fill (legible over the dimmed thumbnail), thin border, sentence
   case, medium weight, no drop shadow. Semantic tint kept restrained so an
   unavailable option still reads at a glance (red = sold out, neutral = needs
   another connection). */
.cfg-opt__badge {
  position: absolute; top: 0.6rem; right: 0.6rem; z-index: 3;   /* moved to top-right, clear of the left-side selection control */
  display: inline-flex; align-items: center; gap: 0.34rem; max-width: calc(100% - 1.2rem);
  padding: 0.28rem 0.6rem; border-radius: var(--radius-pill); line-height: 1.2;
  font-size: 0.75rem; font-weight: 600; letter-spacing: normal; text-transform: none;
  border: 1px solid var(--color-graphite-200); background: var(--color-white); color: var(--color-graphite-700);
}
.cfg-opt__badge svg { width: 0.9rem; height: 0.9rem; flex: none; }
.cfg-opt__badge.is-oos { background: var(--color-orange-50); border-color: var(--color-orange); color: var(--color-orange-600); }  /* out of stock → orange */
.cfg-opt__badge.is-incompat { background: var(--color-blue-50); border-color: var(--color-blue); color: var(--color-blue-600); }  /* needs another connection → blue */

/* ── Compact radio rows: for thumbnail-less binary choices (e.g. Gravur) –
   the full image-tile treatment is too heavy for a plain option ── */
.cfgb .cfg-opts--rows { grid-template-columns: 1fr; gap: 0.5rem; }
.cfgb .cfg-opts--rows .cfg-opt { flex-direction: row; align-items: center; gap: 0.75rem; padding: 0.7rem 0.85rem; }
.cfgb .cfg-opts--rows .cfg-opt__mark { position: relative; top: auto; left: auto; right: auto; z-index: auto; background: none; flex: none; }
.cfgb .cfg-opts--rows .cfg-opt__body { flex: 1 1 auto; padding-right: 0; }
.cfgb .cfg-opts--rows .cfg-opt__price { margin: 0 0 0 auto; padding-top: 0; align-self: center; text-align: right; white-space: nowrap; }

/* ── Price-details summary (itemized cart with qty steppers) ── */
/* One shared 3-column grid (name | qty | price); rows use subgrid so the qty and price
   columns line up across every row instead of each row sizing its own columns. */
.cfgb-summary { display: grid; grid-template-columns: 1fr auto auto; column-gap: 0.7rem; padding: 0.5rem 0.9rem; margin-bottom: 0.2rem;
  background: var(--color-white); border: 1px solid var(--color-graphite-200); border-radius: var(--radius); }
.sum-row { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: center; padding: 0.55rem 0; }
.sum-row__price, .sum-qty, .sum-qty-ro { justify-self: end; }   /* right-align qty + price within their shared columns */
.sum-row + .sum-row { border-top: 1px solid var(--color-graphite-100); }
.sum-row__name { font-size: 0.8125rem; color: var(--color-digital-black); min-width: 0; }
.sum-row__name b { font-weight: 700; }
.sum-row__name .sum-sub { display: none; }   /* finish is shown in Ausführung + specs – not repeated per price line */
.sum-row__price { font-size: 0.8125rem; font-weight: 700; color: var(--color-digital-black); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.sum-row__price.is-incl { color: var(--color-green); font-weight: 600; }
.sum-qty { display: inline-flex; align-items: center; gap: 0.3rem; }
.sum-qty button { width: 1.55rem; height: 1.55rem; border: 1px solid var(--color-graphite-300); background: var(--color-white);
  border-radius: var(--radius); cursor: pointer; font-size: 1rem; line-height: 1; color: var(--color-digital-black);
  display: grid; place-items: center; transition: border-color .15s, color .15s; }
.sum-qty button:hover { border-color: var(--color-teal); color: var(--color-teal); }
.sum-qty span { min-width: 1.1rem; text-align: center; font-weight: 700; font-size: 0.8125rem; font-variant-numeric: tabular-nums; }
.sum-row--total { border-top: 2px solid var(--color-graphite-200); margin-top: 0.1rem; padding-top: 0.7rem; }
.sum-row--total .sum-row__name { font-weight: 700; }
.sum-row--total .sum-row__price { font-size: 0.875rem; }

/* ── Sticky bottom bar – set only vertical padding; the horizontal inset comes
   from .container's padding-inline so the bar's content lines up with the page
   content above (was overriding it with a shorthand → edge-to-edge misalignment). ── */
#pdpStickyBar .pdp-stickybar__inner { padding-block: 0.8rem; gap: 1.1rem; }
#pdpStickyBar .pdp-stickybar__cta { padding: 0 1.6rem; margin-left: 0.6rem; }
@media (max-width: 900px) {
  #pdpStickyBar .pdp-stickybar__inner { padding: 0.7rem 1rem; }
  /* collapse the hero to a single stacked column – the base rule (pdp.css:289) does this,
     but .pdp-b .pdp-hero__grid (pdp-b.css:20) outranks it, so re-state the override here
     or the buybox stays trapped in a half-width grid track.
     minmax(0,1fr) (not 1fr) + min-width:0 let the column shrink to the viewport instead
     of the buy-box's min-content, which otherwise forces ~330px and overflows narrow phones. */
  .pdp-b .pdp-hero__grid { grid-template-columns: minmax(0, 1fr); column-gap: 0; }
  .pdp-b .pdp-buybox { min-width: 0; }
}

/* ============================================================
   KONTAKT & SERVICE MODAL – ported from the Metzler contact-bar
   handoff (namespaced .cm-* so it never collides with page styles)
   ============================================================ */
@keyframes cm-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes cm-rise { from { opacity: 0; transform: translateY(20px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes cm-in-left { from { opacity: 0; transform: translateX(-12px); } to { opacity: 1; transform: none; } }
@keyframes cm-in-right { from { opacity: 0; transform: translateX(12px); } to { opacity: 1; transform: none; } }

.cm-overlay { position: fixed; inset: 0; z-index: 400; background: rgba(0,0,0,.45);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); display: none; place-items: center; padding: 24px; }
.cm-overlay.is-open { display: grid; animation: cm-fade .3s ease; }
.cm-modal { position: relative; width: min(60rem,100%); display: grid; grid-template-columns: 5fr 7fr;
  background: var(--color-white); border-radius: var(--radius-xl); overflow: hidden;
  box-shadow: 0 1px 2px rgba(0,0,0,.04), 0 40px 80px -20px rgba(1,40,40,.45); animation: cm-rise .45s cubic-bezier(.2,.8,.2,1); }

.cm-brand { position: relative; padding: 3rem 2.75rem; background: var(--color-teal-600); color: var(--color-white); display: flex; flex-direction: column; min-height: 32.5rem; overflow: hidden; }
.cm-brand-head, .cm-brand-foot { position: relative; z-index: 1; animation: cm-in-left .5s ease .1s both; }
.cm-brand-foot { margin-top: 32px; animation-delay: .25s; border-top: 1px solid rgba(255,255,255,.12); padding-top: 22px; display: flex; flex-direction: column; gap: 10px; }
.cm-brand-title { margin: 0 0 1rem; font-size: 1.875rem; line-height: 1.25; font-weight: 700; letter-spacing: -.02em; }
.cm-brand-title em { font-style: normal; color: var(--color-mint); font-weight: 600; }
.cm-lede { margin: 0; font-size: .875rem; line-height: 1.5; color: var(--on-dark-muted); font-weight: 400; max-width: 32ch; }
.cm-brand-foot .cm-label { font-size: .75rem; font-weight: 700; line-height: 1.4; letter-spacing: .18em; text-transform: uppercase; color: var(--color-mint); }
.cm-phone { font-size: 1.25rem; font-weight: 700; line-height: 1.35; letter-spacing: -.01em; color: var(--color-white); text-decoration: none; }
.cm-metaline { font-size: .75rem; line-height: 1.4; color: var(--on-dark-muted); font-weight: 400; }
.cm-mail { font-size: .875rem; line-height: 1.5; color: var(--color-mint); text-decoration: none; font-weight: 600; }
.cm-mail:hover { color: var(--color-white); text-decoration: underline; }

.cm-actions { position: relative; padding: 2.5rem 2.5rem 2rem; background: var(--color-white); display: flex; flex-direction: column; }
.cm-eyebrow { display: inline-flex; align-items: center; gap: 0.625rem; font-size: .75rem; font-weight: 700; line-height: 1.4;
  letter-spacing: .18em; text-transform: uppercase; color: var(--color-graphite-600); margin: 0 0 0.75rem; animation: cm-in-right .5s ease .2s both; }
.cm-h2 { margin: 0 0 0.375rem; font-size: 1.25rem; font-weight: 700; line-height: 1.35; letter-spacing: -.01em; color: var(--color-digital-black); animation: cm-in-right .5s ease .25s both; }
.cm-sub { margin: 0 0 1.75rem; font-size: .875rem; font-weight: 400; color: var(--color-graphite-700); line-height: 1.5; animation: cm-in-right .5s ease .28s both; }

.cm-list { display: flex; flex-direction: column; flex: 1; gap: 0.625rem; }
.cm-row { position: relative; display: grid; grid-template-columns: 2rem 1fr auto; align-items: center; gap: 0.875rem;
  padding: 1rem 1.625rem 1rem 1.25rem; border: 1px solid rgba(1,82,83,.1); border-radius: var(--radius-lg); background: var(--color-white);
  text-decoration: none; color: inherit; cursor: pointer; overflow: hidden; isolation: isolate;
  transition: border-color .45s cubic-bezier(.2,.8,.2,1), transform .45s cubic-bezier(.2,.8,.2,1); animation: cm-in-right .5s ease both; }
.cm-row::before { content: ""; position: absolute; inset: 0; z-index: -1; opacity: 0; transition: opacity .5s cubic-bezier(.2,.8,.2,1);
  background: linear-gradient(120deg, rgba(1,82,83,0) 0%, rgba(1,82,83,.04) 45%, rgba(124,198,185,.08) 100%); }
.cm-row::after { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 0.1875rem;
  background: linear-gradient(180deg, var(--color-teal) 0%, #7cc6b9 100%); transform: scaleY(0); transform-origin: center; transition: transform .45s cubic-bezier(.2,.8,.2,1); }
.cm-row:nth-child(1){animation-delay:.3s} .cm-row:nth-child(2){animation-delay:.38s} .cm-row:nth-child(3){animation-delay:.46s} .cm-row:nth-child(4){animation-delay:.54s}
.cm-ico { position: relative; width: 2rem; height: 2rem; border-radius: var(--radius); display: grid; place-items: center; color: var(--color-teal);
  background: linear-gradient(135deg, #f0f6f6 0%, #e2edec 100%);
  box-shadow: inset 0 0 0 1px rgba(1,82,83,.08), inset 0 1px 0 rgba(255,255,255,.8); transition: transform .35s cubic-bezier(.2,.8,.2,1); }
.cm-ico svg { width: 1rem; height: 1rem; stroke-width: 1.5; }
.cm-body { min-width: 0; display: flex; flex-direction: column; gap: 0.1875rem; transition: transform .45s cubic-bezier(.2,.8,.2,1); }
.cm-rowlabel { font-size: 1rem; font-weight: 700; line-height: 1.375; letter-spacing: -.008em; color: var(--color-digital-black); transition: color .25s ease; }
.cm-rowmeta { font-size: .75rem; font-weight: 400; line-height: 1.4; color: var(--color-graphite-600); letter-spacing: .005em; }
.cm-arrow { display: grid; place-items: center; color: var(--color-teal); transition: transform .3s cubic-bezier(.2,.8,.2,1); }
.cm-arrow svg { width: 1.375rem; height: 1.375rem; stroke-width: 1.5; transition: transform .35s cubic-bezier(.2,.8,.2,1); }
.cm-row:hover { border-color: rgba(1,82,83,.35); transform: translateY(-1px); }
.cm-row:hover::before { opacity: 1; }
.cm-row:hover::after { transform: scaleY(1); }
.cm-row:hover .cm-body { transform: translateX(4px); }
.cm-row:hover .cm-rowlabel { color: var(--color-teal); }
.cm-row:hover .cm-ico { transform: scale(1.06); }
.cm-row:hover .cm-arrow svg { transform: translateX(3px); }

.cm-close { position: absolute; top: 1.25rem; right: 1.25rem; z-index: 2; width: 2.25rem; height: 2.25rem; border-radius: var(--radius);
  background: transparent; border: 0; color: var(--color-graphite-600); cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  transition: background .15s ease, color .15s ease; }
.cm-close svg { width: 1.125rem; height: 1.125rem; }   /* centered lightbox X – matches the other popups' close icon */
.cm-close:hover { color: var(--color-digital-black); background: var(--color-graphite-100); }

@media (max-width: 767px) {
  .cm-overlay.is-open { padding: 0; align-items: flex-end; }
  .cm-modal { display: flex; flex-direction: column; grid-template-columns: none; border-radius: var(--radius-xl) var(--radius-xl) 0 0; max-height: 90vh; overflow: hidden; }
  .cm-brand { padding: 1.75rem 1.5rem 1.5rem; min-height: auto; flex: 0 0 auto; }
  .cm-brand-title { font-size: 1.625rem; }
  .cm-lede { display: none; }
  .cm-brand-foot { padding-top: 1.125rem; margin-top: 1.125rem; gap: 0.375rem; }
  .cm-actions { padding: 1.5rem 1.25rem 1.75rem; flex: 1 1 auto; min-height: 0; overflow-y: auto; }
  .cm-close { top: 0.875rem; right: 0.875rem; width: 2.75rem; height: 2.75rem; color: var(--color-mint); }
  .cm-close:hover { background: transparent; color: var(--color-white); }
}
@media (prefers-reduced-motion: reduce) {
  .cm-overlay, .cm-modal, .cm-brand-head, .cm-brand-foot, .cm-eyebrow, .cm-h2, .cm-sub, .cm-row { animation: none !important; }
}

/* ============================================================
   CUSTOMER REVIEWS – overall score, distribution, testimonial carousel.
   Built on the Metzler design tokens; scoped to .rv. ============================ */
.rv { background: var(--color-paper); padding: var(--sx-rhythm) 0; scroll-margin-top: 5.5rem; }
.rv__inner { display: flex; flex-direction: column; }

/* Heading – matches the About-us section header (.eyebrow / .section-title / .section-sub) */
.rv__head { text-align: center; max-width: 44rem; margin: 0 auto clamp(1.75rem, 3vw, 2.5rem); }
.rv__eyebrow { margin: 0 0 0.75rem; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.15em; line-height: 1.4; text-transform: uppercase; color: var(--color-graphite-600); }
.rv__title { margin: 0; font-size: clamp(2rem, 4vw, 2.875rem); font-weight: 700; letter-spacing: -0.01em; line-height: 1.15; color: var(--color-digital-black); }
.rv__sub { margin: 1rem auto 0; max-width: 56ch; font-size: 1.125rem; line-height: 1.5; color: var(--color-digital-black); }   /* 18px — DS body-lg, consistent with .psx-lead */

/* ── One merged panel: rating summary (left zone) + featured testimonial (right zone),
   divided by a single hairline – one surface, no double cards. ── */
.rv__layout { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.6fr);
  gap: 0; align-items: stretch;
  background: var(--color-white); border: 1px solid var(--color-graphite-200);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-soft); overflow: hidden; }

/* ── Summary – left zone of the panel, set apart by a soft tonal tint (a stats
   panel), not a divider line ── */
.rv__summary { display: flex; flex-direction: column; justify-content: center; gap: 1.35rem;
  padding: clamp(1.5rem, 3vw, 2.25rem); background: var(--color-teal-50); }   /* soft mint-green tint, matching the info-icon backgrounds */

/* score */
.rv__score { text-align: center; }
.rv__score-num { font-size: clamp(2.25rem, 3.5vw, 3rem); font-weight: 800; letter-spacing: -0.03em; line-height: 1; color: var(--color-digital-black); }
.rv__score-num span { font-size: 0.35em; font-weight: 700; color: var(--color-graphite-500); margin-left: 0.15em; }
.rv__score-stars { margin: 0.65rem 0 0.5rem; justify-content: center; }
.rv__score-stars svg { width: 1.35rem; height: 1.35rem; }
.rv__score-count { margin: 0; font-size: 1rem; color: var(--color-graphite-700); }
.rv__score-count b { color: var(--color-digital-black); font-weight: 800; }
.rv__verified { display: inline-flex; align-items: center; gap: 0.4rem; margin: 0.75rem 0 0;
  font-size: 0.75rem; font-weight: 700; color: var(--color-teal); }
.rv__verified svg { width: 1rem; height: 1rem; }

/* distribution bars */
.rv__dist { display: flex; flex-direction: column; gap: 0.55rem; min-width: 0;
  padding: 1.25rem 0; border-top: 1px solid var(--color-graphite-200); border-bottom: 1px solid var(--color-graphite-200); }
.rv__dist-row { display: grid; grid-template-columns: 4.75rem 1fr 2rem; align-items: center; gap: 0.7rem; }
.rv__dist-label { font-size: 0.875rem; font-weight: 700; color: var(--color-graphite-700); white-space: nowrap; }
/* empty track: same treatment as the CTA button – white fill + graphite outline –
   so the tracks read as consistent with the "Alle Bewertungen" button */
.rv__dist-bar { height: 0.5rem; background: var(--color-white); border: 1px solid var(--color-graphite-200); border-radius: var(--radius-pill); overflow: hidden; }
.rv__dist-bar i { display: block; height: 100%; border-radius: var(--radius-pill);
  background: var(--color-star); }
.rv__dist-val { font-size: 0.8125rem; font-weight: 700; color: var(--text-muted); text-align: right; }

/* aside: CTA */
.rv__aside { display: flex; flex-direction: column; align-items: center; gap: 0.6rem; text-align: center; }
/* CTA – mirrors the gallery's "Alle N Bilder ansehen" button (.pdp-thumbs__all):
   white, 1px grey border, teal text, radius-lg; hover = teal border + teal-50 */
.rv__cta { display: flex; width: 100%; align-items: center; justify-content: center; gap: 0.5rem; padding: 0.75rem 1.4rem;
  font-size: 0.875rem; font-weight: 700; letter-spacing: -0.01em; text-decoration: none;
  color: var(--color-teal); background: var(--color-white); border: 1px solid var(--color-graphite-200);
  border-radius: var(--radius-lg); transition: background .16s, border-color .16s; }
.rv__cta svg { width: 1.05rem; height: 1.05rem; transition: transform .16s; }
.rv__cta:hover { background: var(--color-teal-50); border-color: var(--color-teal); }
.rv__cta:hover svg { transform: translateX(3px); }
.rv__cta:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 3px; }
.rv__aside-note { font-size: 0.75rem; color: var(--text-muted); max-width: 16rem; line-height: 1.4; }

/* ── Featured testimonial – right zone of the merged panel. Contained customer photo
   beside a pull-quote; navigation consolidated into one control row below. ── */
.rv__carousel { position: relative; display: flex; flex-direction: column; gap: clamp(1rem, 2vw, 1.5rem);
  padding: clamp(1.25rem, 2.5vw, 1.75rem); }
.rv__track[hidden] { display: none; }   /* data source only */

/* equal-height 2-column: photo | (text + thumbnails). align-items:stretch makes the photo
   column match the text column's height exactly – image edge-to-edge, no top/bottom padding. */
.rv__feature-card { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(1rem, 2vw, 1.5rem); align-items: stretch;
  scroll-margin-top: 8rem; }   /* clear the sticky header when a thumbnail tap scrolls the featured photo into view */

.rv__feature-media { margin: 0; position: relative; border-radius: var(--radius);
  overflow: hidden; background: var(--color-paper);
  aspect-ratio: 1 / 1; align-self: center; }   /* always square (never stretched by the taller text column); kill the <figure> UA margin → true edge-to-edge */

/* right column: review text (centered, grows) on top, thumbnail nav pinned below.
   A constant min-height keeps the card the same size across reviews so the thumbnails
   don't shift with review length – but the reservation is on the BLOCK, not the text,
   so short reviews get no awkward internal gap. */
.rv__feature-body { min-width: 0; display: flex; flex-direction: column; justify-content: center;
  gap: clamp(1rem, 1.5vw, 1.25rem); min-height: 25rem; }
.rv__feature-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.rv__feature-cam { position: absolute; left: 0.75rem; bottom: 0.75rem; display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.01em; color: var(--color-white);
  background: rgba(20,22,26,0.55); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  padding: 0.32rem 0.65rem; border-radius: var(--radius-pill); }
.rv__feature-cam svg { width: 0.9rem; height: 0.9rem; }

/* The stars→title→text→name group is TOP-packed, so the author name always hugs the
   review text (never pushed down). A min-height reserves the tallest case (a full
   3-line review), making this block a CONSTANT height on every slide – so the thumbnail
   nav below it sits at a FIXED position regardless of how long each review is. The
   leftover space on shorter reviews falls below the name, not between text and name. */
.rv__feature-content { flex: 0 0 auto; justify-content: flex-start; min-height: 15.75rem;
  position: relative; display: flex; flex-direction: column; gap: 0.7rem; padding: 0; }
/* stars and the decorative quote share one row – quote right-aligned, both centred on the line */
.rv__feature-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.rv__feature-quote { flex: none; width: 3rem; height: 3rem; color: var(--color-teal-50); pointer-events: none; }
.rv__feature-stars { position: relative; }
.rv__feature-stars svg { width: 1.5rem; height: 1.5rem; }
.rv__feature-title { margin: 0; font-size: clamp(1.2rem, 2vw, 1.5rem); font-weight: 700; letter-spacing: -0.015em; line-height: 1.2; color: var(--color-digital-black); }
.rv__feature-text { margin: 0; font-size: 1rem; line-height: 1.6; color: var(--color-graphite-700);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }   /* max 3 lines, truncate rest */
.rv__feature-foot { display: flex; align-items: center; gap: 0.7rem; margin-top: 0.5rem; flex-wrap: wrap; }
.rv__feature-who { display: flex; flex-direction: column; line-height: 1.25; }
.rv__feature-who b { font-size: 0.8125rem; font-weight: 700; color: var(--color-digital-black); }
.rv__feature-who time { font-size: 0.8125rem; color: var(--text-muted); }

/* crossfade when switching reviews */
.rv__feature-media img, .rv__feature-stars, .rv__feature-title, .rv__feature-text, .rv__feature-foot { transition: opacity .2s ease; }
.rv__feature-card.is-swapping .rv__feature-media img,
.rv__feature-card.is-swapping .rv__feature-stars,
.rv__feature-card.is-swapping .rv__feature-title,
.rv__feature-card.is-swapping .rv__feature-text,
.rv__feature-card.is-swapping .rv__feature-foot { opacity: 0; }

/* label + control row grouped; label clarifies the thumbnails are OTHER customers */
.rv__navwrap { display: flex; flex-direction: column; gap: 0.65rem; }
.rv__navlabel { margin: 0; text-align: center; font-size: 0.75rem; font-weight: 700;
  letter-spacing: 0.15em; line-height: 1.4; text-transform: uppercase; color: var(--color-graphite-600); }
/* one control row: prev · customer-photo thumbnails · next */
.rv__navrow { display: flex; align-items: center; gap: 0.75rem; }

/* square icon buttons, consistent with the PLP carousel arrows */
.rv__feature-arrow { flex: none; display: grid; place-items: center; width: 2.5rem; height: 2.5rem; cursor: pointer;
  background: var(--color-white); color: var(--color-digital-black);
  border: 1px solid var(--color-graphite-300); border-radius: var(--radius);
  transition: background .15s ease, color .15s ease, border-color .15s ease; }
.rv__feature-arrow svg { width: 1.5rem; height: 1.5rem; }
.rv__feature-arrow:hover { background: var(--color-teal); color: var(--color-white); border-color: var(--color-teal); }
.rv__feature-arrow:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(1,82,83,0.10); }

/* customer-photo thumbnail nav – fills the row between the arrows */
.rv__thumbsnav { flex: 1; min-width: 0; display: flex; justify-content: center; flex-wrap: wrap; gap: 0.6rem; }
.rv__thumbnav-btn { width: 3.5rem; height: 3.5rem; padding: 0; cursor: pointer; overflow: hidden; flex: none;
  background: var(--color-white); border: 1px solid var(--color-graphite-200); border-radius: var(--radius);
  opacity: 0.6; transition: opacity .18s, transform .18s, border-color .18s; }
.rv__thumbnav-btn img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rv__thumbnav-btn:hover { opacity: 1; transform: translateY(-2px); }
.rv__thumbnav-btn:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; }
/* selected uses the same 1px border weight as the others, just teal */
.rv__thumbnav-btn[aria-current="true"] { opacity: 1; border-color: var(--color-teal); }

@media (max-width: 64rem) {
  /* stack the panel: summary (tinted) above, testimonial below.
     minmax(0,1fr) + min-width:0 stop the column expanding to min-content and overflowing */
  .rv__layout { grid-template-columns: minmax(0, 1fr); }
  .rv__summary, .rv__carousel { min-width: 0; }
}
@media (max-width: 48rem) {
  /* stack: photo on top, then text + thumbnails */
  .rv__feature-card { grid-template-columns: minmax(0, 1fr); }
  .rv__feature-card, .rv__feature-content, .rv__feature-media, .rv__feature-body { min-width: 0; }
  .rv__feature-media { aspect-ratio: 1 / 1; min-height: 0; }
  .rv__feature-body { min-height: 0; }   /* no reserved height when stacked */
  .rv__feature-text { max-width: none; }
  /* overflow-x:auto also clips the Y axis, so pad top+bottom equally, otherwise
     the active thumbnail's teal top border is cut off (invisible) */
  .rv__thumbsnav { flex-wrap: nowrap; overflow-x: auto; justify-content: flex-start; scrollbar-width: none; padding: 0.25rem 0; }
  .rv__thumbsnav::-webkit-scrollbar { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .rv__feature-media img, .rv__feature-content > *, .rv__feature-arrow, .rv__thumbnav-btn, .rv__cta, .rv__cta svg { transition: none !important; }
}
/* Footer legal links only wrap ≤640px in the design system, so they overflow the
   viewport across the tablet range. Extend the wrap up to 75rem (PDP-scoped; desktop
   ≥1200px and the shared Home page are untouched). */
@media (max-width: 75rem) {
  .footer__legal-links { flex-wrap: wrap; white-space: normal; justify-content: center; text-align: center; column-gap: var(--sp-4); row-gap: var(--sp-2); }
}

/* ============================================================
   PRODUCT INFO – sticky scroll-spy nav + 5 stacked sections
   (Beschreibung · Bewertungen · Downloads · Technische Details · Frage)
   ============================================================ */
html { scroll-behavior: smooth; }
/* Stop the page rubber-banding past its content – the overscroll bounce beyond the
   dark footer otherwise exposes the white body background as a blank strip on iOS.
   `none` pins the root scroller to its bounds so the scroll stops at the footer. */
html, body { overscroll-behavior-y: none; }

/* --pdp-header-h tracks the live (compacting) site-header height; pdp-b.js keeps it
   in sync so the sticky bars below always sit flush under the header. */
:root { --pdp-header-h: 81px; }
.psx-nav { position: sticky; top: var(--pdp-header-h); z-index: 50; background: var(--color-white);
  border-top: 1px solid var(--color-graphite-200); border-bottom: 1px solid var(--color-graphite-200);
  box-shadow: 0 4px 10px -8px rgba(10,20,20,0.2); }

/* ── Sticky handoff (desktop + mobile) ─────────────────────────────────────
   The green quickbar pins directly under the header while scrolling. As the
   product-section nav (.psx-nav) rises into its slot, pdp-b.js fades the quickbar
   from opaque to transparent so the section nav slides up UNDER it and takes its
   place – a clean baton-pass, not two stacked bars. */
body.is-scrolled #quickbar {
  position: sticky; top: var(--pdp-header-h); z-index: 45;
  box-shadow: 0 8px 18px -14px rgba(1,40,40,0.55);
  will-change: opacity;
}
/* Mobile: pin the contact bar ABOVE the section nav (which is z-index:50) so the nav
   visibly slides UNDER it while it fades. Kept below the header (z-index:90). Mobile
   only – desktop keeps the config-dock stacking untouched. */
@media (max-width: 47.9375rem) {
  body.is-scrolled #quickbar { z-index: 55; }
}
.psx-nav__inner { display: flex; gap: 1rem; align-items: stretch; }
/* Only the tab links scroll horizontally; the CTA is a non-scrolling sibling that stays
   pinned at the right edge (was buried at the far end of the scroll on mobile). flex:1 +
   min-width:0 lets this strip fill the row and shrink/scroll inside its own box. */
.psx-nav__tabs { display: flex; gap: clamp(1.75rem, 4vw, 3.75rem); align-items: stretch;
  flex: 1 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none; }
.psx-nav__tabs::-webkit-scrollbar { display: none; }
/* Mobile: fade the tab strip on whichever edge still has content off-screen, so it
   reads as horizontally scrollable. JS sets data-scroll (start|middle|end|none);
   the default (start) fades only the right edge. */
@media (max-width: 47.9375rem) {
  /* Bleed the strip to the right screen edge so a tab visibly runs off-screen
     (the "content continues" cue), instead of stopping inside the container
     padding where it just looks like the nav ends. Inner padding keeps the
     last tab off the very edge once you've scrolled to the end. */
  .psx-nav__tabs { --nav-fade: 1.75rem;
    margin-right: calc(-1 * clamp(var(--sp-6), 4vw, 56px));
    padding-right: clamp(var(--sp-6), 4vw, 3.5rem);
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - var(--nav-fade)), transparent 100%);
            mask-image: linear-gradient(90deg, #000 calc(100% - var(--nav-fade)), transparent 100%); }
  .psx-nav__tabs[data-scroll="middle"] {
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--nav-fade), #000 calc(100% - var(--nav-fade)), transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 var(--nav-fade), #000 calc(100% - var(--nav-fade)), transparent 100%); }
  .psx-nav__tabs[data-scroll="end"] {
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--nav-fade));
            mask-image: linear-gradient(90deg, transparent 0, #000 var(--nav-fade)); }
  .psx-nav__tabs[data-scroll="none"] { -webkit-mask-image: none; mask-image: none; }
}
/* "Termin vereinbaren" action pinned to the right of the section nav – opens the same
   Kontakt & Service modal as the green contact bar (via data-cm-open). */
.psx-nav__termin { align-self: center; flex: none; display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.55rem 1.2rem; border: 0; border-radius: var(--radius);
  background: var(--color-teal); color: var(--color-white); font-family: inherit; font-size: 0.875rem; font-weight: 700; line-height: 1;
  white-space: nowrap; cursor: pointer; transition: background .15s ease, opacity .2s ease, transform .2s ease;
  /* Hidden until the green contact bar leaves the viewport and the section nav takes
     over the sticky slot (pdp-b.js adds .psx-nav--cta-on on handoff). The slot stays
     reserved so the reveal doesn't reflow the tab strip. */
  opacity: 0; visibility: hidden; transform: translateY(-2px); pointer-events: none; }
.psx-nav--cta-on .psx-nav__termin { opacity: 1; visibility: visible; transform: none; pointer-events: auto; }
.psx-nav__termin svg { width: 1.05rem; height: 1.05rem; }
@media (max-width: 47.9375rem) { .psx-nav__termin { display: none; } }   /* mobile: hide the CTA so the section tabs get the full width */
.psx-nav__termin:hover { background: var(--color-teal-hover); }
.psx-nav__link { position: relative; display: inline-flex; align-items: center; gap: 0.35rem; white-space: nowrap;
  padding: 1.05rem 0.15rem; font-size: 1rem; font-weight: 700; letter-spacing: -0.01em;
  color: var(--color-graphite-700); text-decoration: none; border-bottom: 2px solid transparent;
  transition: color .15s, border-color .15s; }
.psx-nav__link:hover { color: var(--color-digital-black); }
.psx-nav__link.is-active { color: var(--color-teal); border-bottom-color: var(--color-teal); }
.psx-nav__count { font-size: 0.8em; font-weight: 700; color: var(--text-muted); }
.psx-nav__link.is-active .psx-nav__count { color: var(--color-teal); }

/* One rhythm token for every full-width info section, so the vertical padding
   (and therefore the gap between any two sections) is identical at all widths. */
:root { --sx-rhythm: clamp(2.75rem, 5vw, 4.5rem);   /* between top-level sections */
  --sx-blockgap: clamp(2rem, 4vw, 3rem); }           /* between major blocks WITHIN a section (intro/features/spec) – one value so the rhythm is consistent */
.psx-sec { scroll-margin-top: 7.75rem; padding: var(--sx-rhythm) 0; }
.psx-sec--alt { background: var(--color-paper); }
.rv { scroll-margin-top: 7.75rem; }   /* reviews section = Bewertungen target */

.psx-eyebrow { margin: 0 0 0.6rem; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.15em; line-height: 1.4; text-transform: uppercase; color: var(--color-graphite-600); }
.psx-title { margin: 0 0 1rem; font-size: clamp(1.6rem, 3vw, 2.25rem); font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; color: var(--color-digital-black); }
.psx-lead { margin: 0 0 2rem; max-width: 62ch; font-size: 1.125rem; line-height: 1.6; color: var(--color-graphite-700); }
/* Section intro/body copy: 18px on desktop, 16px on mobile */
@media (max-width: 47.9375rem) { .psx-lead, .rv__sub { font-size: 1rem; } }

/* Center the intro text block (eyebrow · title · lead) in the Bewertungen,
   Downloads and Technische-Details sections only – Beschreibung and FAQ keep
   their left-aligned headers. The lead's max-width box is re-centered via auto
   side margins so the copy sits centered under the title. */
#sx-bewertungen .psx-eyebrow, #sx-bewertungen .psx-title, #sx-bewertungen .psx-lead,
#sx-downloads .psx-eyebrow,   #sx-downloads .psx-title,   #sx-downloads .psx-lead,
#sx-technik .psx-eyebrow,     #sx-technik .psx-title,     #sx-technik .psx-lead {
  text-align: center;
}
#sx-bewertungen .psx-lead, #sx-downloads .psx-lead, #sx-technik .psx-lead {
  margin-left: auto; margin-right: auto;
}

/* spec chips (camera / IP ratings / SIP) */
.psx-chips { list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1.1rem 0 0; padding: 0; }
.psx-chips li { padding: 0.35rem 0.75rem; border-radius: var(--radius); background: var(--color-paper); border: 1px solid var(--color-graphite-300); font-size: 0.75rem; font-weight: 700; color: var(--color-digital-black); }
/* selectable LED colour dots */
.psx-dots { list-style: none; display: flex; flex-wrap: wrap; gap: 0.6rem; margin: 1.1rem 0 0; padding: 0; }
/* flat, refined swatches – clean e-commerce colour dots (hairline ring so light
   colours read on white; gentle hover lift) */
.psx-dots { gap: 0.7rem; }
.psx-dots li { width: 1.6rem; height: 1.6rem; border-radius: var(--radius); cursor: pointer;
  box-shadow: 0 0 0 1px rgba(20,22,25,0.14); transition: transform .16s ease, box-shadow .16s ease; }
.psx-dots li:hover { transform: scale(1.09); box-shadow: 0 0 0 1px rgba(20,22,25,0.18), 0 3px 8px rgba(20,22,25,0.14); }
/* Highlight badges under the intro title */
.psx-badges { list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0 0 1.4rem; padding: 0; }
.psx-badges li { padding: 0.4rem 0.85rem; border: 1px solid var(--color-graphite-300); border-radius: var(--radius-pill); font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-teal); background: var(--color-white); }
/* extra breathing room above the alternating rows */
.psx-rows { margin-top: clamp(2rem, 4vw, 3.25rem); }
/* ===== Neue Features – premium branded panel ===========================
   A deep-teal rounded panel holding white icon-cards. Each card lifts on
   hover, its icon chip fills teal, and a short accent underline grows out
   from the title. Responsive 3 → 2 → 1 columns. ==================== */
.nfeat { margin: var(--sx-blockgap) 0 0; padding: clamp(1.75rem,3.5vw,3rem) clamp(1.25rem,3vw,2.75rem);
  border-radius: var(--radius-xl);
  /* Aspect-independent depth: a fixed-size soft spotlight centred on the top edge reads
     the same on a short/wide desktop panel and a tall/narrow mobile one, over a gentle
     in-hue teal→teal-700 vertical deepening – no dark pooling in a corner */
  background:
    radial-gradient(1100px 500px at 50% -80px, rgba(92,219,211,0.16) 0%, transparent 60%),
    linear-gradient(180deg, var(--color-teal) 0%, var(--color-teal-700) 100%);
  color: var(--color-white); }
.nfeat__head { text-align: center; max-width: 44rem; margin: 0 auto clamp(1.5rem,3vw,2.25rem); }
.nfeat__eyebrow { display: inline-block; margin: 0 0 0.7rem; padding: 0.28rem 0.7rem; border-radius: var(--radius-pill);
  background: rgba(92,219,211,0.12); border: 1px solid rgba(92,219,211,0.24);
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--color-mint); }
.nfeat__title { margin: 0 0 0.6rem; font-size: clamp(1.5rem,2.6vw,2.05rem); font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; color: var(--color-white); }
.nfeat__lead { margin: 0; font-size: 1rem; line-height: 1.6; color: var(--on-dark-muted); }

.nfeat__grid { list-style: none; margin: 0; padding: 0; display: grid;
  grid-template-columns: 1fr; gap: clamp(0.85rem,1.5vw,1.15rem); }
@media (min-width: 40rem)  { .nfeat__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 60rem)  { .nfeat__grid { grid-template-columns: repeat(3, 1fr); } }
/* glass cards on the teal panel (style borrowed from the XDM10 .hl-card): a faint
   translucent-white fill + hairline light border, white text, lift + teal-glow on hover */
.nfeat__card { position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 0.55rem;
  padding: clamp(1.25rem,2vw,1.6rem); background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.14); border-radius: var(--radius-lg);
  box-shadow: 0 2px 6px -2px rgba(0,20,20,0.35), inset 0 1px 0 rgba(255,255,255,0.08);
  transition: transform .3s ease, background .3s ease, border-color .3s ease, box-shadow .3s ease; }
.nfeat__card:hover { transform: translateY(-6px); background: rgba(255,255,255,0.10); border-color: var(--color-mint);
  box-shadow: 0 14px 26px -14px rgba(0,20,20,0.5), inset 0 1px 0 rgba(255,255,255,0.12); }
.nfeat__cardtitle { position: relative; margin: 0; padding-bottom: 0.55rem; font-size: 1.125rem; font-weight: 700;
  letter-spacing: -0.01em; color: var(--color-white); }
.nfeat__cardtitle::after { content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 1.5rem;
  background: var(--color-mint); border-radius: var(--radius-sm); transition: width .25s ease; }
.nfeat__card:hover .nfeat__cardtitle::after { width: 3rem; }
.nfeat__cardtext { margin: 0; font-size: 0.875rem; line-height: 1.55; color: var(--on-dark-muted); }

/* Beschreibung – pinned scrollytelling: sticky image (left) swaps as the text
   scenes (right) scroll past. Uses position:sticky, so no scroll-jacking. */
.psx-story__grid { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: clamp(2rem,5vw,4.5rem); align-items: start; margin: clamp(1rem,2vw,1.75rem) 0 var(--sx-blockgap); }
/* Centre the image on the TRUE viewport middle (50vh): the pin spans the full viewport and
   flexbox centres the image, so its midpoint sits on the exact centre line. The sticky nav
   and buy-bar float over the pin's empty top/bottom edges. No position math, no drift. */
.psx-story__pin { position: sticky; top: 0; height: 100vh;
  display: flex; align-items: center; justify-content: center; }
.psx-story__media { position: relative; width: 100%; height: min(70vh, 34rem); max-height: 100%;
  border-radius: var(--radius-lg); overflow: hidden; background: var(--color-paper); }
.psx-story__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transform: scale(1.06); transition: opacity .6s ease, transform 1.4s cubic-bezier(.2,.7,.2,1); }
.psx-story__img.is-active { opacity: 1; transform: scale(1); }
.psx-story__img--contain { object-fit: contain; background: var(--color-white); padding: clamp(1rem, 3vw, 2.25rem); }

/* ── Bewertungen (Reviews) – happy carousel + detailed list with rating sidebar ── */
/* shared stars */
.rvw-stars { display: inline-flex; gap: 2px; color: var(--color-star); line-height: 0; }
.rvw-stars svg { width: 1rem; height: 1rem; display: block; }
.rvw-stars--lg svg { width: 1.35rem; height: 1.35rem; }
.rvw-review__head .rvw-stars svg { width: 1.35rem; height: 1.35rem; }   /* review-list rating – was tiny at 1rem */
/* Icon-only verified badge: the seal alone (label kept for screen readers + a hover
   tooltip via title). No text, so no gap and the box shrinks to the seal. */
.rvw-verified { display: inline-flex; align-items: center; gap: 0; font-size: 0.8125rem; font-weight: 700; color: var(--color-teal); white-space: nowrap; }
.rvw-verified svg { width: 1.35rem; height: 1.35rem; }
.rvw-vlabel { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.rvw-author { font-weight: 800; color: var(--color-digital-black); }

/* happy carousel */
.rvw-happy { margin: 0 0 var(--sx-blockgap); }   /* between-major-block rhythm (happy carousel → main reviews) */
/* larger, more prominent stars on the carousel cards */
.rvw-happy-card .rvw-stars { gap: 3px; }
.rvw-happy-card .rvw-stars svg { width: 1.35rem; height: 1.35rem; }
.rvw-happy__head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 1.25rem; }
.rvw-happy__title { margin: 0; font-size: 1.25rem; font-weight: 700; letter-spacing: -0.01em; color: var(--color-digital-black); }
.rvw-arrows { display: flex; gap: 0.5rem; flex: none; }
.rvw-arrow { width: 40px; height: 40px; display: grid; place-items: center; border: 1px solid var(--color-graphite-300); border-radius: var(--radius); background: var(--color-white); color: var(--color-digital-black); cursor: pointer; transition: border-color .15s ease, color .15s ease, opacity .15s ease; }
.rvw-arrow svg { width: 1.5rem; height: 1.5rem; }
.rvw-arrow:hover:not(:disabled) { border-color: var(--color-teal); color: var(--color-teal); }
.rvw-arrow:disabled { opacity: 0.35; cursor: default; }
.rvw-carousel { list-style: none; margin: 0; padding: 0 0 0.5rem; display: flex; gap: 1rem; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.rvw-carousel::-webkit-scrollbar { display: none; }
.rvw-happy-card { scroll-snap-align: start; flex: 0 0 clamp(16rem, 27vw, 19.5rem); box-sizing: border-box; display: flex; flex-direction: column; background: var(--color-white); border: 1px solid var(--color-graphite-300); border-radius: var(--radius-lg); overflow: hidden; }
.rvw-happy-card__media { aspect-ratio: 4 / 3; background: var(--color-paper); }
.rvw-happy-card__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Mobile: show 2.5 cards per row (the half-card peek signals more to scroll).
   Cards + internals scale down to stay premium/legible at the smaller size. */
@media (max-width: 47.9375rem) {
  /* 1.5 cards per row – one full card plus a half-card peek to signal more to scroll */
  .rvw-carousel { gap: 0.75rem; }
  .rvw-carousel .rvw-happy-card { flex: 0 0 calc((100% - 0.75rem) / 1.5); }
}
.rvw-happy-card__body { flex: 1; display: flex; flex-direction: column; gap: 0.85rem; padding: 1.25rem 1.4rem 1.4rem; }
.rvw-happy-quote { margin: 0; font-size: 1rem; line-height: 1.6; color: var(--color-digital-black);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; }
/* byline row: name + line-divider + date grouped on the left, verified seal pushed to the right */
.rvw-happy-foot { margin-top: auto; display: flex; flex-direction: row; align-items: center; gap: 0.5rem; padding-top: 0.35rem; }
.rvw-happy-foot .rvw-author { order: 1; font-size: 0.875rem; }
.rvw-meta { display: contents; }   /* promote the date + seal into the foot's flex row so they can be ordered independently */
.rvw-happy-foot time { order: 2; font-size: 0.75rem; color: var(--color-graphite-700); }
.rvw-happy-foot time::before { content: ""; display: inline-block; width: 1px; height: 0.85em; margin-right: 0.5rem; vertical-align: -0.1em; background: var(--color-graphite-300); }   /* line divider between name and date */
.rvw-happy-foot .rvw-verified { order: 3; margin-left: auto; }   /* right-aligned seal */

/* detailed list + sticky summary sidebar */
.rvw-main { display: grid; grid-template-columns: minmax(0,1fr) 24rem; gap: clamp(1.5rem,3.5vw,3.5rem); align-items: start; }
/* Sticky rating box. Default: pinned 2px below the sticky top bar (compacting site
   header var + the 61px section-tabs nav), so it sits just under the bar and slides
   underneath it on scroll (the nav's z-index 50 keeps it on top). Tracks the header
   as it compacts, so the gap stays 2px instead of drifting. */
.rvw-summary { grid-column: 2; grid-row: 1; position: sticky; top: calc(var(--pdp-header-h) + 61px + 2px); }
/* Only on roomy (tall) desktop windows: vertically centre it in the space below the
   header, so big screens keep the balanced look without a large gap under the card. */
@media (min-width: 56.3125rem) and (min-height: 56.25rem) {
  .rvw-summary { top: calc(50vh - 12.35rem); }
}
.rvw-summary__inner { background: var(--color-paper); border: 1px solid var(--color-graphite-300); border-radius: var(--radius-lg); padding: clamp(1.5rem,2.5vw,2rem); }
.rvw-summary__top { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.25rem; }
.rvw-summary__score { font-size: 3rem; font-weight: 800; line-height: 1; letter-spacing: -0.02em; color: var(--color-digital-black); }
.rvw-summary__scoremeta { display: flex; flex-direction: column; gap: 0.35rem; }
.rvw-summary__count { margin: 0; font-size: 0.8125rem; color: var(--color-graphite-700); }
.rvw-dist { display: grid; gap: 0.5rem; margin-bottom: 1.5rem; }
.rvw-dist-row { display: grid; grid-template-columns: 3.75rem 1fr 1.75rem; align-items: center; gap: 0.6rem; font-size: 0.875rem; color: var(--color-graphite-700); }
.rvw-dist-label { font-weight: 700; }   /* match the top summary card's "5 Sterne" labels */
/* track: white fill + graphite outline, matching the CTA and the featured-section bars */
.rvw-dist-bar { height: 0.5rem; border-radius: var(--radius-pill); background: var(--color-white); border: 1px solid var(--color-graphite-200); overflow: hidden; }
.rvw-dist-bar i { display: block; height: 100%; background: var(--color-star); border-radius: var(--radius-pill); }
.rvw-dist-val { text-align: right; font-variant-numeric: tabular-nums; }
.rvw-cta { display: inline-flex; align-items: center; justify-content: center; width: 100%; box-sizing: border-box; gap: 0.5rem; padding: 0.7rem 1.25rem; border: 2px solid var(--color-teal); border-radius: var(--radius); background: var(--color-white); color: var(--color-teal); font-size: 1rem; font-weight: 700; text-decoration: none; cursor: pointer; transition: background .15s ease, color .15s ease; }
.rvw-cta:hover { background: var(--color-teal); color: var(--color-white); }
/* "Wie funktionieren Bewertungen?" disclosure – quiet explanatory note under the
   CTA, divided by a hairline so it reads as secondary to the score + write-review
   action. Collapsed by default: the summary row is the tap target, the body reveals
   on open and the chevron rotates to signal state. */
.rvw-howto { margin-top: 1.25rem; padding-top: 1.25rem; border-top: 1px solid var(--color-graphite-300); }
/* Legally required info – always visible (no longer a collapsible disclosure) */
.rvw-howto__title { margin: 0; font-size: 1rem; font-weight: 700; color: var(--color-digital-black); }
.rvw-howto__text { margin: 0.55rem 0 0; font-size: 0.875rem; line-height: 1.55; color: var(--color-graphite-700); }
/* inline verified badge inside the explainer copy (replaces the old „Verifizierter Kauf" text).
   Rendered as plain inline text (not an atomic inline-flex chip) so the sentence wraps
   word-by-word; the seal icon is glued to the first word (no whitespace between them). */
.rvw-howto__badge { font-size: 0.8125rem; font-weight: 700; color: var(--color-teal); }
.rvw-howto__badge svg { display: inline-block; width: 1rem; height: 1rem; margin-right: 0.2rem; vertical-align: -0.15em; }
.rvw-howto__link { display: inline-block; margin-top: 0.6rem; font-size: 0.8125rem; font-weight: 600;
  color: var(--color-teal); text-decoration: underline; text-underline-offset: 2px; }
.rvw-howto__link:hover { color: var(--color-teal-600); }
.rvw-list { grid-column: 1; grid-row: 1; display: flex; flex-direction: column; }
/* review card: block flow – the star rating sits on its own row ABOVE the title
   (head precedes the title in the DOM), everything left-aligned and full width. */
.rvw-review { padding: clamp(1.25rem,2.5vw,1.75rem) 0; border-top: 1px solid var(--color-graphite-300); }
.rvw-review:first-child { border-top: 0; padding-top: 0; }
.rvw-review__head { display: flex; align-items: center; gap: 0.85rem; margin: 0 0 0.35rem; }
.rvw-review__title { margin: 0 0 0.4rem; font-size: 1.125rem; font-weight: 700; letter-spacing: -0.01em; color: var(--color-digital-black); }
.rvw-review__text { margin: 0; font-size: 1rem; line-height: 1.65; color: var(--color-graphite-700);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; line-clamp: 4; overflow: hidden; }
/* tap/click a truncated review to expand it in place (a real button gives keyboard access) */
.rvw-review__text.is-clamped { cursor: pointer; }
.rvw-review__text.is-expanded { -webkit-line-clamp: unset; line-clamp: unset; overflow: visible; cursor: pointer; }
.rvw-review__more { display: inline-block; margin-top: 0.45rem; padding: 0; background: none; border: 0; cursor: pointer;
  font: inherit; font-size: 0.8125rem; font-weight: 700; color: var(--color-teal); }
.rvw-review__more:hover { color: var(--color-teal-600); }
.rvw-review__more:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; border-radius: var(--radius-sm); }
/* Customer-uploaded photos – a compact thumbnail strip between the review text and
   its byline. Square tiles, capped at three per review; each opens a lightbox. */
.rvw-review__media { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.9rem 0 0; }
.rvw-shot { flex: none; width: 4.5rem; height: 4.5rem; padding: 0; overflow: hidden; cursor: pointer;
  background: none; border: 1px solid var(--color-graphite-300); border-radius: var(--radius);
  transition: border-color .15s ease, transform .15s ease; }
.rvw-shot:hover { border-color: var(--color-teal); transform: translateY(-1px); }
.rvw-shot:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; }
.rvw-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Lightbox overlay (injected once by JS) */
/* ── Premium review-photo viewer – dark image stage + white context panel ── */
.rvw-lightbox { position: fixed; inset: 0; z-index: 1000; display: none; align-items: center; justify-content: center;
  padding: clamp(0.75rem, 3vw, 2.5rem); }
.rvw-lightbox.is-open { display: flex; }
.rvw-lightbox__backdrop { position: absolute; inset: 0; background: rgba(8,10,12,0.78); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
/* card is a grid: image spans the left column full-height; header (top) and body
   (scroll) stack in the right column */
.rvw-lb { position: relative; z-index: 1; display: grid; grid-template-columns: 1.15fr 0.85fr; grid-template-rows: auto minmax(0, 1fr);
  width: min(64rem, 100%); height: min(85vh, 37rem);   /* definite height → the image column is ~square (matches the square review photos) instead of a text-driven sliver */
  background: var(--color-white); border-radius: var(--radius-xl); overflow: hidden; box-shadow: var(--shadow-modal);
  animation: rvwLbIn .22s cubic-bezier(.2,.7,.3,1) both; }
.rvw-lb__stage { grid-column: 1; grid-row: 1 / 3; }
.rvw-lb__head { grid-column: 2; grid-row: 1; }
.rvw-lb__body { grid-column: 2; grid-row: 2; }
@keyframes rvwLbIn { from { opacity: 0; transform: translateY(0.75rem) scale(0.985); } to { opacity: 1; transform: none; } }

/* Close – bare icon button; square press/tap feedback (never circular) */
.rvw-lb__close { flex: none; width: 2.25rem; height: 2.25rem; margin-right: -0.5625rem; display: grid; place-items: center; cursor: pointer;   /* neg margin = (btn − icon)/2 so the icon box lines up with the body content's right edge */
  color: var(--color-graphite-600); background: transparent; border: 0; border-radius: var(--radius); transition: background .15s; }
.rvw-lb__close:hover { background: var(--color-graphite-100); }
.rvw-lb__close:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; }
.rvw-lb__close svg { width: 1.125rem; height: 1.125rem; }

/* Image stage */
.rvw-lb__stage { position: relative; flex: 1.15 1 0%; min-width: 0; display: flex; align-items: center; justify-content: center;
  overflow: hidden; background: radial-gradient(120% 120% at 50% 0%, #16191d 0%, #0b0d10 100%); }
/* Absolute-fill the stage instead of being an in-flow flex child: iOS Safari
   stretches an <img> that has object-fit + percentage height inside a flexbox
   (it ignores the fit and fills the box). Absolute positioning gives it a
   definite containing block so object-fit is always honoured. */
.rvw-lb__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; }
/* subtle top scrim keeps the photo counter legible over a full-bleed photo */
.rvw-lb__stage::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 5rem; z-index: 1; pointer-events: none;
  background: linear-gradient(to bottom, rgba(0,0,0,0.3), rgba(0,0,0,0)); }
.rvw-lb__counter { position: absolute; top: clamp(0.75rem, 2vw, 1.1rem); left: clamp(0.75rem, 2vw, 1.1rem); z-index: 3;
  padding: 0.28rem 0.65rem; border-radius: 999px; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.03em;
  color: var(--on-dark-strong); background: rgba(0,0,0,0.5); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  font-variant-numeric: tabular-nums; }
/* nav arrows – design-system slider arrow: square var(--radius), white outline, inverts on hover (never circular) */
.rvw-lb__nav { position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  width: 2.75rem; height: 2.75rem; display: grid; place-items: center; line-height: 1; cursor: pointer;
  color: var(--color-white); background: rgba(0,0,0,0.28); border: 1px solid rgba(255,255,255,0.85); border-radius: var(--radius);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); transition: background .15s ease, color .15s ease, transform .12s ease; }
.rvw-lb__nav[data-dir="prev"] { left: clamp(0.5rem, 1.5vw, 1rem); }
.rvw-lb__nav[data-dir="next"] { right: clamp(0.5rem, 1.5vw, 1rem); }
@media (hover: hover) { .rvw-lb__nav:hover { background: var(--color-white); color: var(--color-digital-black); } }
.rvw-lb__nav:active { background: var(--color-white); color: var(--color-digital-black); transform: translateY(-50%) scale(0.94); }
.rvw-lb__nav:focus-visible { outline: 2px solid var(--color-white); outline-offset: 2px; }
.rvw-lb__nav svg { width: 1.4rem; height: 1.4rem; }

/* title bar – anchors the review context and holds the close control */
.rvw-lb__head { min-width: 0; display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.9rem clamp(1.35rem, 2.4vw, 1.9rem); border-bottom: 1px solid var(--color-graphite-300); }   /* horizontal padding matches the body so the title + close align with the content column */
.rvw-lb__headtitle { margin: 0; font-size: 1.25rem; font-weight: 700; line-height: 1.35; letter-spacing: -0.01em; color: var(--color-digital-black); }
/* body is a fixed-height column: title/meta pinned top, text scrolls, gallery pinned bottom */
.rvw-lb__body { min-width: 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden;
  padding: clamp(1.35rem, 2.4vw, 1.9rem); }
/* top row – review title (left) paired with the star rating (right);
   sized so a typical title fits on one line beside the stars */
.rvw-lb__top { flex: none; display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
.rvw-lb__title { flex: 1 1 auto; margin: 0; font-size: 1.0625rem; font-weight: 700; letter-spacing: -0.01em; line-height: 1.35; color: var(--color-digital-black);
  /* Cap at 2 lines (ellipsis beyond) so a long product name can't grow this row
     and shove the meta/text/gallery down. Full name stays on hover (title attr). */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; }
.rvw-lb__stars.rvw-lb__stars { flex: none; margin-top: 0.1rem; }
.rvw-lb__stars svg { width: 1.15rem; height: 1.15rem; }
/* meta line – identical style to the review-list byline: bold name · line-divider · date · icon-only seal */
.rvw-lb__meta { flex: none; margin: 0.5rem 0 0; display: flex; align-items: center; flex-wrap: wrap; gap: 0 0.6rem;
  font-size: 0.875rem; color: var(--color-graphite-700); }
.rvw-lb__author { font-weight: 800; color: var(--color-digital-black); }
.rvw-lb__date::before { content: ""; display: inline-block; width: 1px; height: 0.85em; margin-right: 0.6rem; vertical-align: -0.1em; background: var(--color-graphite-300); }   /* line divider between name and date */
/* verified seal – icon only, right after the date (same as the review list) */
.rvw-lb__badge { display: inline-flex; align-items: center; flex: none; color: var(--color-teal); }
.rvw-lb__badge svg { width: 1.25rem; height: 1.25rem; }
/* text is the scroll region: it grows to fill the space so the photo gallery
   always sits pinned at the bottom; scrolls internally when the review is long */
.rvw-lb__text { flex: 1 1 auto; min-height: 0; overflow-y: auto; margin: 1.15rem 0 0; padding-right: 0.5rem;
  font-size: 0.875rem; line-height: 1.7; color: var(--color-graphite-700);
  scrollbar-width: thin; scrollbar-color: rgba(0,0,0,0.18) transparent; }
/* minimal scrollbar – thin pill thumb, no track, no stepper buttons */
.rvw-lb__text::-webkit-scrollbar { width: 5px; }
.rvw-lb__text::-webkit-scrollbar-track { background: transparent; }
.rvw-lb__text::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.18); border-radius: 999px; }
.rvw-lb__text::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.32); }
.rvw-lb__text::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
/* photo gallery – flows directly beneath the review as a connected section
   (a hairline divider ties it to the text); styled identically to the
   review-preview thumbnail nav (.rv__thumbnav-btn) for a consistent system */
.rvw-lb__gallery { flex: none; margin-top: 1.5rem; padding-top: 1.5rem; border-top: 1px solid var(--color-graphite-200); }
.rvw-lb__gallery-label { margin: 0 0 0.65rem; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.15em;
  line-height: 1.4; text-transform: uppercase; color: var(--color-graphite-600); }
.rvw-lb__thumbs { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.rvw-lb__thumb { flex: none; width: 3.5rem; height: 3.5rem; padding: 0; cursor: pointer; overflow: hidden;
  background: var(--color-white); border: 1px solid var(--color-graphite-200); border-radius: var(--radius);
  opacity: 0.6; transition: opacity .18s, transform .18s, border-color .18s; }
.rvw-lb__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rvw-lb__thumb:hover { opacity: 1; transform: translateY(-2px); }
.rvw-lb__thumb:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; }
.rvw-lb__thumb[aria-selected="true"] { opacity: 1; border-color: var(--color-teal); }

@media (max-width: 52rem) {
  /* mobile: header + image stay FIXED at the top; only the review body scrolls
     beneath them, so the image remains visible while reading the review */
  /* One fixed sheet size for EVERY review – short quote or long text, one photo or
     several. Height is content-independent (dvh, toolbar-aware; vh fallback) so the
     modal never resizes to fit; long text scrolls inside the body instead. */
  .rvw-lb { display: flex; flex-direction: column; width: min(30rem, 100%);
    height: 90vh; height: 90dvh; max-height: 90dvh; overflow: hidden; }
  .rvw-lb__head { order: 1; flex: none; }
  .rvw-lb__close { width: 2.75rem; height: 2.75rem; margin-right: -0.8125rem; }   /* 44px touch target; neg margin = (2.75 − 1.125)/2 keeps the icon box aligned to the content edge */
  /* Image is a fixed SHARE of the sheet (not vh) so the photo/text split stays constant
     across reviews and always agrees with the sheet's own height unit. */
  .rvw-lb__stage { order: 2; flex: none; height: 45%; }
  .rvw-lb__body { order: 3; flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: thin; scrollbar-color: rgba(0,0,0,0.18) transparent; }
  .rvw-lb__body::-webkit-scrollbar { width: 5px; }
  .rvw-lb__body::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.18); border-radius: 999px; }
  .rvw-lb__body::-webkit-scrollbar-button { display: none; }
  .rvw-lb__text { flex: none; min-height: 0; overflow: visible; padding-right: 0; }
  /* gallery flows right after the full text; symmetric top/bottom padding, no divider */
  .rvw-lb__gallery { margin-top: 0; padding-top: clamp(1.35rem, 2.4vw, 1.9rem); border-top: 0; }
  .rvw-lb__nav { width: 2.75rem; height: 2.75rem; }
  .rvw-lb__nav svg { width: 1.3rem; height: 1.3rem; }
}
@media (prefers-reduced-motion: reduce) { .rvw-lb { animation: none; } }

/* ── Carousel cards are tappable → they open the same two-pane review lightbox
   as the detailed-review photos. Give them a clear interactive affordance. ── */
.rvw-happy-card--clickable { cursor: pointer; transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease; }
.rvw-happy-card--clickable:hover { transform: translateY(-3px); box-shadow: var(--shadow-md, 0 8px 24px rgba(8,10,12,0.1)); border-color: var(--color-graphite-400, var(--color-graphite-300)); }
.rvw-happy-card--clickable:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 3px; }
/* Mobile "Info & Hilfecenter" quickbar: entries are placeholders for now – the panel
   still expands/collapses, but the individual links are non-interactive. */
@media (max-width: 767px) {
  .quickbar .qa, .quickbar .qa-cta { pointer-events: none; cursor: default; }
}
.rvw-review__foot { margin-top: 0.7rem; display: flex; align-items: center; gap: 0.6rem; font-size: 0.875rem; }
.rvw-review__foot .rvw-author { font-size: 0.875rem; }
.rvw-review__foot time { color: var(--color-graphite-700); }
.rvw-review__foot time::before { content: ""; display: inline-block; width: 1px; height: 0.85em; margin-right: 0.6rem; vertical-align: -0.1em; background: var(--color-graphite-300); }   /* line divider between name and date */
/* verified seal in the byline row: icon only (label stays visually hidden), sitting
   right after the name/date instead of pushed to the far right */
.rvw-review__foot .rvw-verified svg { width: 1.25rem; height: 1.25rem; }
/* provenance – quiet secondary metadata under the byline (how the review reached us):
   translation note + origin shop. Uses the DS caption/metadata token (--text-muted,
   graphite-600) so it reads as fine print yet meets WCAG AA contrast. */
.rvw-review__prov { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.5rem;
  margin-top: 0.55rem; font-size: 0.75rem; line-height: 1.35; color: var(--text-muted); }
/* each note as a soft pill/chip so the provenance reads as discrete metadata tags.
   Same surface language as the review summary side container (.rvw-summary__inner):
   #F5F6FA fill + a 1px graphite-300 border. */
.rvw-prov { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.25rem 0.7rem;
  border-radius: 999px; background: #F5F6FA; border: 1px solid var(--color-graphite-300); }
.rvw-prov svg { width: 0.9rem; height: 0.9rem; flex: none; color: inherit; }
/* label/value hierarchy inside the origin pill: "Herkunft:" is the emphasised title,
   "Shop Frankreich" the quiet value */
.rvw-prov__label { color: var(--text-secondary); font-weight: 600; }   /* graphite-700 #54545C */
.rvw-prov__val { color: var(--text-muted); font-weight: 400; }
/* per-surface fit: keep the pill row from stretching/shrinking in the flex columns of
   the lightbox body and the featured card, and hug the byline it belongs to */
.rvw-lb__prov { flex: none; }
.rv__feature-prov { margin-top: 0.6rem; }
.rvw-list__more { align-self: flex-start; margin-top: 1.5rem; display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.875rem; font-weight: 700; color: var(--color-teal); text-decoration: none; }
.rvw-list__more svg { width: 1.1rem; height: 1.1rem; transition: transform .15s ease; }
.rvw-list__more:hover svg { transform: translateX(3px); }
@media (max-width: 56.25rem) {
  .rvw-main { grid-template-columns: 1fr; }
  .rvw-summary, .rvw-list { grid-column: 1; grid-row: auto; }
  /* mobile/tablet: summary stacks above the list and scrolls normally (NOT pinned);
     the sticky behaviour is desktop-only (base rule). */
  .rvw-summary { position: static; margin-bottom: 2rem; }
}
.psx-story__scenes { display: flex; flex-direction: column; }
.psx-story__scene { min-height: 68vh; display: flex; flex-direction: column; justify-content: center; gap: 0.6rem;
  opacity: 0.4; transition: opacity .4s ease; }
.psx-story__scene.is-current { opacity: 1; }
.psx-story__step { font-size: 0.75rem; font-weight: 800; letter-spacing: 0.14em; color: var(--color-teal); }
/* desktop + tablet: title 32px, body 18px; mobile (≤767px) stays smaller */
.psx-story__scene h3 { margin: 0; font-size: 2rem; font-weight: 700; letter-spacing: -0.015em; line-height: 1.2; color: var(--color-digital-black); }
.psx-story__scene p { margin: 0; font-size: 1.125rem; line-height: 1.65; color: var(--color-graphite-700); max-width: 42ch; }
@media (max-width: 47.9375rem) {
  .psx-story__scene h3 { font-size: 1.35rem; }
  .psx-story__scene p { font-size: 1rem; }
}
/* scene fact bullets – teal check marks, matching the page's feature-bullet style */
.psx-facts { list-style: none; margin: 0.9rem 0 0; padding: 0; display: grid; gap: 0.5rem; max-width: 42ch; }
.psx-facts li { position: relative; padding-left: 1.6rem; font-size: 0.875rem; line-height: 1.5; color: var(--color-graphite-700); }
.psx-facts li::before { content: ""; position: absolute; left: 0.15rem; top: 0.15em; width: 0.4rem; height: 0.72rem; border: solid var(--color-teal); border-width: 0 2px 2px 0; transform: rotate(45deg); }
.psx-facts a { color: var(--color-teal); text-decoration: underline; text-underline-offset: 2px; }

/* Mobile shows each scene's own image inline (above its text) instead of the desktop
   sticky cross-fade – so every image is seen, not just the first. Hidden on desktop. */
.psx-story__sceneimg { display: none; }
@media (max-width: 56.25rem) {
  .psx-story__grid { grid-template-columns: 1fr; gap: 1rem; }
  .psx-story__pin { display: contents; }   /* dissolve the sticky pin on mobile (media is hidden, scenes stack) */
  .psx-story__media { display: none; }
  .psx-story__scene { min-height: 0; opacity: 1; margin-bottom: 2.25rem; }
  .psx-story__sceneimg { display: block; aspect-ratio: 4 / 3; margin: 0 0 1rem; border-radius: var(--radius-lg); overflow: hidden; background: var(--color-paper); }
  .psx-story__sceneimg img, .psx-story__sceneimg video { width: 100%; height: 100%; object-fit: cover; display: block; }
  .psx-story__sceneimg--contain { background: var(--color-white); }
  .psx-story__sceneimg--contain img { object-fit: contain; padding: clamp(0.75rem, 3vw, 1.5rem); }
}
@media (prefers-reduced-motion: reduce) {
  .psx-story__media { position: relative; top: 0; height: auto; aspect-ratio: 4 / 3; }
  .psx-story__img { transition: none; }
  .psx-story__scene { opacity: 1; min-height: 0; margin-bottom: 1.75rem; }
}

/* Downloads */
/* ===== Downloads – premium document cards ==============================
   Modernised on the existing markup (no HTML change, so both index versions
   inherit it): airier cards with a soft rest-shadow and a teal lift on hover,
   a folded-corner "PDF" sheet badge, and a circular download button whose
   arrow nudges down on hover. ========================================= */
.psx-dl { list-style: none; margin: 0; padding: 0; display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(19rem,100%),1fr));
  grid-auto-rows: 1fr; align-items: stretch; gap: 1rem; }

.psx-dl__item { position: relative; overflow: hidden; height: 100%; box-sizing: border-box;
  display: flex; align-items: center; gap: 1.1rem; padding: 1.15rem 1.25rem; text-decoration: none;
  background: var(--color-white); border: 1px solid var(--color-graphite-300); border-radius: var(--radius-lg);
  transition: border-color .2s ease, box-shadow .25s ease, transform .2s ease; }
/* soft teal wash that fades in from the top-right on hover */
.psx-dl__item::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(130% 140% at 100% 0%, rgba(1,82,83,0.07), transparent 55%);
  opacity: 0; transition: opacity .25s ease; }
.psx-dl__item:hover { border-color: var(--color-teal); transform: translateY(-3px);
  box-shadow: 0 4px 12px -8px rgba(1,82,83,0.28); }
.psx-dl__item:hover::after { opacity: 1; }
.psx-dl__item:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 3px; }

/* PDF badge → a document sheet with a folded top-right corner */
.psx-dl__badge { position: relative; flex: none; display: grid; place-items: center;
  width: 2.75rem; height: 3.25rem; border-radius: var(--radius-lg);
  background: linear-gradient(158deg, var(--color-white) 0%, var(--color-teal-50) 100%);
  border: 1px solid var(--color-teal-75); color: var(--color-teal);
  font-size: 0.75rem; font-weight: 800; letter-spacing: 0.05em;
  box-shadow: 0 1px 3px -2px rgba(1,82,83,0.25); transition: transform .2s ease; }
.psx-dl__badge::before { content: ""; position: absolute; top: 0; right: 0; width: 0; height: 0;
  border-top: 0.75rem solid var(--color-white); border-left: 0.75rem solid transparent;
  border-top-right-radius: 0.55rem; filter: drop-shadow(-1px 1px 1px rgba(1,82,83,0.12)); }
.psx-dl__item:hover .psx-dl__badge { transform: translateY(-2px) rotate(-3deg); }

.psx-dl__text { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; flex: 1; }
.psx-dl__text b { font-size: 0.875rem; font-weight: 700; line-height: 1.3; color: var(--color-digital-black); }
.psx-dl__text span { font-size: 0.75rem; color: var(--color-graphite-700); }

/* circular download button – arrow nudges down on hover */
.psx-dl__icon { flex: none; box-sizing: content-box; width: 1.1rem; height: 1.1rem; padding: 0.55rem;
  border-radius: 50%; background: var(--color-teal-50); color: var(--color-teal);
  transition: background .2s ease, color .2s ease; }
.psx-dl__item:hover .psx-dl__icon { background: var(--color-teal); color: var(--color-white); }
@media (prefers-reduced-motion: no-preference) {
  .psx-dl__item:hover .psx-dl__icon { animation: dl-nudge .7s ease; }
  @keyframes dl-nudge { 0%,100% { transform: translateY(0); } 45% { transform: translateY(3px); } }
}

/* Technische Details */
.psx-spec { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(20rem,100%),1fr)); gap: clamp(1.25rem,3vw,2.5rem) clamp(1.5rem,4vw,3.5rem); }
.psx-spec__grouptitle { margin: 0 0 0.35rem; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--color-teal); }
.psx-spec__list { margin: 0; }
.psx-spec__list > div { display: flex; justify-content: space-between; gap: 1rem; padding: 0.65rem 0; border-top: 1px solid var(--color-graphite-200); }
.psx-spec__list dt { margin: 0; font-size: 0.875rem; color: var(--color-graphite-600); }
.psx-spec__list dd { margin: 0; font-size: 0.875rem; font-weight: 700; color: var(--color-digital-black); text-align: right; }

/* ===== Anschlussübersichten – diagram galleries (replaces the live dropdowns) =====
   Open, labeled groups instead of accordions: a titled block + a responsive grid
   of diagram cards. Each schematic sits on a clean white surface with its caption;
   clicking opens a zoom lightbox (techdia JS) since the diagrams must be read close. */
/* ===== Merkmale & Technische Daten – flexible attribute list (end of description) =
   Content-agnostic: each row is a label + a wrapping set of clickable chips (or a
   plain value for measurements), so it adapts to any product – one value or a
   dozen, few attributes or many. Closes with a quiet manufacturer/safety footer. */
.dspec { margin-top: var(--sx-blockgap); }
.dspec__title { margin: 0 0 clamp(1.1rem,2vw,1.4rem); font-size: clamp(1.15rem,1.9vw,1.4rem); font-weight: 700; letter-spacing: -0.01em; color: var(--color-digital-black); }
/* white surface with #DADADA (graphite-300) borders/dividers */
.dspec__list { margin: 0; background: var(--color-white); border: 1px solid var(--color-graphite-300);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0; border-bottom: 0; overflow: hidden;
  box-shadow: none; }   /* bottom opened so the mfr footer fuses on as the table's foot (all widths) */
.dspec__row { display: grid; grid-template-columns: 1fr; }
.dspec__row + .dspec__row { border-top: 1px solid var(--color-graphite-300); }
@media (min-width: 40rem) { .dspec__row { grid-template-columns: minmax(11rem, 16rem) 1fr; } }
.dspec__key { display: flex; align-items: center; flex-wrap: wrap; padding: 0.8rem 1.15rem; background: var(--color-paper); font-size: 0.875rem; font-weight: 700; line-height: 1.35; color: var(--color-digital-black); }
@media (min-width: 40rem) { .dspec__key { border-right: 1px solid var(--color-graphite-300); } }
.dspec__sub { margin-left: 0.4rem; font-size: 0.75rem; font-weight: 600; color: var(--color-graphite-700); white-space: nowrap; }
.dspec__val { display: flex; flex-wrap: wrap; align-items: center; align-content: center; gap: 0.45rem 0.55rem; min-width: 0; margin: 0; padding: 0.8rem 1.15rem; }   /* margin:0 removes the browser's default 40px <dd> indent so the value block's left padding matches the title's */
.dspec__val--plain { font-size: 0.875rem; font-weight: 700; color: var(--color-digital-black); font-variant-numeric: tabular-nums; }
/* clickable value chip (System, Farbe, Klingeltaster, Türöffner-Bedienung …) */
.dspec__chip { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.3rem 0.65rem; border-radius: var(--radius-pill);
  background: var(--color-teal-50); border: 1px solid var(--color-teal-75); color: var(--color-teal);
  font-size: 0.75rem; font-weight: 600; text-decoration: none; white-space: nowrap;
  transition: background .15s ease, border-color .15s ease, color .15s ease; }
.dspec__chip:hover { background: var(--color-teal); border-color: var(--color-teal); color: var(--color-white); }
.dspec__chip:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; }
/* small colour dot inside Farbe chips */
.dspec__dot { flex: none; width: 0.85rem; height: 0.85rem; border-radius: var(--radius); box-shadow: inset 0 0 0 1px rgba(0,0,0,0.2); }
.dspec__dot--light { box-shadow: inset 0 0 0 1px var(--color-graphite-400); }
.dspec__dot--custom { background: conic-gradient(from 210deg, #e8443c, #f2c223, #2dbe6c, #3cc6e6, #9457e8, #e8443c); }

.dspec__mfr { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 0.9rem;
  margin: 0; padding: 0.9rem 1.15rem; background: var(--color-white);
  border: 1px solid var(--color-graphite-300); border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  box-shadow: none;
  font-size: 0.75rem; line-height: 1.5; color: var(--color-graphite-700); }   /* footer fused to the spec table: matching border + rounded bottom, no floating gap */
.dspec__mfr > svg { flex: none; width: 1rem; height: 1rem; color: var(--color-graphite-600); }
.dspec__mfr span { min-width: 0; }
.dspec__mfr b { color: var(--color-graphite-700); font-weight: 700; }
.dspec__mfr a { color: var(--color-teal); text-decoration: underline; text-underline-offset: 2px; }
.dspec__safety { margin-left: auto; display: inline-flex; align-items: center; gap: 0.4rem; flex: none;
  padding: 0.4rem 0.8rem; border: 1px solid var(--color-red-600); border-radius: var(--radius-pill);
  color: var(--color-red-600) !important; font-weight: 700; text-decoration: none !important;
  transition: border-color .15s ease, color .15s ease, background .15s ease; }
.dspec__safety:hover { border-color: var(--color-red-600); background: var(--color-red-50); color: var(--color-red-600) !important; }
.dspec__safety svg { width: 1rem; height: 1rem; color: var(--color-red-600); }

/* ===== Technische Übersichten – master–detail on one unified surface =====
   A single bordered card split into a tinted category rail and a detail panel.
   One category at a time → no long scroll; the vertical rail is visually distinct
   from the horizontal mid-nav → no tabs-in-tabs. Collapses to a chip row on
   small screens. */
.techms { margin-top: 2rem; display: grid; grid-template-columns: 1fr;   /* title→content gap = the lead's 2rem, matching the other sections (Technik has no lead) */
  border: 1px solid var(--color-teal); border-radius: var(--radius-xl); overflow: hidden; background: var(--color-white); }
@media (min-width: 56rem) { .techms { grid-template-columns: 17rem 1fr; } }

/* rail – design-system dark band, consistent with .nfeat: a fixed-size soft top
   spotlight over a gentle in-hue teal→teal-700 vertical deepening (aspect-independent,
   so it reads the same on the tall desktop column and the short mobile row) */
.techms__rail { display: flex; flex-direction: row; gap: 0.2rem; padding: 0.6rem; overflow-x: auto; scrollbar-width: none;
  background:
    radial-gradient(1100px 500px at 50% -80px, rgba(92,219,211,0.16) 0%, transparent 60%),
    linear-gradient(180deg, var(--color-teal) 0%, var(--color-teal-700) 100%); }
.techms__rail::-webkit-scrollbar { display: none; }
@media (min-width: 56rem) {
  .techms__rail { flex-direction: column; gap: 0.2rem; padding: 0.85rem 0.7rem; overflow: visible; }
}

/* rail item on teal – light text/icon; active = a white pill with teal text/icon */
.techms__tab { flex: none; display: flex; align-items: center; gap: 0.7rem;
  padding: 0.65rem 0.75rem; border: 0; border-radius: var(--radius); background: transparent;
  text-align: left; cursor: pointer; white-space: nowrap; color: var(--on-dark-strong);
  transition: background .18s ease, color .18s ease; }
@media (min-width: 56rem) { .techms__tab { white-space: normal; } }
.techms__tab:hover { color: var(--color-white); background: rgba(255,255,255,0.10); box-shadow: inset 0 0 0 1px var(--color-mint); }
.techms__tab.is-active { color: var(--color-teal); background: var(--color-white); }
.techms__tab:focus-visible { outline: 2px solid var(--color-white); outline-offset: 2px; }
.techms__ico { flex: none; display: grid; place-items: center; width: 1.4rem; height: 1.4rem;
  color: var(--on-dark-muted); transition: color .18s ease; }
.techms__ico svg { width: 1.3rem; height: 1.3rem; }
.techms__tab:hover .techms__ico { color: var(--color-white); }
.techms__tab.is-active .techms__ico { color: var(--color-teal); }
.techms__tabtext { min-width: 0; flex: 1; }
.techms__tablabel { display: block; font-size: 0.875rem; font-weight: 600; line-height: 1.3; letter-spacing: -0.005em; }
.techms__tabsub { display: none; }
.techms__tab.is-active .techms__tablabel { font-weight: 700; }
.techms__count { flex: none; font-size: 0.75rem; font-weight: 700; padding: 0; background: none; color: inherit; }   /* match the label colour in every state (white / hover-white / active-teal) */

/* panel */
.techms__panel { padding: clamp(1.25rem,2.5vw,2rem); }
.techms__panel[hidden] { display: none; }
.techms__phead { display: flex; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; gap: 0.4rem 1rem; margin: 0 0 1.35rem; }
.techms__ptitle { margin: 0 0 0.25rem; font-size: clamp(1.1rem,1.7vw,1.3rem); font-weight: 700; letter-spacing: -0.01em; color: var(--color-digital-black); }
.techms__pdesc { margin: 0; font-size: 0.875rem; line-height: 1.5; color: var(--color-graphite-600); }
.techms__phint { display: inline-flex; align-items: center; gap: 0.35rem; flex: none; margin-top: 0.15rem; font-size: 0.75rem; font-weight: 600; color: var(--text-muted); }
.techms__phint svg { width: 1rem; height: 1rem; color: var(--color-teal); }
/* datasheet card (Datenblatt panel) */
.techms__doc { display: flex; align-items: center; gap: 1.1rem; padding: 1.25rem 1.35rem; text-decoration: none;
  background: var(--color-white); border: 1px solid var(--color-graphite-200); border-radius: var(--radius-lg);
  transition: border-color .2s ease, box-shadow .25s ease, transform .2s ease; }
.techms__doc:hover { border-color: var(--color-teal); transform: translateY(-2px); box-shadow: 0 8px 18px -14px rgba(1,82,83,0.28); }
.techms__doc-badge { flex: none; display: grid; place-items: center; width: 2.75rem; height: 3.25rem; border-radius: var(--radius-lg);
  background: linear-gradient(158deg,var(--color-white),var(--color-teal-50)); border: 1px solid var(--color-teal-75); color: var(--color-teal);
  font-size: 0.75rem; font-weight: 800; letter-spacing: 0.05em; }
.techms__doc-body { display: flex; flex-direction: column; gap: 0.2rem; flex: 1; min-width: 0; }
.techms__doc-body b { font-size: 0.875rem; font-weight: 700; color: var(--color-digital-black); }
.techms__doc-body span { font-size: 0.75rem; color: var(--color-graphite-600); }
.techms__doc-icon { flex: none; width: 1.35rem; height: 1.35rem; color: var(--color-teal); }

.techdia { margin-top: var(--sx-rhythm); }
.techdia__group + .techdia__group { margin-top: clamp(2rem,4vw,3rem); }
.techdia__grouphead { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem;
  margin: 0 0 1.1rem; padding-bottom: 0.7rem; border-bottom: 1px solid var(--color-graphite-200); }
.techdia__grouptitle { margin: 0; font-size: clamp(1.05rem,1.6vw,1.2rem); font-weight: 700; letter-spacing: -0.01em; color: var(--color-digital-black); }
.techdia__groupmeta { margin: 0; font-size: 0.75rem; color: var(--text-muted); }

.techdia__grid { list-style: none; margin: 0; padding: 0; display: grid;
  grid-template-columns: 1fr; gap: clamp(1rem,2vw,1.35rem); }
@media (min-width: 40rem) { .techdia__grid { grid-template-columns: repeat(2, 1fr); } }

.techdia__item { display: flex; flex-direction: column; gap: 0.7rem; min-width: 0; }
.techdia__shot { position: relative; display: block; width: 100%; padding: clamp(0.75rem,2vw,1.25rem); cursor: zoom-in;
  background: var(--color-white); border: 1px solid var(--color-graphite-200); border-radius: var(--radius-lg); overflow: hidden;
  transition: border-color .2s ease, box-shadow .25s ease, transform .2s ease; }
/* The technical diagrams are all square (1:1) source files – frame them square so the
   drawing fills the box instead of floating pillar-boxed inside a too-wide 4/3 frame
   (which read as "stretched" on wide desktops). object-fit:contain stays as a safety
   net for any non-square image added later; aspect-ratio reserves space (no CLS). */
.techdia__shot img { display: block; width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: contain; }
.techdia__shot:hover { border-color: var(--color-teal); transform: translateY(-2px);
  box-shadow: 0 8px 18px -14px rgba(1,82,83,0.28); }
.techdia__shot:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 3px; }
/* zoom affordance – a circular magnifier badge that appears on hover/focus */
.techdia__zoom { position: absolute; top: 0.7rem; right: 0.7rem; width: 2.1rem; height: 2.1rem; display: grid; place-items: center;
  border-radius: 50%; background: rgba(1,82,83,0.92); color: var(--color-white); opacity: 0; transform: scale(0.85);
  transition: opacity .2s ease, transform .2s ease; }
.techdia__zoom svg { width: 1.1rem; height: 1.1rem; }
.techdia__shot:hover .techdia__zoom, .techdia__shot:focus-visible .techdia__zoom { opacity: 1; transform: scale(1); }
.techdia__caption { font-size: 0.875rem; font-weight: 600; line-height: 1.4; color: var(--color-graphite-700); }

/* Diagram lightbox (injected by pdp-b.js) – reuses the review-lightbox look */
.tdiag-lightbox { position: fixed; inset: 0; z-index: 1000; display: none; align-items: center; justify-content: center;
  gap: 0.5rem; padding: clamp(1rem,4vw,3rem); background: rgba(10,12,14,0.86); }
.tdiag-lightbox.is-open { display: flex; }
.tdiag-lightbox figure { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 0.9rem; max-width: min(92vw, 1100px); }
.tdiag-lightbox img { max-width: 100%; max-height: 80vh; background: var(--color-white); border-radius: var(--radius); box-shadow: 0 18px 50px rgba(0,0,0,0.45); }
.tdiag-lightbox figcaption { color: var(--on-dark-strong); font-size: 0.875rem; text-align: center; }
.tdiag-lightbox__close { position: absolute; top: clamp(0.75rem,2vw,1.4rem); right: clamp(0.75rem,2vw,1.4rem);
  width: 2.75rem; height: 2.75rem; display: grid; place-items: center; font-size: 1.6rem; line-height: 1; cursor: pointer;
  color: var(--color-white); background: none; border: 0; transition: color .15s ease, transform .15s ease; }
.tdiag-lightbox__close:hover { color: var(--on-dark-strong); transform: scale(1.08); }
.tdiag-lightbox__close svg { width: 1.25rem; height: 1.25rem; }
/* nav arrows – design-system slider arrow: square var(--radius), white outline, inverts on hover (never circular) */
.tdiag-lightbox__nav { position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 2.75rem; height: 2.75rem; display: grid; place-items: center; line-height: 1;
  cursor: pointer; color: var(--color-white); background: rgba(0,0,0,0.28); border: 1px solid rgba(255,255,255,0.85); border-radius: var(--radius);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); transition: background .15s ease, color .15s ease, transform .12s ease; }
.tdiag-lightbox__nav[data-dir="prev"] { left: clamp(0.5rem, 1.5vw, 1rem); }
.tdiag-lightbox__nav[data-dir="next"] { right: clamp(0.5rem, 1.5vw, 1rem); }
@media (hover: hover) { .tdiag-lightbox__nav:hover { background: var(--color-white); color: var(--color-digital-black); } }
.tdiag-lightbox__nav:active { background: var(--color-white); color: var(--color-digital-black); transform: translateY(-50%) scale(0.94); }
.tdiag-lightbox__nav:focus-visible { outline: 2px solid var(--color-white); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .pdp-lightbox__nav:active, .rvw-lb__nav:active, .tdiag-lightbox__nav:active { transform: translateY(-50%); }
}
.tdiag-lightbox__nav svg { width: 1.4rem; height: 1.4rem; }
@media (max-width: 48rem) {
  .tdiag-lightbox__nav { width: 2.75rem; height: 2.75rem; }
  .tdiag-lightbox__nav svg { width: 1.3rem; height: 1.3rem; }
}

/* Frage / FAQ – ported from the produktionsprozess page (.faq), mapped to PDP tokens */
.faq__inner { display: grid; grid-template-columns: 1fr 1.6fr; gap: clamp(1.5rem, 4vw, 4rem); align-items: start; }
.faq__support { background: var(--color-paper); border: 1px solid var(--color-graphite-300); border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 3vw, 2rem); align-self: start; position: sticky; top: 7.5rem; }
.faq__support h3 { margin: 0; font-size: 1.375rem; font-weight: 700; letter-spacing: -0.01em; color: var(--color-digital-black); }
.faq__support p { margin: 0.75rem 0 0; font-size: 0.875rem; line-height: 1.6; color: var(--color-graphite-700); }
.faq__cta { display: inline-flex; width: 100%; align-items: center; justify-content: center; gap: 0.5rem; margin-top: 1.5rem;
  padding: 0.8rem 1.4rem; font-size: 0.875rem; font-weight: 700; text-decoration: none; color: var(--color-white);
  background: var(--color-teal); border-radius: var(--radius); transition: background .15s; }
.faq__cta:hover { background: var(--color-teal-600); }
.faq__cta svg { width: 1.05rem; height: 1.05rem; }
.faq__phone { margin-top: 1.5rem; padding: 1.25rem; background: var(--color-white); border: 1px solid var(--color-graphite-300);
  border-radius: var(--radius); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; color: var(--color-graphite-600); }
.faq__phone strong { display: block; margin-top: 0.375rem; color: var(--color-teal); font-size: 1.375rem; font-weight: 700; letter-spacing: -0.01em; text-transform: none; }
.faq__phone-hours { display: block; margin-top: 0.375rem; font-size: 0.75rem; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--color-graphite-600); }

/* ═══ "Zum Kundensupport" → "Eine Frage zum Produkt stellen" form modal ═══
   Self-contained, qf-namespaced module. Spec (fields, floating labels, success
   state, validation) ported from the VDM10 working page, remapped onto the
   Metzler design tokens used here. */
.qf-overlay { position: fixed; inset: 0; z-index: 9999; display: flex; align-items: center; justify-content: center; padding: 1rem;
  background: rgba(0,0,0,0.45); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
.qf-overlay[hidden] { display: none; }
.qf-dialog { width: 100%; max-width: 40rem; max-height: 90vh; display: flex; flex-direction: column; overflow: hidden;
  background: var(--color-white); border-radius: var(--radius-xl); box-shadow: var(--shadow-modal); animation: qfIn .2s ease; }
@keyframes qfIn { from { opacity: 0; transform: translateY(0.5rem) scale(0.985); } to { opacity: 1; transform: none; } }
.qf-head { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1.25rem 1.5rem; border-bottom: 1px solid var(--color-graphite-200); }
.qf-head-t { font-size: 1.25rem; font-weight: 700; line-height: 1.35; letter-spacing: -0.01em; color: var(--color-digital-black); }
.qf-close { flex: none; width: 2.25rem; height: 2.25rem; margin-right: -0.5625rem; display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  color: var(--color-graphite-600); background: transparent; border: 0; border-radius: var(--radius); transition: background .15s; }   /* neg margin = (btn − icon)/2 so the icon box lines up with the body's right edge */
.qf-close:hover { background: var(--color-graphite-100); }
.qf-close:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; }
.qf-close svg { width: 1.125rem; height: 1.125rem; }
.qf-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 1.5rem; }
/* Grab handle – only shown on the mobile bottom sheet; signals the swipe-to-dismiss gesture. */
.qf-grip { display: none; }
.qf-dialog.qf-dragging { animation: none; transition: none; }
.qf-dialog.qf-settling { transition: transform .25s cubic-bezier(.4,0,.2,1); }

.qf-form { display: flex; flex-direction: column; gap: 1.25rem; }
.qf-field { display: flex; flex-direction: column; gap: 0.5rem; }
.qf-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
@media (max-width: 32.5rem) { .qf-row { grid-template-columns: 1fr; } }

.qf-wrap { position: relative; }
.qf-control { display: block; width: 100%; box-sizing: border-box; padding: 0.7rem 0.9375rem; font: inherit; font-size: 1rem;
  color: var(--color-digital-black); background: var(--color-white); border: 1px solid var(--color-graphite-300);
  border-radius: var(--radius); outline: none; transition: border-color .15s; }
.qf-control:focus { border-color: var(--color-teal); }
.qf-wrap label { position: absolute; left: 0.9375rem; top: 50%; transform: translateY(-50%); z-index: 1; pointer-events: none;
  font-size: 1rem; line-height: 1.4; white-space: nowrap; color: var(--color-graphite-500); transition: all .15s ease; }
.qf-control:focus + label,
.qf-control:not(:placeholder-shown) + label { left: 0.6875rem; top: -0.5625rem; transform: none;
  font-size: 0.75rem; color: var(--color-digital-black); background: var(--color-white); padding: 0 0.3125rem; }
.qf-wrap--area .qf-control { min-height: 8rem; line-height: 1.5; resize: vertical; }
.qf-wrap--area label { top: 0.7rem; transform: none; }
.qf-wrap.qf--error .qf-control { border-color: var(--color-red); }
.qf-error-msg { display: block; margin-top: 0.35rem; font-size: 0.75rem; color: var(--color-red); }
.qf-req { color: var(--color-red); font-weight: 700; }

.qf-foot { display: flex; flex-direction: column; gap: 0.85rem; padding-top: 1rem; border-top: 1px solid var(--color-graphite-200); }
.qf-note { margin: 0; font-size: 0.75rem; color: var(--color-graphite-600); }
.qf-foot .qf-note + .qf-note { margin-top: -0.55rem; }
.qf-link { color: var(--color-teal); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.qf-link:hover { color: var(--color-teal-600); }
.qf-submit { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; width: 100%; height: 3.125rem;
  font: inherit; font-size: 1rem; font-weight: 700; cursor: pointer; color: var(--color-white); background: var(--color-teal);
  border: 0; border-radius: var(--radius); transition: background .15s; }
.qf-submit:hover { background: var(--color-teal-600); }
.qf-submit:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; }

.qf-success { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0.5rem 0.5rem 0.25rem; animation: qfPop .4s cubic-bezier(.34,1.56,.64,1); }
.qf-success[hidden] { display: none; }   /* setting display: flex above would otherwise defeat the [hidden] attribute */
@keyframes qfPop { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: none; } }
.qf-success-art { width: 8.75rem; height: 8.75rem; margin-bottom: 0.75rem; }
.qf-success-art svg { width: 100%; height: 100%; display: block; }
.qf-success-h { margin: 0 0 0.5rem; font-size: 1.375rem; font-weight: 700; letter-spacing: -0.01em; color: var(--color-digital-black); }
.qf-success-p { margin: 0 0 1.5rem; max-width: 22rem; font-size: 0.875rem; line-height: 1.55; color: var(--color-graphite-700); }
/* Mobile: dock to the bottom and slide up as a sheet (rounded top corners only) */
@media (max-width: 47.9375rem) {
  .qf-overlay { align-items: flex-end; padding: 0; }
  /* max-height is a % of the overlay, which JS sizes to the visual viewport while
     open – so when the keyboard opens the sheet shrinks to sit above it, keeping
     the submit button reachable instead of hidden behind the keyboard. */
  .qf-dialog { max-width: none; width: 100%; max-height: 92%;
    border-radius: var(--radius-xl) var(--radius-xl) 0 0; animation: qfSheet .3s cubic-bezier(.4,0,.2,1); }
  .qf-grip { display: block; flex: none; width: 2.25rem; height: 0.25rem; margin: 0.55rem auto -0.15rem;
    border-radius: 999px; background: var(--color-graphite-300); }
  .qf-head { padding-top: 0.85rem; }
  .qf-close { width: 2.75rem; height: 2.75rem; margin-right: -0.8125rem; }   /* ≥44px touch target; neg margin = (2.75 − 1.125)/2 aligns the icon box to the content edge */
  /* clear the iOS home indicator so the submit button is never under it */
  .qf-body { padding-bottom: calc(1.5rem + env(safe-area-inset-bottom)); }
}
@keyframes qfSheet { from { transform: translateY(100%); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) { .qf-dialog, .qf-success { animation: none; } }

.faq__list { display: flex; flex-direction: column; gap: 0; margin-top: 1.25rem; }
.faq__item { position: relative; border-bottom: 1px solid var(--color-graphite-300); transition: background .18s ease; }
.faq__item:first-child { border-top: 1px solid var(--color-graphite-300); }
.faq__item:hover { background: rgba(26,23,27,0.015); }
.faq__item[open] { background: rgba(1,82,83,0.025); }
.faq__item::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--color-teal); transform: scaleY(0); transition: transform .25s ease; }
.faq__item[open]::before { transform: scaleY(1); }
.faq__q { width: 100%; display: flex; justify-content: space-between; align-items: center; gap: 1.5rem; text-align: left;
  padding: 1.4rem 1.25rem; font-size: 1.125rem; font-weight: 700; color: var(--color-digital-black); cursor: pointer; list-style: none; transition: color .18s ease; }
.faq__q::-webkit-details-marker { display: none; }
.faq__item[open] .faq__q { color: var(--color-teal); }
/* plain chevron, no circle – reset the ring the Home design-system rule adds, to
   match the produktionsprozess FAQ (background:none · border:0 · flips on open) */
.faq__q-icon { flex: none; width: 1.5rem; height: 1.5rem; display: grid; place-items: center; background: none; border: 0; border-radius: 0; color: var(--color-graphite-600); transition: color .2s ease; }
.faq__q-icon svg { width: 1.5rem; height: 1.5rem; transition: transform .2s ease; }
.faq__item:hover .faq__q-icon, .faq__item[open] .faq__q-icon { color: var(--color-teal); background: none; border-color: transparent; }
.faq__item[open] .faq__q-icon svg { transform: scaleY(-1); }
.faq__a { padding: 0 1.25rem 1.5rem; max-width: none; font-size: 1rem; line-height: 1.9; color: var(--color-graphite-700); }
/* Inline link inside an answer – give it a clear, on-brand affordance (teal, semibold,
   underlined) with a trailing arrow that nudges on hover so it reads unmistakably as a link. */
.faq__link { color: var(--color-teal); font-weight: 700; border-radius: 2px;
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.22em; transition: color .15s ease; }
.faq__link svg { display: inline-block; width: 1rem; height: 1rem; margin-left: 0.35rem; vertical-align: -0.15em; transition: transform .18s ease; }
.faq__link:hover { color: var(--color-teal-hover); }
.faq__link:hover svg { transform: translateX(3px); }
.faq__link:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; }

@media (max-width: 56.25rem) {
  .faq__inner { display: flex; flex-direction: column; }
  .faq__inner > *:first-child { order: 2; }
  .faq__inner > *:last-child { order: 1; }
  .faq__support { position: static; }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .faq__item::before, .faq__q-icon svg { transition: none; }
}

/* ── Tasteful motion: scroll-reveal on blocks (JS adds .psx-anim so no-JS
   stays static); fully disabled under prefers-reduced-motion. ── */
@media (prefers-reduced-motion: no-preference) {
  .psx-anim { opacity: 0; transform: translateY(18px); transition: opacity .6s ease, transform .6s cubic-bezier(.2,.7,.2,1); }
  .psx-anim.is-in { opacity: 1; transform: none; }
}

/* ==========================================================================
   LARGE-PHONE PASS (≤ 767px) – the base mobile breakpoint (560px) is too low
   for wide phones (~561–767px), where several components fall into a cramped
   in-between layout. Realign them to the mobile treatment. Desktop / tablet
   ≥ 768px is untouched.
   ========================================================================== */
@media (max-width: 47.9375rem) {

  /* 1 · Config option cards → single-column rows (not cramped 2-col tiles) */
  .cfgb .cfg-opts { grid-template-columns: 1fr; gap: 0.5rem; }
  .cfgb .cfg-opts .cfg-opt { flex-direction: row; align-items: center; gap: 0.8rem; padding: 0.65rem 0.75rem; text-align: left; }
  .cfgb .cfg-opts .cfg-opt__thumb { width: 3.25rem; height: 3.25rem; flex: none; border-radius: var(--radius); }
  .cfgb .cfg-opts .cfg-opt__body { flex: 1 1 auto; min-width: 0; padding-right: 0; }
  .cfgb .cfg-opts .cfg-opt__desc { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .cfgb .cfg-opts .cfg-opt__price { margin: 0 0 0 auto; align-self: center; padding-top: 0; text-align: right; white-space: nowrap; }
  /* show the selection control (checkbox / radio) on mobile too – parity with desktop */
  .cfgb .cfg-opts .cfg-opt__mark { display: grid; position: relative; top: auto; left: auto; right: auto; flex: none; margin: 0; }
  .cfgb .cfg-opts .cfg-opt__rec { position: static; margin: 0 0 0 auto; align-self: center; }

  /* Product cards (Anschluss, Innenstationen – not the plain Gravur rows): the status
     label pill (Empfohlen / Ausverkauft) sits on a right-aligned top row; the content
     (thumb, name, description) and the price share the row below. Frees the title area
     so cards don't feel cramped. */
  .cfgb .cfg-opts:not(.cfg-opts--rows) .cfg-opt {
    display: grid; grid-template-columns: auto 3.25rem minmax(0, 1fr) auto;
    column-gap: 0.8rem; row-gap: 0.35rem; align-items: center; padding: 0.7rem 0.85rem; }
  /* row 1 – the label pill, top-right */
  .cfgb .cfg-opts:not(.cfg-opts--rows) .cfg-opt__rec,
  .cfgb .cfg-opts:not(.cfg-opts--rows) .cfg-opt.is-unavailable .cfg-opt__badge {
    position: static; grid-column: 1 / -1; grid-row: 1; justify-self: end; align-self: center; margin: 0; top: auto; right: auto; left: auto; }
  /* row 2 – content + price */
  .cfgb .cfg-opts:not(.cfg-opts--rows) .cfg-opt__mark  { grid-column: 1; grid-row: 2; }
  .cfgb .cfg-opts:not(.cfg-opts--rows) .cfg-opt__thumb { grid-column: 2; grid-row: 2; }
  .cfgb .cfg-opts:not(.cfg-opts--rows) .cfg-opt__body  { grid-column: 3; grid-row: 2; padding-right: 0; }
  .cfgb .cfg-opts:not(.cfg-opts--rows) .cfg-opt__price { grid-column: 4; grid-row: 2; justify-self: end; align-self: center; margin: 0; padding: 0; text-align: right; white-space: nowrap; }

  /* 2 · Trust badges → keep both in ONE row with identical frames (equal width +
     height), content centred. Stop the pre-line wrapping so "Garantie" never
     spills to a 3rd line; shrink the seal a touch so it all fits on wide phones. */
  .pdp-b .hl__badges, .pdp-b .hl__badges--infeat { display: flex; flex-direction: row; align-items: stretch; gap: 0.5rem; }
  .pdp-b .hl__badges .hl__badge,
  .pdp-b .hl__badges--infeat .hl__badge { flex: 1 1 0; min-width: 0; justify-content: center; gap: calc(0.5rem + 1px); padding: 0.55rem 0.4rem; }
  .pdp-b .hl__badges .hl__badge + .hl__badge,
  /* separate framed chips in a row – restore ALL borders (the ≤560px stack rule zeroes
     border-top/left for a vertical stack, but here they sit side by side with a gap) */
  .pdp-b .hl__badges--infeat .hl__badge + .hl__badge { border-left: 1px solid var(--color-graphite-300); border-top: 1px solid var(--color-graphite-300); }
  .pdp-b .hl__badge-pre { white-space: nowrap; font-size: 0.75rem; }
  .pdp-b .hl__badge-txt b { font-size: 0.875rem; }
  /* The gold seal is a starburst (points + negative space), so at an equal box it reads
     smaller than the solid flag disc – give it a larger box so the two marks look the
     same size, mirroring the desktop ratio. */
  .pdp-b .hl__badge-seal { width: 1.75rem; height: 1.75rem; }
  .pdp-b .hl__badge-seal--flag { width: 1.625rem; height: 1.625rem; }   /* square so border-radius:50% is a round flag coin, not a squashed oval */

  /* 3 · Spec table (Datenblatt) → block rows so the value pills sit flush-left,
     perfectly aligned under each section title (grid was offsetting the value cell) */
  .dspec__row { display: block; }
  /* Each section = a tinted title band (key, #F5F6FA) above a white value band (val).
     Keep BOTH bands' vertical padding symmetric (base 0.8rem) so the title is centred in
     its tinted band and the pill is centred in its white band – the pill was top-aligned
     (padding-top:0) and looked like it hugged the title with empty space below. */
  .dspec__key { border-right: 0; }
  .dspec__val { margin-left: 0; }   /* margin:0 (base) keeps the pill box flush-left under the title; padding stays the symmetric 0.8rem base */
  /* manufacturer / safety footer → fused to the spec table as one continuous card:
     the table's bottom edge is opened (no border / square corners) and the footer
     carries the matching side+bottom borders with a rounded bottom, so it reads as the
     table's foot rather than a note floating in the gap below it. The info icon leads
     the address inline; the safety notice is a full-width tinted banner on top. */
  .dspec__list { border-bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
  .dspec__mfr { flex-direction: row; flex-wrap: wrap; align-items: flex-start; gap: 0.25rem 0.5rem;
    margin-top: 0; padding: 1rem 1.15rem; background: var(--color-white);
    border: 1px solid var(--color-graphite-300); border-radius: 0 0 var(--radius-lg) var(--radius-lg); }
  .dspec__mfr > svg { flex: none; width: 0.95rem; height: 0.95rem; margin-top: 0.2rem; }
  .dspec__mfr > span { flex: 1 1 12rem; min-width: 0; }
  .dspec__safety { flex: 1 0 100%; width: 100%; justify-content: center; margin: 0.85rem 0 0;
    padding: 0.55rem 0.9rem; background: var(--color-red-50); }   /* full-width banner BELOW the manufacturer address */

  /* 4 · Delivery table → let the value wrap cleanly (key stays a fixed narrow column) */
  .bx-delivery__row { grid-template-columns: 8.5rem 1fr; }
  .bx-delivery__key { padding: 0.7rem 0.6rem 0.7rem 0.75rem; }
  .bx-delivery__val { padding: 0.7rem 0.75rem 0.7rem 0.6rem; }

  /* 5 · Preisdetails sheet foot → stack price above a full-width CTA. Keep the ending
     separator on mobile (it's dropped at the base for the wide desktop drawer) so the
     price/CTA block reads as a distinct footer under the item list. */
  /* Symmetric spacing around the price row: the gap above it (padding-top) equals the gap
     below it (flex gap to the CTA) and the padding below the CTA – a consistent 1.25rem. */
  .sheet__foot { flex-direction: column; align-items: stretch; gap: 1.25rem;
    border-top: 1px solid var(--color-graphite-200); margin-top: 0.5rem; padding-top: 1.25rem; }
  .sheet__foot .pdp-cta { min-width: 0; width: auto; }   /* full-width stacked CTA on mobile; drop the desktop fixed width */
  .sheet__price { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.15rem 0.5rem; }
  .sheet__pricelabel:not([hidden]) { flex: 1 0 100%; }   /* label on its own line, above the price */
  #bSheetCart { width: 100%; }

  /* 6 · Sticky purchase bar → chevron handle centred on top (opens the price sheet),
     then a single NON-wrapping row: title+price on the left (title truncates with
     ellipsis), CTA on the right. Chevron is absolute so it never forces a wrap. */
  #pdpStickyBar .pdp-stickybar__inner { position: relative; flex-wrap: nowrap; align-items: center; gap: 0.6rem; padding-top: 3rem; padding-bottom: 0.95rem; }   /* clear the chevron handle (top:0, ~2.3rem tall) so the content row below has a real gap and both are easy to tap */
  /* chevron handle: a generous, centred tap target that isn't glued to the top edge */
  .pdp-stickybar__details { position: absolute; top: 0; left: 50%; transform: translateX(-50%);
    flex: none; width: auto; min-height: 0; height: auto; margin: 0; padding: 0.45rem 2rem 0.35rem; border: 0; background: none; }
  .pdp-stickybar__details > span { display: none; }
  .pdp-stickybar__details svg { width: 1.5rem; height: 1.5rem; color: var(--color-graphite-400); }
  .pdp-stickybar__details:hover { border: 0; color: var(--color-graphite-600); }
  .pdp-stickybar__info { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; overflow: hidden; }
  .pdp-stickybar__name { max-width: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .pdp-stickybar__price { display: block; white-space: nowrap; }
  #pdpStickyBar .pdp-stickybar__cta { flex: 0 0 auto; margin-left: 0; padding: 0 1.1rem; }
}

/* Technik rail on mobile: collapse the sidebar into a clean full-width vertical
   list (same pattern as the desktop sidebar) – every option on its own aligned
   row, nothing clipped or fragmented. Desktop sidebar (≥ 56rem) is unaffected. */
@media (max-width: 55.9375rem) {
  .techms__rail { flex-direction: column; overflow-x: visible; gap: 0.15rem; }
  .techms__tab { flex: none; width: 100%; justify-content: flex-start; white-space: normal; }
}

/* ============================================================
   Accessibility
   ============================================================ */
/* Skip-to-content link – hidden until focused (keyboard entry point) */
.skip-link { position: fixed; top: 0.5rem; left: 0.5rem; z-index: 2000;
  padding: 0.6rem 1rem; background: var(--color-teal); color: var(--color-white);
  border-radius: var(--radius); font-size: 0.875rem; font-weight: 700; text-decoration: none;
  box-shadow: var(--shadow-modal); transform: translateY(-160%); transition: transform .15s ease; }
.skip-link:focus { transform: translateY(0); outline: 2px solid var(--color-white); outline-offset: 2px; }
#pdpMain:focus { outline: none; }   /* programmatic focus target, no visible ring */

/* Comfortable tap targets for standalone controls on mobile (WCAG 2.5.5/2.5.8) */
@media (max-width: 47.9375rem) {
  .pdp-media__toggle button { min-height: 2.25rem; }
  .bx-share { min-height: 2.75rem; }
}

/* Honour reduced-motion for every animation/transition and programmatic smooth scroll */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  html { scroll-behavior: auto !important; }
}

/* ============================================================
   V2 (flow-b) – color selection. The v1 swatch grid STAYS (fast
   one-click pick); a link opens a single-column, labelled SIDE
   WINDOW for people who want the whole palette + names at a
   glance. Window rows proxy-click the swatches so the selection
   engine (article, price delta, image swap, RAL picker, config
   unlock) is reused unchanged. Markup: index.html · wiring: pdp-b.js.
   ============================================================ */
/* v2 KEEPS v1's swatch grid (fast one-click selection) and ADDS a secondary link that opens
   the full labelled list – so both user groups are served from the same interface. The link
   markup lives in index.html but only shows under ?flow=b. */
.bx-color__listlink { display: none; align-items: center; gap: 0.45rem; margin-top: 0;
  padding: 0.15rem 0; background: none; border: 0; cursor: pointer; font: inherit; font-size: 0.875rem; font-weight: 700;
  color: var(--color-teal); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.22em;
  transition: color .15s ease; }
/* .bx-color is a flex column, so a plain flex item would stretch full-width; align-self keeps
   the link sized to its content and pinned to the left edge (under the swatches / label). */
.flow-b .bx-color__listlink { display: inline-flex; align-self: flex-start; }
/* In v2 the link and RAL picker sit in .bx-color's flex column; drop their extra margins so
   the gap above and below the link is the uniform flex `gap` (v1 keeps the RAL picker margin). */
.flow-b #ralPick { margin-top: 0; }
/* Roomier, uniform spacing between the colour block's rows (label · swatches · link · RAL
   picker) so they don't read as cramped – scoped to v2 so v1 spacing is untouched. */
.flow-b .bx-color { gap: 1.25rem; }
/* Mobile: the swatch row has top/bottom padding and the indicator line floats in the TOP
   padding, so the space above the indicator (label→indicator) is much smaller than the space
   below the swatches (row bottom padding + gap) down to the link. Pull the link up so the gap
   below the swatches ≈ the gap above the indicator (measured from the indicator, not the row). */
.flow-b .swtouch .bx-color__listlink { margin-top: -1rem; }
/* The link is the last item in the colour block; the buy-box's 2rem section gap made the
   space BELOW it much larger than the ~1.25rem above. Pull the config panel up in v2 so the
   link sits with roughly equal breathing room above and below (desktop + mobile alike). */
.flow-b #cfgbPanel { margin-top: -0.75rem; }
.bx-color__listlink:hover { color: var(--color-teal-hover); }
.bx-color__listlink:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; border-radius: 2px; }
.bx-color__listlink svg { flex: none; width: 1.05rem; height: 1.05rem; }

/* ============================================================
   V3 (flow-c) – color selection. Same v1 swatch grid + v2 side window, but the
   entry point is a select-style FIELD ("Alle Farben mit Bezeichnung ansehen")
   that opens the labelled #colorwin list, and the chosen finish shows as a plain
   LABEL directly above the swatch grid. Order: field · label · swatches.
   Rendered in Metzler's own language. Markup: index.html · JS: pdp-b.js.
   ============================================================ */
.bx-listfield, .bx-colorsel { display: none; }        /* v3/v4 list-field + (retired) v3 eyebrow – hidden by default */
/* v3 keeps the SAME "Farbe: <value>" head as v1/v2/v4 – no bespoke eyebrow label. */
.flow-c .bx-color__listlink { display: none !important; }   /* replaced by the .bx-listfield */
.flow-c .bx-color { gap: 1rem; }
.flow-c #ralPick { margin-top: 0; }
.flow-c #cfgbPanel { margin-top: -0.75rem; }
/* v3: the list-field opener sits UNDER the swatch grid (matches v4). .bx-color is a
   flex column, so reorder its children with `order` – the shared DOM stays put.
   Visible order: colour label · swatches · list-field · RAL picker · note. */
.flow-c .bx-color__head { order: 0; }
.flow-c .pdp-swatches  { order: 1; }
.flow-c .bx-listfield  { order: 2; }
.flow-c #ralPick       { order: 3; }
.flow-c .bx-color__note { order: 4; }

/* select-style field that opens the full labelled colour list.
   Shared by v3 (flow-c) and v4 (flow-d) – see the flow-d note below. */
.flow-c .bx-listfield,
.flow-d .bx-listfield {
  display: flex; align-items: center; gap: 0.7rem; width: 100%;
  padding: 0.7rem 0.85rem; text-align: left; font: inherit; cursor: pointer;
  background: var(--color-white); border: 1px solid var(--color-graphite-300); border-radius: var(--radius-lg);
  transition: border-color .18s cubic-bezier(.22,1,.36,1), box-shadow .18s cubic-bezier(.22,1,.36,1);
}
.flow-c .bx-listfield:hover,
.flow-d .bx-listfield:hover { border-color: var(--color-teal); box-shadow: 0 1px 2px rgba(26,23,27,0.06); }
.flow-c .bx-listfield:focus-visible,
.flow-d .bx-listfield:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; }
.bx-listfield__icon { flex: none; width: 1.15rem; height: 1.15rem; color: var(--color-teal); }
.bx-listfield__text { flex: 1 1 auto; min-width: 0; font-size: 0.9375rem; font-weight: 700; color: var(--color-digital-black);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* selected-finish preview – hidden until a colour is chosen. The text grows to fill,
   so the thumb sits at the RIGHT, directly next to the chevron (0.7rem field gap). */
.bx-listfield__thumb { flex: none; width: 1.85rem; height: 1.85rem; box-sizing: border-box;
  border-radius: var(--radius); overflow: hidden; background: var(--color-paper); border: 1px solid var(--color-graphite-200); }
.bx-listfield__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bx-listfield__thumb:empty { display: none; }
.bx-listfield__chev { flex: none; width: 1.15rem; height: 1.15rem; color: var(--color-graphite-500);
  transition: transform .18s cubic-bezier(.22,1,.36,1), color .18s ease; }
.flow-c .bx-listfield:hover .bx-listfield__chev,
.flow-d .bx-listfield:hover .bx-listfield__chev { color: var(--color-teal); transform: translateX(0.125rem); }


/* Side window – premium right drawer + backdrop.
   Stays in the DOM (visibility, not display) so BOTH open AND close animate – with
   display:none the exit transition never plays. Visibility flips to hidden only AFTER
   the exit finishes (transition-delay), so the panel fully slides out first. Enter and
   exit are asymmetric: enter decelerates in (emphasized ease-out, feels like it settles),
   exit accelerates out (ease-in, feels responsive), with the backdrop fading a touch
   quicker than the panel so the page reappears promptly on close. */
.colorwin { position: fixed; inset: 0; z-index: 1000; visibility: hidden; pointer-events: none;
  transition: visibility 0s linear .34s; }
.colorwin.is-open { visibility: visible; pointer-events: auto; transition: visibility 0s linear 0s; }
.colorwin__backdrop { position: absolute; inset: 0; background: rgba(10,20,20,0.55);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  opacity: 0; transition: opacity .24s ease; }                                        /* exit fade */
.colorwin.is-open .colorwin__backdrop { opacity: 1; transition: opacity .32s ease; }  /* enter fade */
.colorwin__panel { position: absolute; top: 0; right: 0; height: 100%; width: min(27rem, 100%);
  display: flex; flex-direction: column; background: var(--color-white); box-shadow: var(--shadow-xl);
  transform: translateX(100%); will-change: transform;
  transition: transform .3s cubic-bezier(.4, 0, 1, 1); }                              /* exit: accelerate out */
.colorwin.is-open .colorwin__panel { transform: none;
  transition: transform .44s cubic-bezier(.16, 1, .3, 1); }                            /* enter: emphasized decelerate */
@media (prefers-reduced-motion: reduce) { .colorwin { transition-delay: 0s; } }

/* Header – title + close */
.colorwin__head { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1.35rem 1.25rem; border-bottom: 1px solid var(--color-graphite-200); }
.colorwin__headtext { min-width: 0; }
.colorwin__title { margin: 0; font-size: 1.2rem; font-weight: 700; letter-spacing: -0.015em; line-height: 1.25; color: var(--color-digital-black); }
.colorwin__close { flex: none; width: 2.5rem; height: 2.5rem; margin: -0.35rem -0.5rem -0.35rem 0; display: grid; place-items: center; cursor: pointer;
  color: var(--color-graphite-600); background: transparent; border: 0; border-radius: var(--radius); transition: background .15s ease, color .15s ease; }
.colorwin__close:hover { background: var(--color-graphite-100); color: var(--color-digital-black); }
.colorwin__close:focus-visible { outline: 2px solid var(--color-teal); outline-offset: 2px; }
.colorwin__close svg { width: 1.2rem; height: 1.2rem; }

/* List – thin refined scrollbar */
.colorwin__list { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0.5rem 0 1rem; -webkit-overflow-scrolling: touch;
  scrollbar-width: thin; scrollbar-color: rgba(0,0,0,0.18) transparent; }
.colorwin__list::-webkit-scrollbar { width: 6px; }
.colorwin__list::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.16); border-radius: 999px; }
.colorwin__list::-webkit-scrollbar-button { display: none; }

/* Group caption – sets the individual Wunschfarbe apart from the standard finishes */
.colorwin__group { margin-top: 0.4rem; padding: 1rem 1.25rem 0.5rem; border-top: 1px solid var(--color-graphite-200);
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-graphite-500); }

/* Row – larger swatch, two-tone "Name · code", teal accent + filled check badge */
.colorwin__row { position: relative; width: 100%; display: flex; align-items: center; gap: 0.85rem; padding: 0.85rem 1.25rem;
  background: transparent; border: 0; cursor: pointer; text-align: left; font: inherit; transition: background .16s cubic-bezier(.22,1,.36,1); }
.colorwin__row::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--color-teal);
  transform: scaleY(0); transition: transform .24s cubic-bezier(.22,1,.36,1); }
.colorwin__row:hover { background: var(--color-teal-50); }
.colorwin__row:focus-visible { outline: 2px solid var(--color-teal); outline-offset: -2px; }
.colorwin__row.is-selected { background: var(--color-teal-50); }
.colorwin__row.is-selected::before { transform: scaleY(1); }
/* Hairline divider between finishes – inset from the panel edges so it reads as a light
   item separator; the full-width rule above the "Individuell" group stays the stronger
   section break. Sits at the top of every row after the first. */
.colorwin__row + .colorwin__row::after {
  content: ""; position: absolute; top: 0; left: 1.25rem; right: 1.25rem; height: 1px;
  background: var(--color-graphite-200); pointer-events: none;
}
/* The side-window chip shares the inline swatch's language exactly – same white
   ground, graphite-300 frame, flat-at-rest → lift-on-hover, teal frame when
   chosen – so a colour looks identical whether picked in the grid or the list. */
.colorwin__sw { flex: none; width: 3.75rem; height: 3.75rem; border-radius: var(--radius); overflow: hidden;
  background: var(--color-white); border: 1px solid var(--color-graphite-300); box-sizing: border-box;
  transition: transform .24s cubic-bezier(.22,1,.36,1), border-color .2s cubic-bezier(.22,1,.36,1), box-shadow .24s cubic-bezier(.22,1,.36,1); }
.colorwin__sw img { width: 100%; height: 100%; object-fit: cover; display: block; }
.colorwin__row:hover .colorwin__sw { transform: translateY(-0.125rem); box-shadow: var(--shadow-md); }
.colorwin__row.is-selected .colorwin__sw { border-color: var(--color-teal); border-width: 2px; }

/* v4 (flow-d) ONLY: the side-window swatches use the SAME material texture as the grid
   (not the product photo), so a finish looks identical inside and outside the list.
   Mirrors the grid's per-article material map (.flow-d .pdp-swatch). Other versions keep
   the product-photo thumbnails unchanged. */
.flow-d .colorwin__sw { background-repeat: no-repeat; background-size: cover; background-position: center; }
.flow-d .colorwin__sw img { display: none; }
.flow-d .colorwin__row[data-article="31101"] .colorwin__sw { background-image: url("assets/materials/anthrazit.webp"); }      /* Anthrazit */
.flow-d .colorwin__row[data-article="31102"] .colorwin__sw { background-image: url("assets/materials/verkehrsweiss.webp"); }   /* Verkehrsweiß */
.flow-d .colorwin__row[data-article="31103"] .colorwin__sw { background-image: url("assets/materials/graualuminium.webp"); }   /* Graualuminium */
.flow-d .colorwin__row[data-article="31104"] .colorwin__sw { background-image: url("assets/materials/eisenglimmer.webp"); }    /* Eisenglimmer */
.flow-d .colorwin__row[data-article="31105"] .colorwin__sw { background-image: url("assets/materials/tiefschwarz.webp"); }     /* Tiefschwarz */
.flow-d .colorwin__row[data-article="31106"] .colorwin__sw { background-image: url("assets/materials/edelstahl.webp"); }       /* Edelstahl */
.flow-d .colorwin__row[data-article="31107"] .colorwin__sw { background-image: url("assets/materials/linen-tex-black.webp"); } /* Linen Tex Black */
.flow-d .colorwin__row[data-article="31108"] .colorwin__sw { background-image: url("assets/materials/wunschfarbe.webp"); }     /* Wunschfarbe – RAL fan */

/* v4 (flow-d) ONLY: the list-field's selected-finish thumb also shows the material
   texture, not the product photo. syncCard() (pdp-b.js) stamps the chosen article on
   #colorCardLink; the img it appends is hidden and the material painted underneath. */
.flow-d .bx-listfield__thumb { background-repeat: no-repeat; background-size: cover; background-position: center; }
.flow-d .bx-listfield__thumb img { display: none; }
.flow-d .bx-listfield[data-article="31101"] .bx-listfield__thumb { background-image: url("assets/materials/anthrazit.webp"); }
.flow-d .bx-listfield[data-article="31102"] .bx-listfield__thumb { background-image: url("assets/materials/verkehrsweiss.webp"); }
.flow-d .bx-listfield[data-article="31103"] .bx-listfield__thumb { background-image: url("assets/materials/graualuminium.webp"); }
.flow-d .bx-listfield[data-article="31104"] .bx-listfield__thumb { background-image: url("assets/materials/eisenglimmer.webp"); }
.flow-d .bx-listfield[data-article="31105"] .bx-listfield__thumb { background-image: url("assets/materials/tiefschwarz.webp"); }
.flow-d .bx-listfield[data-article="31106"] .bx-listfield__thumb { background-image: url("assets/materials/edelstahl.webp"); }
.flow-d .bx-listfield[data-article="31107"] .bx-listfield__thumb { background-image: url("assets/materials/linen-tex-black.webp"); }
.flow-d .bx-listfield[data-article="31108"] .bx-listfield__thumb { background-image: url("assets/materials/wunschfarbe.webp"); }
.colorwin__text { flex: 1 1 auto; min-width: 0; }
.colorwin__name { font-size: 1rem; font-weight: 700; letter-spacing: -0.01em; color: var(--color-digital-black); }
.colorwin__code { font-size: 0.9rem; font-weight: 500; color: var(--color-graphite-600); }
.colorwin__code::before { content: "·"; margin: 0 0.45em; color: var(--color-graphite-400); }
/* surcharge shown as a plain, prominent value; sits just left of the check (which stays in the
   same far-right column as every other row) */
.colorwin__price { flex: none; font-size: 1.0625rem; font-weight: 700; color: var(--color-digital-black); white-space: nowrap; }
.colorwin__check { flex: none; width: 1.5rem; height: 1.5rem; display: grid; place-items: center; border-radius: 50%;
  background: var(--color-teal); color: var(--color-white); opacity: 0; transform: scale(0.5);
  transition: opacity .18s ease, transform .24s cubic-bezier(.22,1,.36,1); }
.colorwin__check svg { width: 0.9rem; height: 0.9rem; }
.colorwin__row.is-selected .colorwin__check { opacity: 1; transform: scale(1); }

/* ── Tall screens: fill the drawer, enlarge the swatch ──────────────────────
   On short viewports the list scrolls (~770px of rows). On a tall monitor the
   drawer has height to spare, leaving dead space under the last colour. Here the
   list becomes a flex column so the rows SHARE that leftover height (grow, never
   shrink → shorter content still scrolls), and each swatch image steps up a size.
   The group caption keeps its natural height. Self-adjusting to any tall height.
   max-height caps the growth so rows fill normal big screens (≈960–1200px) yet
   never stretch airy on very large monitors – a clean row + a small bottom gap
   there instead of over-tall rows. */
@media (min-height: 60rem) {
  .colorwin__list { display: flex; flex-direction: column; }
  .colorwin__row { flex: 1 0 auto; max-height: 8.5rem; }
  .colorwin__group { flex: 0 0 auto; }
  .colorwin__sw { width: 4.75rem; height: 4.75rem; }
  .colorwin__name { font-size: 1.0625rem; }
}
