/* === KW Seilwinden-Filter Block ===
 * WAS:    Sidebar (Desktop ≥880px) / Bottom-Sheet (Mobile <880px) Filter-UI
 * WARUM:  Matcht archive-seilwinde Pattern + Handoff §7.2
 *         Mobile-First Base 375px, Aufstockung min-width:880px
 */

/* Issue #1444 -- kw-swf-css laedt async (media="print"+onload, gleiche
   Architektur wie #1346/kw-blocks-css). Vor dem Nachladen hat .kw-swf/
   .kw-swf__layout/.kw-swf__main/.kw-swf__grid keinerlei Layout-Regel: die
   Sidebar (280/300px, sticky) und das Karten-Raster (Grid) fehlen, alles
   rendert als normale Blockelemente in voller Breite uebereinander, bis das
   externe Stylesheet nachlaedt und in einem Schlag auf die Endmasse
   umschnappt (CLS 0,44-1,02 Desktop, gemessen). Marker unten (kw_blocks_
   critical_css(), render.php) inlinen die geometrierelevanten Regeln 1:1 als
   <style> synchron im ersten Paint -- reine Layout-/Groessenwerte, keine neue
   Optik, Rest der Datei (Farben/Hover/Uebergaenge) bleibt unangetastet async. */
/* KW-SWF-CRITICAL-BASE-START */
.kw-swf { padding: 48px 0; background: #fff; }
.kw-swf .kw-container { max-width: 1240px; margin: 0 auto; padding: 0 20px; }

/* === Mobile Toggle (sichtbar <880px) === */
.kw-swf__toggle {
    display: flex;
    align-items: center;
    /* Label + Count zentriert in einem Fluss, größere Schrift — Gregor 2026-06-02. */
    justify-content: center;
    gap: 16px;
    width: 100%;
    min-height: 56px;
    padding: 16px 24px;
    background: #97233F;
    color: #fff;
    border: 0;
    border-radius: 8px;
    font-family: 'Josefin Sans', sans-serif;
    font-weight: 700;
    font-size: 18px;
    text-transform: uppercase;
    letter-spacing: 1.5px;
    line-height: 1.2;
    cursor: pointer;
    margin-bottom: 24px;
}
.kw-swf__toggle:hover { background: #7E1C32; }
.kw-swf__toggle-count { font-weight: 400; opacity: 0.85; text-transform: none; letter-spacing: 0; }

/* === Layout === */
.kw-swf__layout { display: flex; flex-direction: column; gap: 24px; position: relative; }
/* KW-SWF-CRITICAL-BASE-END */

/* === Sidebar (Mobile = Bottom-Sheet) === */
/* Runde 5 (#1444, Mobil-Rest): diese Basisregel (kein @media -- gilt <880px)
   fehlte in JEDER bisherigen kritischen Kopie. KW-SWF-CRITICAL-880 (weiter
   unten) inlinet nur den Desktop-Override (position:sticky) -- Mobil blieb
   auf keinerlei kritische Regel, die Sidebar rendert vor dem CSS-Nachladen
   als normales Blockelement IM Textfluss (position:static default) statt
   als per position:fixed aus dem Fluss genommenes Bottom-Sheet. Diagnose
   (Playwright, async-CSS per Route-Abort blockiert, 375px): .kw-swf__sidebar
   display:block/position:static/Hoehe 448px (Fluss-Beitrag) vor dem
   Nachladen -> display:flex/position:fixed/0px Fluss-Beitrag danach --
   genau der ~470px-Sprung, der #filter/.kw-swf__layout/.kw-swf__main auf
   allen 3 Sibling-Hubs (Diagnose-Messung, forstseilwinde selbst hat dort ein
   anderes DOM ohne eigenes #filter-Element) nach unten schob. Fix: dieselbe
   Methode, 1:1 kopiert, kein neuer Wert -- die position:fixed-Eigenschaft
   allein nimmt das Element aus dem Fluss, sobald sie beim ersten Paint
   bereits gilt. */
/* KW-SWF-CRITICAL-SIDEBAR-START */
.kw-swf__sidebar {
    position: fixed;
    bottom: 0; left: 0; right: 0;
    max-height: 85vh;
    background: #fff;
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -4px 24px rgba(0,0,0,0.18);
    transform: translateY(100%);
    transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1);
    z-index: 201;
    display: flex;
    flex-direction: column;
}
/* KW-SWF-CRITICAL-SIDEBAR-END */
.kw-swf__sidebar.is-open { transform: translateY(0); }
.kw-swf__sidebar-handle {
    width: 40px; height: 4px;
    background: #C9B89A;
    border-radius: 2px;
    margin: 10px auto 0;
}
.kw-swf__sidebar-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 20px 12px;
    border-bottom: 1px solid #E8E2DA;
}
.kw-swf__sidebar-header-actions { display: flex; align-items: center; gap: 14px; }
/* Zuruecksetzen-Link im Sidebar-Kopf (Punkt 3, #1384) — nur wo render.php ihn
   rendert (Archiv-Hub-Seiten), Desktop only per Mockup, Mobil bleibt beim
   bestehenden Footer-Reset-Button ("mobil wie bisher"). */
.kw-swf__reset-link {
    display: none;
    background: none; border: 0; padding: 4px 0; cursor: pointer;
    font-family: 'Josefin Sans', sans-serif; font-size: 12px; font-weight: 600;
    letter-spacing: 0.04em; color: #97233F;
}
.kw-swf__reset-link:hover { text-decoration: underline; }
.kw-swf__sidebar-title {
    margin: 0;
    font-family: 'Josefin Sans', sans-serif;
    font-weight: 700;
    font-size: 18px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #1A1A1A;
}
.kw-swf__sidebar-close {
    background: none; border: 0;
    width: 44px; height: 44px;
    font-size: 28px; line-height: 1;
    color: #5C5C5C;
    cursor: pointer;
}
.kw-swf__sidebar-close:hover { color: #97233F; }
.kw-swf__sidebar-inner { padding: 20px; overflow-y: auto; flex: 1; }
.kw-swf__sidebar-footer {
    display: flex; gap: 12px;
    padding: 16px 20px;
    border-top: 1px solid #E8E2DA;
    background: #fff;
}
.kw-swf__sidebar-footer .kw-btn { flex: 1; min-height: 48px; }
/* Reset-Button: explizit Bordeaux-on-cream, sonst auf cream-Sidebar unlesbar */
.kw-swf__sidebar-footer .kw-swf__reset {
    color: #97233F;
    border: 1.5px solid #97233F;
    background: transparent;
    font-family: 'Josefin Sans', sans-serif;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 13px;
    border-radius: 8px;
    padding: 12px 20px;
    cursor: pointer;
    transition: background .15s, color .15s;
}
.kw-swf__sidebar-footer .kw-swf__reset:hover {
    background: #97233F;
    color: #fff;
}

/* === Overlay === */
.kw-swf__overlay {
    position: fixed; inset: 0;
    background: rgba(20,15,10,0.55);
    z-index: 200;
}

/* === Group === */
.kw-swf__group { border: 0; padding: 0; margin: 0 0 24px; }
.kw-swf__group legend {
    font-family: 'Josefin Sans', sans-serif;
    font-weight: 600;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: #1A1A1A;
    margin-bottom: 12px;
    padding: 0;
}
.kw-swf__hint { font-weight: 400; font-size: 11px; color: #888; margin-left: 6px; text-transform: none; letter-spacing: 0; }

/* === Custom Checkbox === */
.kw-swf__check {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 10px 0; min-height: 48px;
    cursor: pointer; user-select: none;
    color: #1A1A1A;
    font-size: 15px;
    font-family: 'PT Serif', Georgia, serif;
}
.kw-swf__check input[type=checkbox] {
    appearance: none; -webkit-appearance: none;
    width: 20px; height: 20px;
    margin: 4px 0 0;
    border: 1.5px solid #C9B89A;
    border-radius: 4px;
    background: #fff;
    cursor: pointer;
    flex-shrink: 0; position: relative;
    transition: border-color .15s, background .15s;
}
.kw-swf__check input[type=checkbox]:hover { border-color: #97233F; }
.kw-swf__check input[type=checkbox]:checked { background: #97233F; border-color: #97233F; }
.kw-swf__check input[type=checkbox]:checked::after {
    content: ""; position: absolute;
    left: 6px; top: 2px;
    width: 5px; height: 10px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}
.kw-swf__check input[type=checkbox]:focus-visible { outline: 2px solid #97233F; outline-offset: 2px; }
.kw-swf__check input[type=checkbox]:disabled,
.kw-swf__check.kw-swf__disabled { opacity: 0.4; cursor: not-allowed; }
.kw-swf__check.kw-swf__disabled input { pointer-events: none; }

.kw-swf__check--with-desc { align-items: flex-start; }
.kw-swf__check-text { display: flex; flex-direction: column; gap: 2px; }
.kw-swf__check-title { font-weight: 600; }
.kw-swf__check-desc { font-size: 12px; color: #5C5C5C; line-height: 1.4; font-family: 'PT Serif', Georgia, serif; font-style: italic; }

/* === Pill-Buttons (Bauart) === */
.kw-swf__pills { display: flex; flex-direction: column; gap: 8px; }
.kw-swf__pill {
    display: flex; align-items: center; justify-content: center;
    padding: 6px 14px; min-height: 34px;
    border: 1.5px solid #C9B89A;
    border-radius: 999px;
    background: #fff;
    color: #1A1A1A;
    font-family: 'PT Serif', Georgia, serif;
    font-size: 14px;
    cursor: pointer; user-select: none;
    transition: border-color .15s, background .15s, color .15s;
    text-align: center;
}
.kw-swf__pill input { position: absolute; opacity: 0; pointer-events: none; width: 0; height: 0; }
.kw-swf__pill:hover { border-color: #97233F; }
.kw-swf__pill:has(input:checked) {
    background: #97233F;
    border-color: #97233F;
    color: #fff;
}
.kw-swf__pill:has(input:focus-visible) { outline: 2px solid #97233F; outline-offset: 2px; }
.kw-swf__pill.kw-swf__disabled,
.kw-swf__pill:has(input:disabled) { opacity: 0.4; cursor: not-allowed; }

/* Trefferzahlen je Bauart (Punkt 3, #1384) — :has() scoped auf Pills, die den
   Count-Span tatsaechlich rendern (nur Archiv-Hub-Seiten); Sibling-Hubs ohne
   Count-Span bleiben bei der zentrierten Pill-Optik unveraendert. */
.kw-swf__pill:has(.kw-swf__pill-count) { justify-content: space-between; padding-left: 16px; padding-right: 16px; text-align: left; }
.kw-swf__pill-count { font-family: 'Josefin Sans', sans-serif; font-size: 12px; color: #8A8A8A; margin-left: 10px; }
.kw-swf__pill:has(input:checked) .kw-swf__pill-count { color: rgba(255,255,255,0.75); }

/* === Range === */
.kw-swf__range legend { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.kw-swf__range-vals {
    font-family: 'PT Serif', Georgia, serif;
    font-size: 13px; color: #97233F;
    font-weight: 700; font-style: italic;
    text-transform: none; letter-spacing: 0;
}

.kw-swf__dual { position: relative; height: 32px; margin-top: 12px; padding: 0 10px; }
.kw-swf__dual-track {
    position: absolute; left: 10px; right: 10px; top: 50%;
    height: 4px; transform: translateY(-50%);
    background: #E8E2DA; border-radius: 2px;
}
.kw-swf__dual-fill {
    position: absolute; top: 50%;
    height: 4px; transform: translateY(-50%);
    background: #97233F; border-radius: 2px;
}
.kw-swf__dual input[type=range] {
    position: absolute; top: 50%;
    left: 0; width: 100%;
    height: 0; margin: 0; padding: 0;
    background: none; pointer-events: none;
    -webkit-appearance: none; appearance: none;
    z-index: 3; outline: none;
}
.kw-swf__dual input[type=range]::-webkit-slider-runnable-track { height: 0; background: transparent; border: none; }
.kw-swf__dual input[type=range]::-moz-range-track { height: 0; background: transparent; border: none; }
.kw-swf__dual input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    pointer-events: auto;
    width: 24px; height: 24px;
    border-radius: 50%;
    background: #97233F; border: 2px solid #fff;
    box-shadow: 0 1px 4px rgba(0,0,0,0.25);
    cursor: grab;
    margin-top: -12px;
    transition: transform .12s;
    position: relative; z-index: 4;
}
.kw-swf__dual input[type=range]::-webkit-slider-thumb:hover { transform: scale(1.12); }
.kw-swf__dual input[type=range]::-webkit-slider-thumb:active { cursor: grabbing; transform: scale(1.18); }
.kw-swf__dual input[type=range]::-moz-range-thumb {
    pointer-events: auto;
    width: 24px; height: 24px;
    border-radius: 50%;
    background: #97233F; border: 2px solid #fff;
    box-shadow: 0 1px 4px rgba(0,0,0,0.25);
    cursor: grab;
}
@media (max-width: 480px) {
    .kw-swf__dual input[type=range]::-webkit-slider-thumb { width: 28px; height: 28px; margin-top: -14px; }
    .kw-swf__dual input[type=range]::-moz-range-thumb { width: 28px; height: 28px; }
}

/* === Advanced Details === */
.kw-swf__advanced { margin: 8px 0 24px; }
.kw-swf__advanced summary {
    font-family: 'Josefin Sans', sans-serif;
    font-weight: 600; font-size: 13px;
    text-transform: uppercase; letter-spacing: 0.08em;
    color: #5C5C5C; cursor: pointer;
    padding: 8px 0; min-height: 44px;
    display: flex; align-items: center;
}
.kw-swf__advanced summary:hover { color: #97233F; }
.kw-swf__advanced[open] summary { color: #97233F; margin-bottom: 8px; }

/* === Main / Counter === */
/* KW-SWF-CRITICAL-GRID-START */
.kw-swf__main { flex: 1; min-width: 0; }
.kw-card-grid.kw-swf__grid,
.kw-swf__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 16px;
}
/* Grid-Items: width:100% + min-width:0 zwingt die Card auf die Grid-Zelle, unabhängig von intrinsischer Bildgröße. */
.kw-swf__grid > .kw-card { width: 100%; min-width: 0; max-width: none; }
/* Card-Thumb: SSOT-Foto-Standard ist 5:4 (4:5 W:H Portrait). Querformat-Bilder werden
   center-gecropt, damit alle Cards in einer Zeile gleich hoch sind. */
.kw-swf__grid .kw-card__thumb {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 5;
    overflow: hidden;
    background: var(--kw-cream-dark, #E8E2DA);
}
.kw-swf__grid .kw-card__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    display: block;
}
/* KW-SWF-CRITICAL-GRID-END */
.kw-swf__grid .kw-card__thumb img { transition: transform 0.6s ease; }
.kw-swf__grid .kw-card:hover .kw-card__thumb img { transform: scale(1.04); }
/* Card-Layout: ab 560px horizontal (Bild links, Info rechts). Unter 560 vertikal. */
/* KW-SWF-CRITICAL-GRID2-START */
.kw-swf__grid .kw-card { display: flex; flex-direction: column; }
.kw-swf__grid .kw-card .kw-card-body { flex: 1 1 auto; display: flex; flex-direction: column; padding: 16px 20px; }
/* KW-SWF-CRITICAL-GRID2-END */
@media (min-width: 560px) {
    /* KW-SWF-CRITICAL-560-START */
    .kw-swf__grid .kw-card { flex-direction: row; align-items: stretch; }
    /* Horizontal: Thumb in Portrait-Aspect 4:5 (SSOT-Foto-Standard), Image dadurch unbeschnitten.
       Card-Höhe = thumb_height. Bodies stretchen mit, Buttons via margin-top:auto unten bündig. */
    .kw-swf__grid .kw-card__thumb {
        width: 42%;
        flex-shrink: 0;
        aspect-ratio: 4 / 5;
        align-self: flex-start;
        position: relative;
    }
    .kw-swf__grid .kw-card__thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
    .kw-swf__grid .kw-card .kw-card-body { width: 58%; padding: 16px 18px; }
    /* Issue #684: Card ohne echtes Produktfoto — Body füllt die volle Breite,
       kein 42%-Leerraum links. */
    .kw-swf__grid .kw-card--no-thumb .kw-card-body { width: 100%; }
    /* KW-SWF-CRITICAL-560-END */
}
/* Super-Prüfer F1 (#1420): Grid stretcht Items per Default auf volle Row-Höhe
   (align-items:stretch der .kw-swf__grid). Nachbar-Karten mit 4:5-Bild ziehen die
   Row-Höhe hoch — die bildlose Karte (kein Thumb, Body flex:1 mit margin-top:auto
   auf den Buttons) wird mitgestreckt und reißt eine leere Lücke zwischen Badges und
   Buttons auf (~210px). Fix: bildlose Karte NICHT strecken, sondern oben in der
   Grid-Zelle andocken — Karte bleibt kompakt auf Content-Höhe, Buttons rücken direkt
   unter die Badges. Nachbarkarten (mit Thumb) bleiben unverändert (kein align-self hier). */
.kw-swf__grid .kw-card--no-thumb { align-self: start; }
/* Mehr Pills auf der Card */
/* Issue #1444 Runde 3 (Freigabe, eng umrissen): Karten-Innenhalt (Badges/
   Titel/Serie/Aktionen) fehlte in der kritischen Kopie -- bis das echte
   Stylesheet nachlaedt bleibt .kw-product-badges ein normaler Block (0 Hoehe,
   Badges stapeln senkrecht statt Flex-Zeile), h3/kw-card__serie/kw-swf__card-
   actions haben keine Groessen-Regel. Da .kw-swf__grid--archiv row-height =
   max() der 3 Karten einer Zeile ist, reicht EIN unstyled Badge-Block, um die
   ganze Zeile (und damit .kw-swf insgesamt) beim CSS-Nachladen zu vergroessern
   -- konkreter Rest-Verursacher der .kw-swf +14px-Hoehenaenderung (Bau-Report
   Runde 2, Diagnose Runde 3). */
/* KW-SWF-CRITICAL-CARDCONTENT-START */
.kw-swf__grid .kw-product-badges { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 14px; }
.kw-swf__grid .kw-product-badge {
    font-family: 'Josefin Sans', sans-serif;
    /* #1384 Runde 2 Nacharbeit, Befund 2: Gregors "Icon-/Kennzahlen-Schrift
       zu klein, Lesbarkeit" (Punkt 3, Runde 2, siehe kw-blocks.css-Log) galt
       generell, nicht nur ab 1280px. Die 13px/18px-Anhebung stand bisher NUR
       in der @media(min-width:1280px)-Regel weiter unten (.kw-swf__grid--
       archiv .kw-product-badge) -- unter 1280px (also auch am 375px-Mobile-
       First-Gate) blieb diese Basis-Regel bei 11px/12px. Gleiches Mass jetzt
       auch hier: .kw-product-badges hat flex-wrap:wrap (KEIN nowrap wie beim
       1280px-Archiv-Block), einzelne Badges white-space:nowrap -- bei zu
       wenig Platz wandert ein ganzes Badge in die naechste Zeile statt zu
       ueberlaufen/den Text zu brechen, das ist bestehendes, gewolltes
       Verhalten dieser Basis-Regel. Bei 375px mit dem breitesten Karten-Fall
       aller 12 Modelle gemessen (KGD 85 SA: "8,5 t" + "1,9 / 2,0 / 2,2 m" +
       "667-718 kg", Statik-Harness .tmp-1384-measure/, siehe Bau-Report):
       kein horizontales Overflow (card-body scrollWidth==clientWidth), kein
       Text-Bruch innerhalb eines Badges -- Badge 3 (Gewicht) faellt in eine
       zweite Zeile, GENAUSO wie es das schon bei den alten 11px/12px tat
       (gegengemessen). Die Groessenanhebung aendert also nichts am
       Zeilenumbruch-Verhalten dieses Grenzfalls, erzeugt keine neue
       Ueberlappung/kein Clipping. */
    font-size: 13px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 4px 9px;
    border-radius: 999px;
    background: #F6EFE5;
    color: #5C5C5C;
    white-space: nowrap;
}
.kw-swf__grid h3 { font-size: 18px; margin: 0 0 2px; }
.kw-swf__grid .kw-card__serie {
    font-family: 'PT Serif', Georgia, serif;
    font-size: 12px;
    font-style: italic;
    color: #97233F;
    margin: 0 0 10px;
    letter-spacing: 0.02em;
}
.kw-swf__grid .kw-product-badge.kw-badge--feature {
    background: #97233F;
    color: #fff;
}
.kw-swf__grid .kw-product-badge { display: inline-flex; align-items: center; gap: 5px; }
.kw-product-badge__icon {
    /* #1384 Runde 2 Nacharbeit, Befund 2: gleiches Mass wie oben (13px-Text),
       Icon 12px -> 18px auch in der Basis-Regel (vorher nur >=1280px). */
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    /* Tint Black-SVG zu mid-gray, passt zu Pill-Text */
    filter: brightness(0) saturate(0) opacity(0.55);
}
.kw-badge--feature .kw-product-badge__icon { filter: brightness(0) invert(1) opacity(0.95); }
.kw-swf__card-actions { display: flex; gap: 8px; margin-top: auto; }
.kw-swf__card-actions .kw-btn {
    flex: 1;
    padding: 8px 12px;
    min-height: 36px;
    font-size: 12px;
    letter-spacing: 0.08em;
    text-align: center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1.2;
}
/* KW-SWF-CRITICAL-CARDCONTENT-END */
@media (min-width: 560px) {
    /* KW-SWF-CRITICAL-560-GRID-START */
    .kw-card-grid.kw-swf__grid,
    .kw-swf__grid { grid-template-columns: repeat(2, 1fr); gap: 20px; }
    /* KW-SWF-CRITICAL-560-GRID-END */
}
@media (min-width: 1100px) {
    /* KW-SWF-CRITICAL-1100-GRID-START */
    .kw-card-grid.kw-swf__grid,
    .kw-swf__grid { grid-template-columns: repeat(2, 1fr); gap: 24px; }
    /* KW-SWF-CRITICAL-1100-GRID-END */
}
/* Issue #1444 Runde 4 (Freigabe, letzte Bau-Runde): main-header/counter/
   sort-label fehlten in der kritischen Kopie -- vor dem CSS-Nachladen ist
   .kw-swf__main-header ein normaler Block (kein Flex), .kw-swf__sort-label
   spannt dadurch die volle Zeilenbreite (874px) statt seiner Auto-Breite
   (~203px); die Kopfzeile kollabiert/wechselt beim Nachladen -- Rest-
   Verursacher nach Runde 3 (Diagnose Runde 3, alle 4 Archiv-Hubs betroffen). */
/* KW-SWF-CRITICAL-MAINHEADER-START */
.kw-swf__main-header {
    display: flex; align-items: center; justify-content: flex-end;
    padding: 0 0 16px;
    border-bottom: 1px solid #E8E2DA;
    margin-bottom: 24px;
}
.kw-swf__counter { margin: 0; font-family: 'PT Serif', Georgia, serif; color: #5C5C5C; font-size: 14px; }
.kw-swf__counter strong { color: #97233F; font-family: 'Josefin Sans', sans-serif; font-size: 16px; margin-right: 4px; }

/* Grid-Kopfzeile "N MODELLE" + Sortierung (Punkt 5, #1384) — nur Archiv-Hub. */
.kw-swf__main-header--archiv { justify-content: space-between; flex-wrap: wrap; gap: 8px; }
.kw-swf__counter--archiv {
    font-family: 'Josefin Sans', sans-serif; font-weight: 600; font-size: 13px;
    text-transform: uppercase; letter-spacing: 0.08em; color: #5C5C5C;
}
.kw-swf__counter--archiv strong { text-transform: none; letter-spacing: 0; }
.kw-swf__sort-label { margin: 0; font-family: 'Josefin Sans', sans-serif; font-size: 13px; color: #5C5C5C; }
.kw-swf__sort-label strong { color: #1A1A1A; font-weight: 700; }
/* KW-SWF-CRITICAL-MAINHEADER-END */

/* === Empty === */
.kw-swf__empty {
    text-align: center; padding: 48px 16px;
    color: #5C5C5C; font-size: 16px;
    font-family: 'PT Serif', Georgia, serif;
    display: flex; flex-direction: column; align-items: center; gap: 16px;
}
.kw-swf__empty[hidden] { display: none; }
.kw-swf__empty-text { margin: 0; }
.kw-swf__empty-reset { min-width: 200px; }

/* === Empfehlungs-Chip auf Card === */
.kw-card { position: relative; }
.kw-card__thumb { position: relative; display: block; }
.kw-card__chip-recommend {
    position: absolute; top: 8px; right: 8px;
    background: #97233F; color: #fff;
    font-family: 'Josefin Sans', sans-serif;
    font-size: 11px; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.5px;
    padding: 4px 10px; border-radius: 3px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.2);
    z-index: 2;
}

/* SSOT-Status Chip „Auslaufend" (Issue #368) — Amber, kein Grün. */
.kw-card__chip-status {
    position: absolute; top: 8px; left: 8px;
    font-family: 'Josefin Sans', sans-serif;
    font-size: 11px; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.5px;
    padding: 4px 10px; border-radius: 3px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.2);
    z-index: 2; line-height: 1.2;
}
.kw-card__chip-status--auslaufend {
    background: var(--kw-warning, #B8860B); color: #fff;
}

/* === Desktop ≥880px === */
@media (min-width: 880px) {
    /* KW-SWF-CRITICAL-880-START */
    .kw-swf { padding: 72px 0; }
    .kw-swf .kw-container { padding: 0 32px; }

    .kw-swf__toggle { display: none; }
    .kw-swf__overlay { display: none !important; }

    .kw-swf__layout { flex-direction: row; gap: 40px; align-items: flex-start; }
    .kw-swf__sidebar {
        position: sticky; top: 88px;
        z-index: 10;
        width: 280px; flex-shrink: 0;
        max-height: calc(100vh - 120px);
        transform: none;
        border-radius: 12px;
        box-shadow: 0 2px 12px rgba(0,0,0,0.04);
        background: #F5F0EB;
        border: 1px solid #E8E2DA;
    }
    /* KW-SWF-CRITICAL-880-END */
    .kw-swf__sidebar-close { display: none; }
    .kw-swf__sidebar-handle { display: none; }
    .kw-swf__sidebar-header { background: transparent; padding: 20px 20px 16px; }
    .kw-swf__sidebar-footer { background: transparent; padding: 16px 20px 20px; flex-direction: row; }
    .kw-swf__sidebar-footer .kw-swf__apply { display: none; }
    .kw-swf__sidebar-footer .kw-swf__reset { flex: 1; }
    .kw-swf__reset-link { display: inline-block; }
}

/* Nachpruefung 22.08. (#1384, Befund 1): "weisse Foto-Hintergruende" war nur
   in der @media(min-width:1280px)-Regel unten gesetzt, darunter (375/768/1024px)
   griff weiterhin die Creme-Basisregel (Zeile ~302) -- exakt das "nur Desktop"-
   Muster, das bei der Kennzahlen-Schrift (Zeile ~345) schon einmal gefunden und
   behoben wurde, hier aber beim Hintergrund uebersehen. Fix: Basisregel statt
   Media-Query-exklusiv, gleicher Scope (nur die 6 Forstseilwinde-Sprachfassungen,
   damals noch .kw-swf__grid--archiv). Die Regel unten in @media(min-width:
   1280px) bleibt stehen (kein Verhaltensunterschied, nur redundant) statt sie
   herauszuschneiden und das Nachtrags-Protokoll dort zu zerreissen.
   KORREKTUR (Delta-Pruefung 22.08., Befund-Kommentar #1384): Scope von
   --archiv auf --foto-hub geweitet (render.php setzt die Klasse jetzt auf
   allen 4 Kategorie-Hubs, $is_foto_hub ist Superset von $is_archiv_hub) --
   sonst blieb der Thumb-Hintergrund auf funkwinde/mechanische-seilwinde
   Creme (rgb(237,229,220)) statt Weiss, sichtbar sobald die Contain-Regel
   unten (Zeile ~584) dort ebenfalls greift. */
.kw-swf__grid.kw-swf__grid--foto-hub .kw-card__thumb { background: #fff; }

/* ==========================================================================
   ISSUE #1384 Vollausbau, Nachbefund Nr. 2 — Spalten-Layout Mockup-treu.
   Mockup (reports/issue-1382/.../3.6 Kategorieseite Desktop.dc.html, Zeile 58):
   Sidebar 300px fix + 1fr Rest, Karten-Grid repeat(3,1fr) (Zeile 123). Bei uns
   war die Sidebar 280px (ok) aber das Karten-Grid blieb bei repeat(2,1fr) —
   dadurch nur 2 grosse Karten statt 3 kompakter. Nur `.kw-swf__grid--archiv`
   wird umgestellt. Bis #1443 rendert render.php diese Klasse nur auf den 6
   Forstseilwinde-Seiten, die generische 2-spaltige Kartenoptik der 3
   Sibling-Hubs blieb unberuehrt.
   ROLLOUT #1443 (22./23.08.): render.php setzt --archiv jetzt auf allen 24
   Kategorie-Hub-Seiten (4 Hubs) -- dieselbe 3-Spalten-Karte gilt seither
   ueberall, keine CSS-Aenderung hier noetig (reine Klassen-Kaskade).
   3 Spalten erst ab 1280px (bei 1024-1279 zu eng fuer 3 kompakte Karten,
   bleibt bewusst bei 2 -- siehe Bau-Report).
   ========================================================================== */
@media (min-width: 1024px) {
    /* KW-SWF-CRITICAL-1024-START */
    .kw-swf__sidebar.kw-swf__sidebar--archiv { width: 300px; }
    /* KW-SWF-CRITICAL-1024-END */
}
@media (min-width: 1280px) {
    /* KW-SWF-CRITICAL-1280-START */
    .kw-swf__grid.kw-swf__grid--archiv { grid-template-columns: repeat(3, 1fr); gap: 20px; }
    /* Karten fuer die 3-Spalten-Reihe zurueck auf vertikal (Bild oben) --
       die generische Quer-Karte (Bild links 42%/Text rechts 58%) ab 560px
       waere bei ~280px Kartenbreite zu schmal fuer ein lesbares Bild. */
    .kw-swf__grid.kw-swf__grid--archiv .kw-card { flex-direction: column; }
    .kw-swf__grid.kw-swf__grid--archiv .kw-card__thumb {
        width: 100%; aspect-ratio: 4 / 3; position: static; align-self: stretch;
    }
    /* KW-SWF-CRITICAL-1280-END */
    /* Punkt 2, Runde 2 (#1384, Gregor: "diese Balken sind haesslich" = die
       Creme-Letterbox aus Punkt 3 oben/Zeile 532ff, dort bewusst gewaehlt
       (contain statt Beschnitt), JETZT Farbe geaendert). Nur der Hintergrund
       hinter dem object-fit:contain-Foto wird weiss -- der contain-Mechanismus
       selbst (kein Beschnitt, volles Produktfoto) bleibt unveraendert, das war
       nicht Teil der Kritik. Scope automatisch nur Forstseilwinde: .kw-swf__grid
       .kw-card__thumb (Basisregel, Zeile ~302) bleibt cream-dark fuer die
       Sibling-Hubs (dort object-fit:cover, Hintergrund ohnehin nie sichtbar) --
       diese Override-Regel greift nur unter .kw-swf__grid--archiv, das render.php
       exklusiv auf den 6 Forstseilwinde-Sprachfassungen setzt ($is_archiv_hub). */
    .kw-swf__grid.kw-swf__grid--archiv .kw-card__thumb { background: #fff; }
    /* Feinschliff (Gregor 19.08. nachmittags): Hochformat-Freisteller (768x960,
       Seitenverhaeltnis 4:5) in der 4:3-Bildflaeche mit object-position:center
       zeigten nur die Bildmitte -- bei kleineren Karten liess das den Cage
       oben dominieren und die rote Winde wirkte knapp/leer. Zwei Varianten per
       Playwright verglichen (object-fit:contain mit Creme-Rand vs. object-fit:
       cover mit object-position:center bottom, Screenshots im Bau-Report):
       contain zeigt das ganze Produkt inkl. Cage, wirkt bei 278x209 aber
       schmal/leer durch die Creme-Balken links/rechts. cover+bottom bleedet
       randlos wie im Mockup (dc.html: object-fit:cover, kein Letterboxing)
       und zeigt die komplette rote Winde -- nur der duenne Draht-Cage oben
       wird bei Bedarf angeschnitten, das ist der optisch unwichtigere Teil.
       Entscheidung: cover + object-position:center bottom. */
    /* Nachbefund v6 (#1384): Selektor bleibt auf dem Bildwrapper gescopt
       (.kw-swf__grid--archiv .kw-card__thumb img), !important zusaetzlich,
       damit die Regel auch fuer ein natives loading=lazy-Bild greift, das der
       Browser noch nicht geladen hat -- unabhaengig von Ladezustand/
       CSS-Optimierungs-Cache-Reihenfolge (WP-Rocket RUCSS). */
    /* Nachbefund v7 (#1384, LEAD-Live-Verifikation): object-position:center
       bottom (= 50% 100%) crop-t das Sichtfenster ganz an den unteren Rand des
       Quellfotos -- bei den Freisteller-Fotos liegt dort bei manchen Modellen
       ein leerer Streifen im Foto selbst (kein CSS-Letterboxing, object-fit:
       cover bleibt aktiv). 35/40/45% live verglichen (Playwright-Screenshots,
       reports/issue-1384/): 40% zeigt bei allen 3 Karten die rote Winde
       vollstaendig und mittig, ohne dass der Cage oben oder ein Rand unten
       dominiert. Entscheidung: 50% 40%. */
    /* Punkt 3 (Nachtrag 20.08., loest Nachbefund v7 ab): Gregor -- Hochformat
       nicht mehr quer beschneiden, Bild auf 100% Hoehe, Weissraum in der
       Breite ist ok, nichts abschneiden, keine eigenen Querformat-Fotos
       "fuers Erste". object-fit:contain in der 4:3-Flaeche skaliert das
       4:5-Freisteller-Foto an der Hoehe (limitierende Dimension bei einem
       hochformatigen Bild in einer breiteren Box) -- voller Cage + volle
       Winde sichtbar, Creme-Rand (.kw-card__thumb-Hintergrund) links/rechts
       statt Beschnitt oben. object-position zentriert, die 40%-Feinjustage
       von v7 war nur fuer den Crop-Fall noetig und faellt mit contain weg. */
    /* FIX-RUNDE #1455 (Befund blinde Pruefung, MITTEL): alle 3 object-position-
       !important-Regeln in diesem Block (hier + 2x unten) ueberschrieben den
       Bildfokus-Slider auf Desktop >=1280px komplett -- Gregor stellte den
       Regler, sah aber auf Foto-Karten keine Wirkung (Mobil griff er korrekt,
       weil dort object-position nur "einfach" gesetzt war, kein !important).
       Fix: object-position liest jetzt var(--kw-bildfokus, center) -- Fallback
       "center" ist exakt der bisherige Wert, aendert also nichts, wenn kein
       Fokus gesetzt ist. Die Custom Property selbst kommt per Inline-Style
       vom selben <img> (kw_bildfokus_style() in inc/bildfokus-fields.php),
       object-fit bleibt in allen 3 Regeln unangetastet (Auftrag). */
    .kw-swf__grid.kw-swf__grid--archiv .kw-card:not(.kw-card--foto) .kw-card__thumb img {
        position: static !important; width: 100% !important; height: 100% !important;
        object-fit: contain !important; object-position: var(--kw-bildfokus, center) !important;
    }
    /* Delta-Fund #1 (Nachpruefung 22.08., Befund-Kommentar #1384): dieselbe
       Freisteller-Contain-Regel jetzt auch fuer die 3 Sibling-Hubs (funkwinde,
       mechanische-seilwinde, quertrommelwinde) -- vorher exklusiv auf
       .kw-swf__grid--archiv gescoped (= nur forstseilwinde), dadurch renderten
       35 SA/85 SA (funkwinde) und alle 4 M-Modelle (mechanische-seilwinde)
       weiterhin object-fit:cover auf Creme statt contain auf Weiss (visuell
       nicht von einer Foto-Karte zu unterscheiden). Eigener Selektor
       (:not(.kw-swf__grid--archiv), damit forstseilwinde exklusiv bei der
       Regel oben bleibt, keine doppelte Ueberschreibung) statt die
       Archiv-Regel selbst umzuwidmen -- die Sibling-Hubs haben KEIN eigenes
       3-Spalten-Layout (Zeile ~542 bleibt archiv-exklusiv), ihr Thumb behaelt
       die normale 4:5-Box + absolut positioniertes Bild (Basisregel Zeile
       ~320-327); object-fit:contain funktioniert auf einem absolut
       positionierten 100%x100%-Bild genauso wie auf einem statischen, kein
       position/width/height-Override noetig (anders als bei der 4:3-
       statischen Archiv-Box oben).
       TOT SEIT #1443 (22./23.08.): render.php setzt --archiv jetzt auf
       denselben 24 Seiten wie --foto-hub (Kategorie-Muster-Rollout, alle 4
       Hubs bekommen das Archiv-Kartenlayout) -- der :not(--archiv)-Zweig
       trifft dadurch auf keiner Seite mehr zu, die Regel oben (Zeile ~590)
       deckt jetzt alle 4 Hubs ab. Bewusst NICHT geloescht (kein Verhaltens-
       gewinn durch Entfernen, volle Historie bleibt lesbar/reversibel). */
    .kw-swf__grid.kw-swf__grid--foto-hub:not(.kw-swf__grid--archiv) .kw-card:not(.kw-card--foto) .kw-card__thumb img {
        object-fit: contain !important; object-position: var(--kw-bildfokus, center) !important;
    }
    /* #1384 Chat-Runde 22.08. (Gregor): echte Natur-/Einsatzfotos (kw-card--foto,
       vom Render-Waechter in render.php nur bei bestaetigtem Querformat gesetzt)
       sollen IMMER die Bildflaeche deckend fuellen (nie Raender) -- die
       Freisteller-contain-Regel direkt darueber gilt darum ausdruecklich nicht
       fuer sie (:not(.kw-card--foto)). STUFE 1 (Gregors Korrektur 22.08.,
       Ruecknahme der ersten Vollausbau-Fassung): diese Regel steht bewusst
       INNERHALB von .kw-swf__grid--archiv, dem bestehenden #1384-Scoping-Muster
       (render.php: Klasse nur bei $is_archiv_hub, also nur /forstseilwinde/ +
       6 WPML-IDs) -- wirkt heute ausschliesslich dort, weil kw-card--foto auf
       den 3 Sibling-Hubs (mechanische-seilwinde/funkwinde/quertrommelwinde)
       nie gesetzt wird (dort gibt es aktuell keine Naturfoto-Zuweisung, jedes
       Modell zeigt "ansicht-front"-Freisteller, Bestands-Check 22.08.). Ausbau
       auf die anderen 3 Hubs erst nach Freigabe -- der Selektor selbst (Karten-
       Klasse statt ID) macht das spaeter zur reinen render.php-Aenderung, ohne
       dieses Regelpaar anzufassen. .kw-card__thumb selbst bleibt hier
       position:static (Regel oben, Zeile ~537, unveraendert fuer beide Faelle)
       -- die Foto-Karte braucht daher ihren eigenen positionierten Kontext,
       sonst haette position:absolute+inset:0 auf dem Bild keinen lokalen
       Bezugsrahmen und wuerde ueber die ganze Karte (inkl. Textbereich) laufen
       statt nur ueber die Thumb-Flaeche. */
    .kw-swf__grid.kw-swf__grid--archiv .kw-card--foto .kw-card__thumb { position: relative; }
    .kw-swf__grid.kw-swf__grid--archiv .kw-card--foto .kw-card__thumb img {
        position: absolute !important; inset: 0 !important; width: 100% !important; height: 100% !important;
        object-fit: cover !important; object-position: var(--kw-bildfokus, center) !important;
    }
    /* Ursache Punkt 6 (Nachtrag 20.08., CSS-Fehler wie von Gregor vermutet):
       Der vorherige Kommentar hier ging davon aus, align-items:stretch
       fuelle .kw-card-body automatisch auf volle Breite -- das stimmt nicht,
       weil die Basis-Regel bei >=560px explizit `.kw-card-body { width:58%
       }` setzt (Quer-Karten-Layout, Bild 42%/Text 58%) und Media-Queries
       sich AUFADDIEREN statt sich abzuloesen: die 58%-Regel bleibt bei
       >=1280px aktiv, obwohl die Karte hier laengst wieder vertikal steht
       (Bild oben, Text soll die volle Breite haben). Ergebnis war eine auf
       58% (~161px von 278px) gestauchte Karten-Body-Spalte -- daran brachen
       "Mechanische Seilwinde" (Punkt 6) und die Icon-Zeile (Punkt 5) um, und
       Details/Angebot quollen ueber den Innenrand hinaus. box-sizing:
       border-box steht hier schon (Zeile darunter), macht width:100% jetzt
       gefahrlos -- die Paddings zaehlen zu den 100%, kein Ueberstand mehr
       wie beim frueheren Versuch ohne border-box. */
    /* KW-SWF-CRITICAL-1280B-START */
    .kw-swf__grid.kw-swf__grid--archiv .kw-card .kw-card-body { width: 100%; padding: 14px 16px 16px; box-sizing: border-box; }
    /* Absicherung falls ein Modell ohne Foto in die 3-Spalten-Reihe faellt
       (aktuell keines) -- dieselbe border-box-Absicherung, kein width:100%. */
    .kw-swf__grid.kw-swf__grid--archiv .kw-card--no-thumb .kw-card-body { box-sizing: border-box; }
    .kw-swf__grid.kw-swf__grid--archiv h3 { font-size: 17px; margin-bottom: 1px; }
    .kw-swf__grid.kw-swf__grid--archiv .kw-card__serie { margin-bottom: 6px; }
    /* KW-SWF-CRITICAL-1280B-END */
    /* Punkt 4+5 (Nachtrag 20.08.): Gregor -- Pillen weg, nur Icon (groesser)
       + Zahl; die Werte-Zeile soll durchgehend in einer Zeile stehen statt
       zu wickeln. Chrome (Hintergrund/Radius/Padding/Grossbuchstaben) der
       Basis-Pill (.kw-product-badge, kw-blocks.css) nur fuer dieses Archiv-
       Raster zurueckgenommen -- Sibling-Hubs behalten ihre Pillen-Optik
       unveraendert. flex-wrap:nowrap erzwingt die eine Zeile jetzt aktiv,
       statt sich nur auf den (durch Punkt 6 gefixten) Platz zu verlassen. */
    /* Punkt 3, Runde 2 (#1384, Gregor: Icon-/Kennzahlen-Schrift zu klein,
       Lesbarkeit). Vorher/Nachher: Schrift 11px -> 13px (kein eigener Token
       unter --kw-text-xs=12px im Styleguide, 13px = die Groesse, die die
       Basis-Pille .kw-product-badge (kw-blocks.css) auf den Sibling-Hubs
       ohnehin traegt -- kein neuer Wert, sondern die Rueckkehr auf den
       bestehenden Standard). Icon 16px -> 18px (+2px, moderat, passt bei
       278px Kartenbreite/3 Kennzahlen weiter in eine Zeile, nowrap bleibt
       aktiv). Gap/Zeilenumbruch-Verhalten (Punkt 4/5 vorige Runde)
       unveraendert. */
    /* KW-SWF-CRITICAL-1280C-START */
    .kw-swf__grid.kw-swf__grid--archiv .kw-product-badges { gap: 10px; margin: 6px 0 12px; flex-wrap: nowrap; }
    .kw-swf__grid.kw-swf__grid--archiv .kw-product-badge {
        font-size: 13px;
        letter-spacing: 0;
        text-transform: none;
        font-weight: 400;
        background: none;
        border-radius: 0;
        padding: 0;
        white-space: nowrap;
    }
    .kw-swf__grid.kw-swf__grid--archiv .kw-product-badge__icon { width: 18px; height: 18px; }
    /* KW-SWF-CRITICAL-1280C-END */
    /* Punkt 5: "Details" soll bis in die Kartenecke reichen -- das war durch
       den Punkt-6-Fix (kw-card-body jetzt volle Breite) bereits geloest,
       .kw-swf__card-actions/.kw-btn sind seit Bestand flex:1 und fuellen
       die volle Zeile bis zur Innenkante; hier nur die verkleinerte
       3-Spalten-Schriftgroesse unveraendert uebernommen. */
    /* KW-SWF-CRITICAL-1280D-START */
    .kw-swf__grid.kw-swf__grid--archiv .kw-swf__card-actions .kw-btn { font-size: 11px; padding: 7px 8px; min-height: 34px; }
    /* KW-SWF-CRITICAL-1280D-END */
}

/* ==========================================================================
   ISSUE #1384 — Kategorieseite Desktop: Filterknopf above the fold
   Nur oberer Innenabstand von .kw-swf reduziert, damit die Sidebar
   ("Winde filtern") bei 1280x800 sichtbar in die Falz ragt. Ueberschreibt
   den Top-Wert aus der Desktop-Regel oben (padding:72px 0) gezielt --
   Selektor ist per body.page-id-* spezifischer (0,0,2,0 vs 0,0,1,0), die
   Kollision ist damit konfliktfrei aufgeloest, unabhaengig von der
   Ladereihenfolge der beiden Stylesheets. padding-bottom bleibt bei 72px
   (Shorthand-Longhand: nur padding-top wird hier gesetzt).
   SCOPE bis #1443: /forstseilwinde/ + 5 Sprachfassungen (Page-IDs siehe
   kw-blocks.css #1384-Kommentar), NUR >=1024px.
   ROLLOUT #1443 (22./23.08.): dieselbe above-the-fold-Reduktion jetzt auf
   allen 4 Kategorie-Hubs (24 Page-IDs = 4 Hubs x 6 WPML-Sprachfassungen,
   IDs identisch zu render.php $kw_archiv_hub_ids). */
@media (min-width: 1024px) {
    /* KW-SWF-CRITICAL-PAGEPAD-START */
    body.page-id-87 .kw-swf,
    body.page-id-2997 .kw-swf,
    body.page-id-2998 .kw-swf,
    body.page-id-2999 .kw-swf,
    body.page-id-3000 .kw-swf,
    body.page-id-3001 .kw-swf,
    body.page-id-396 .kw-swf,
    body.page-id-2967 .kw-swf,
    body.page-id-2968 .kw-swf,
    body.page-id-2969 .kw-swf,
    body.page-id-2970 .kw-swf,
    body.page-id-2971 .kw-swf,
    body.page-id-397 .kw-swf,
    body.page-id-2972 .kw-swf,
    body.page-id-2973 .kw-swf,
    body.page-id-2974 .kw-swf,
    body.page-id-2975 .kw-swf,
    body.page-id-2976 .kw-swf,
    body.page-id-724 .kw-swf,
    body.page-id-3029 .kw-swf,
    body.page-id-3030 .kw-swf,
    body.page-id-3031 .kw-swf,
    body.page-id-3032 .kw-swf,
    body.page-id-3033 .kw-swf {
        padding-top: 20px;
    }
    /* KW-SWF-CRITICAL-PAGEPAD-END */
}
