/* ================================================================
   SPF Produktseite (Cowork) — CSS v1
   Gilt nur innerhalb .ktmpdp (Produktdetailseite, aktuelles Design)
   1) Mengenselektor als Pille (ersetzt grauen Kasten)
   2) Kein Stepper bei nicht lieferbarer Variation
   3) Größen-/Varianten-Chips statt Dropdown
   4) Grundpreis-Zeile unter dem Preis (Germanized)
   5) Fitment-Zeile nur bei Produkten mit Passt-auf-Daten
   6) "Nicht kombinierbar mit" als Mini-Cards neben "Kunden kauften auch"
   7) "Für die Montage erforderlich"-Karte (Checkbox)
   ================================================================ */

/* ---------- 1) Mengenselektor: Pille wie im Warenkorb (110x40, voll gerundet) ---------- */
/* !important: WPCode-Header-CSS laedt VOR dem Theme — gleichspezifische
   Theme-Regeln (border/height/radius) wuerden sonst gewinnen */
.ktmpdp .quantity {
  display: inline-flex !important;
  align-items: center !important;
  justify-content: space-between !important;
  height: 46px !important;
  width: 122px !important;
  padding: 0 4px !important;
  border: 1px solid #cfd2d6 !important;
  border-radius: 999px !important;
  background: #fff !important;
  overflow: hidden;
  box-sizing: border-box;
}
/* `touch-action: manipulation`: Ohne das wartet der Browser nach jedem Tipp
   auf einen moeglichen Doppeltipp und zoomt bei schnellem +/- die Seite heran,
   statt die Menge hochzuzaehlen (Tester, 04.09.2026). */
.ktmpdp .quantity .spf-qbtn {
  touch-action: manipulation;
  width: 36px;
  height: 36px;
  flex: 0 0 36px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  font-size: 18px;
  font-weight: 600;
  color: #16181c;
  cursor: pointer;
  line-height: 1;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background .12s, color .12s;
}
@media (hover:hover){
.ktmpdp .quantity .spf-qbtn:hover{ background: #f0f1f2; }}
.ktmpdp .quantity .spf-qbtn:disabled,
.ktmpdp .quantity .spf-qbtn[disabled] { color: #a7abb1; cursor: default; background: transparent; }
.ktmpdp .quantity input.qty {
  touch-action: manipulation;
  width: 40px;
  height: 100%;
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  text-align: center;
  font-size: 15px;
  font-weight: 700;
  color: #16181c;
  background: transparent;
  appearance: textfield;
  -moz-appearance: textfield;
  padding: 0;
  margin: 0;
  box-shadow: none;
  outline: none;
}
.ktmpdp .quantity input.qty::-webkit-outer-spin-button,
.ktmpdp .quantity input.qty::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
/* Theme setzt flex-order auf die Kinder — explizit zuruecksetzen */
.ktmpdp .quantity .screen-reader-text { order: 0; }
.ktmpdp .quantity .spf-qbtn--minus { order: 1; }
.ktmpdp .quantity input.qty { order: 2; }
.ktmpdp .quantity .spf-qbtn--plus { order: 3; }
/* alte Theme-Plus/Minus-Kaesten aus (JS ersetzt sie durch .spf-qbtn) */
.ktmpdp .quantity .action { display: none !important; }
/* "In den Warenkorb"-Button auf Stepper-Hoehe (46px) bringen */
.ktmpdp .single_add_to_cart_button {
  height: 46px !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center;
  box-sizing: border-box;
}
/* Nicht lieferbare Variation: kein Stepper, kein MENGE-Label */
.ktmpdp .woocommerce-variation-add-to-cart-disabled .quantity { display: none !important; }
.ktmpdp__cart:has(.woocommerce-variation-add-to-cart-disabled) .ktmpdp__qtylabel { display: none; }

/* ---------- 3) Varianten-Chips ---------- */
/* `row-gap` traegt die Fahne unter dem Chip (siehe `.spf-chip__low`), `column-gap` haelt
   Abstand zu ihrem Ueberhang. */
.spf-chips { display: flex; flex-wrap: wrap; gap: 22px 12px; margin: 2px 0 10px; }
.spf-chip {
  min-width: 56px;
  padding: 0 14px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid #d7d9dc;
  border-radius: 10px;
  background: #fff;
  font-size: 15px;
  font-weight: 600;
  color: #16181c;
  cursor: pointer;
  position: relative;
  transition: border-color .12s, background .12s, color .12s;
}
@media (hover:hover){
.spf-chip:hover{ border-color: #9aa0a6; }}
/* Markenfarbe statt KTM-Orange (11.08.2026): auf Husky waren Chips, Randmarke
   und Ankreuzfeld sonst orange in einem blauen Shop. */
.spf-chip.is-sel { border-color: var(--o-text, var(--brand-accent, #ff6600)); box-shadow: inset 0 0 0 1px var(--o-text, var(--brand-accent, #ff6600)); color: var(--o-text, var(--brand-accent, #ff6600)); }
.spf-chip.is-out {
  color: #a7abb1;
  background: #fafafa;
  border-style: dashed;
  cursor: not-allowed;
  overflow: hidden;
}
/* Schraeger Strich (Ecke-zu-Ecke) statt horizontalem line-through */
.spf-chip.is-out::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top right, transparent calc(50% - 0.9px), #9aa0a6 calc(50% - 0.9px), #9aa0a6 calc(50% + 0.9px), transparent calc(50% + 0.9px));
  pointer-events: none;
}
.spf-chip.is-out.is-sel { border-color: #d7d9dc; box-shadow: none; }

/* WooCommerce "Auswahl zuruecksetzen" ausblenden — Deselektieren geht ueber erneuten
   Chip-Klick bzw. die "Option auswaehlen"-Zeile der verbliebenen Dropdowns. */
.ktmpdp .reset_variations { display: none !important; }
/* KNAPP-FAHNE (02.09.2026)
   Vorher ein runder Kreis mit „1×" in der oberen Ecke. Der Inhalt heisst jetzt „Nur noch 1"
   und braucht Breite, also sitzt die Fahne mittig UNTER dem Chip statt in der Ecke — dort
   hat sie die ganze Chipbreite plus etwas Ueberhang, ohne dem Nachbarn in die Ecke zu laufen.
   Deshalb steht `.spf-chips` auf `gap:12px` und `row-gap:22px` (vorher 9 px rundum): Der
   Zeilenabstand muss die Fahne aufnehmen, sonst stoesst sie an die naechste Chipreihe.

   FARBE: ueber zwei Token, nicht fest — `--spf-knapp-bg` und `--spf-knapp-ink`. Die Werte
   hier sind die KTM-Fassung und zugleich der Rueckfall; `spf-marke-husky.css` setzt die
   beiden Token um, ohne diese Regel anzufassen. Dasselbe Muster wie beim Buttonsystem.

   KTM: #ff8c1a in BEIDEN Modi (Kili, 02.09.2026: „Mach die Flaeche bei Hell auch ff8c1a").
   Der Weg dahin ging ueber zwei Zwischenstaende:

   - #e07c00 mit weisser Schrift: Schrift 2,98:1. Zu dunkel fuer weiss, zu blass als Flaeche.
   - #d97800 mit dunkler Schrift: Flaeche 3,16:1 gegen den weissen Chip, Schrift 5,88:1.
   - #ff8c1a mit dunkler Schrift: Schrift 8,00:1 — der beste Wert der drei. Die FLAECHE
     kommt gegen den weissen Chip aber nur auf 2,33:1.

   ⚠️ DER FLAECHENKONTRAST IM HELLMODUS IST BEI KTM UNTER 3:1. Bewusste Entscheidung, kein
   Versehen: Die Fahne ist keine Bedienflaeche, sondern beschrifteter Text auf farbigem Grund
   — was sie mitteilt, steht in der Schrift, und die traegt 8,00:1. Sie ist ausserdem nie die
   einzige Quelle: dieselbe Angabe steht nach der Groessenwahl in der Metazeile („Auf Lager
   (1)") und im `aria-label` des Chips. Wer den Wert ueber 3:1 heben will, nimmt #d97800 —
   der optische Unterschied ist gering, der gemessene nicht.

   DIE SCHRIFT IST DUNKEL, NICHT WEISS. Weiss auf diesem Orange ergaebe 2,33:1 und waere bei
   10 px unlesbar; die Richtlinie verlangt dort 4,5:1. Mit #111315 sind es 8,00:1. Das kostet
   nichts ausser der Gewohnheit, ein Badge weiss zu beschriften — und die Fahne liest sich
   dadurch als Warnhinweis statt als Zaehler. */
.spf-chip__low {
  position: absolute;
  left: 50%;
  bottom: -9px;
  transform: translateX(-50%);
  background: var(--spf-knapp-bg, #ff8c1a);
  color: var(--spf-knapp-ink, #111315);
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  padding: 3px 6px;
  border-radius: 7px;
  white-space: nowrap;
  pointer-events: none;
}
/* Keine Nachtregel fuer KTM: Dort sieht die Fahne in beiden Modi gleich aus. #ff8c1a hebt
   sich vom dunklen Chip (#1a1c1e) mit 7,34:1 ab und vom hellen mit 2,33:1 — der dunkle Modus
   ist hier der guenstigere Fall, nicht der Sonderfall. Husky braucht dagegen zwei Fassungen,
   siehe `spf-marke-husky.css`. */
/* Nur das durch Chips ersetzte (Groessen-)Select ausblenden; Label + Zuruecksetzen bleiben.
   Grafik/Farbe-Selects bei Mehrfach-Attributen bleiben als Dropdown sichtbar (Kili). */
.variations select.spf-chipped { display: none !important; }
.spf-has-chips .variations td.value.spf-chip-cell { padding-top: 2px; }

/* Gestyltes Dropdown fuer die verbliebenen Attribute (Grafik/Farbe), passend zur Chip-Optik */
.ktmpdp form.variations_form .variations select:not(.spf-chipped) {
  height: 44px;
  min-width: 220px;
  max-width: 100%;
  padding: 0 40px 0 14px;
  border: 1px solid #d7d9dc;
  border-radius: 10px;
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%2316181c' stroke-width='1.6' d='M1 1.5 6 6l5-4.5'/%3E%3C/svg%3E") no-repeat right 14px center;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  font-size: 15px;
  font-weight: 600;
  color: #16181c;
  cursor: pointer;
  margin: 2px 0 4px;
}
@media (hover:hover){
.ktmpdp form.variations_form .variations select:not(.spf-chipped):hover{ border-color: #9aa0a6; }}
.ktmpdp form.variations_form .variations select:not(.spf-chipped):focus {
  outline: none;
  border-color: var(--o-text, var(--brand-accent, #ff6600));
  /* 11.09.2026: Der innere Ring muss mit — sonst stuende er in der Tagfarbe innerhalb
     eines Randes in der Signatur. Derselbe Fehler wie am Groessen-Chip. */
  box-shadow: inset 0 0 0 1px var(--o-text, var(--brand-accent, #ff6600));
}

/* ---------- 4) Grundpreis ---------- */
.ktmpdp__price .spf-unitprice,
.ktmpdp__price .unit-price {
  display: block;
  font-size: 14px;
  line-height: 1.3;
  color: #6b7280;
  font-weight: 400;
  margin-top: 3px;
  text-transform: none;
  letter-spacing: 0;
}
.ktmpdp__price .spf-unitprice .woocommerce-Price-amount { font-weight: 500; color: #4b5157; font-size: 14px; }

/* ---------- 5) Fitment nur mit Passt-auf-Daten ---------- */
.ktmpdp.spf-no-fitdata .ktmpdp__summary .spf-fitbadge { display: none !important; }
.ktmpdp.spf-no-fitdata .ktmpdp__summary > div:not([class]):has(> .spf-fitbadge) { display: none !important; }

/* ---------- 6) Nicht kombinierbar: Karussell-Sektion im xsell-Stil, in EINER
   Zeile mit "Kunden kauften auch" (nokombi links, Empfehlungen rechts) ----------
   Karten-Markup identisch zu den xsell-Karten -> Styling kommt vom Theme-CSS. */
/* Spaltenverhaeltnis 2:3 (2 nokombi-Karten links, 3 sichtbare Empfehlungen rechts).
   Die Theme-Karten haben flex-basis 20% der Track-Breite — deshalb KEIN max-content
   (zirkulaer -> Grid explodiert), sondern fr-Spalten + eigene Karten-Basis je Sektion. */
.spf-xrow {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  gap: 0 40px;
  align-items: start;
}
.spf-xrow > section { min-width: 0; }
.spf-nokombi-sec { margin-top: 0; }
/* Beide Kachel-Reihen IMMER gleich hoch — wie ein einziges Karussell (Kili). Die Hoehe
   lief nicht wegen der Pfeile auseinander, sondern wegen unterschiedlich langer
   Produktnamen: ein zweizeiliger Name machte seine Kachel hoeher als die einzeilige
   Nachbarkachel. Loesung: Namenszeile auf feste 2 Zeilen klemmen (min-height reserviert
   2 Zeilen, line-clamp kappt laengere Namen). Damit ist jede Kachel unabhaengig vom
   Namen exakt gleich hoch — bündig oben UND unten. */
.spf-xrow .ktmpc__name {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 38.4px; /* 2 × line-height 19.2px */
}
@media (min-width: 1101px) {
  .spf-xrow .spf-nokombi-sec .ktmpdp__card { flex: 0 0 calc(50% - 10px) !important; }
  .spf-xrow > .ktmpdp__xsell:not(.spf-nokombi-sec) .ktmpdp__card { flex: 0 0 calc(33.333% - 13.4px) !important; }
}
@media (max-width: 1100px) {
  .spf-xrow { display: block; }
  .spf-nokombi-sec { margin-bottom: 10px; }
}
tr.spf-nokombi-src { display: none !important; }
tr.spf-required-src { display: none !important; }

/* ---------- 7) Erforderlicher Artikel (Mitbestellen) ---------- */
.spf-required {
  border: 1px solid #d7d9dc;
  border-left: 3px solid var(--o-text, var(--brand-accent, #ff6600));
  background: #fff;
  border-radius: 10px;
  padding: 12px 14px 13px;
  margin: 16px 0 2px;
}
.spf-required__head {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: #6b7280;
  margin: 0 0 9px;
}
.spf-required__item { display: flex; align-items: center; gap: 11px; margin-top: 8px; }
.spf-required__item:first-of-type { margin-top: 0; }
.spf-required__item img { width: 44px; height: 44px; object-fit: contain; flex: 0 0 44px; border: 1px solid #ececec; border-radius: 6px; background: #fff; }
.spf-required__info { flex: 1 1 auto; min-width: 0; }
.spf-required__name { font-size: 13.5px; font-weight: 600; line-height: 1.3; display: block; color: #16181c; }
.spf-required__meta { font-size: 12px; color: #6b7280; display: block; margin-top: 1px; }
.spf-required__check { display: flex; align-items: center; gap: 7px; font-size: 13px; color: #16181c; cursor: pointer; flex: 0 0 auto; }
.spf-required__check input { width: 17px; height: 17px; accent-color: var(--brand-accent,#ff6600); cursor: pointer; margin: 0; }

/* Add-to-Cart-Feedback + Toast liegen jetzt global in spf-product-card.css
   (gemeinsam fuer Produktseite + Karten), gesteuert von spf-cart-links.js. */

/* =========================================================================
   Streichpreis auf der Produktseite
   -------------------------------------------------------------------------
   Die Preisanzeige `.ktmpdp__price` gehoert dem Bricks-PDP-Template. Dort setzt
   ein Inline-Block (`<style id="ktm-pdp-partial-info-css">`) den Streichpreis auf
   `color:#000` — im Hellmodus richtig, im Nachtmodus stand er als reines Schwarz
   auf #0f1011 und war damit unsichtbar (Kili 30.07.).
   Korrektur hier statt im Template: Das PDP-Template ist Bricks-Code und nicht
   deploybar. `body.spf-night …` (0,2,2) schlaegt `.ktmpdp__price del` (0,1,1),
   die Ladereihenfolge spielt damit keine Rolle.
   `.spfpdp-was` ist der von spf-product-page.js nachgetragene Streichpreis bei
   Variantenwahl — er erbt bewusst dieselbe Optik wie der native `<del>`.
   ========================================================================= */
body.spf-night .ktmpdp__price del,
body.spf-night .ktmpdp__price del *,
body.spf-night .ktmpdp__price .spfpdp-was,
body.spf-night .ktmpdp__price .spfpdp-was * {
    color: #9aa0a6;
}
.ktmpdp__price .spfpdp-was,
.ktmpdp__price .spfpdp-was * {
    color: #000;
    text-decoration: line-through;
}
/* Angebotsfarbe fuer den aktuellen Preis, wenn der Streichpreis nachgetragen wurde.
   Ohne Variantenwahl steckt der Preis in einem <ins> und ist dadurch orange; bei
   Variantenwahl schreibt das Template nur ein nacktes `.woocommerce-Price-amount`.
   `>` (direktes Kind) trifft bewusst NUR den aktuellen Preis — der Streichpreis
   enthaelt selbst ein `.woocommerce-Price-amount` und soll grau bleiben. */
.ktmpdp__price.spfpdp-hassale > .woocommerce-Price-amount,
.ktmpdp__price.spfpdp-hassale > .woocommerce-Price-amount * {
    color: var(--spf-brand, #ff6600);
}
/* 10.09.2026: Die Regel darueber gilt in BEIDEN Modi. Im Hellen traegt das
   Husqvarna-Blau 11,29:1 und bleibt deshalb, wie es ist. Nachts steht der Preis in
   der Kaufbox auf #17181a, und dort kommt dasselbe Blau nur auf 1,57:1 — der
   Aktionspreis waere praktisch unlesbar. Deshalb hier die Signatur (HQV #ffed00,
   14,69:1; KTM unveraendert #ff6600, 6,05:1). */
body.spf-night .ktmpdp__price.spfpdp-hassale > .woocommerce-Price-amount,
body.spf-night .ktmpdp__price.spfpdp-hassale > .woocommerce-Price-amount *,
html.spf-night .ktmpdp__price.spfpdp-hassale > .woocommerce-Price-amount,
html.spf-night .ktmpdp__price.spfpdp-hassale > .woocommerce-Price-amount * {
    color: var(--spf-brand-night, #ff6600);
}

/* =============================================================
   EINBAULAGE (.spfloc) — Explosionszeichnung mit markiertem Teil
   -------------------------------------------------------------
   Zwei Einsatzorte, ein Markup: `--stage` sitzt im Galeriefeld und
   ersetzt dort die Flaeche „Kein Bild", `--panel` steht im Reiter
   ueber die volle Breite.

   Warum der Ring ein eigenes Element ist und nicht ins Bild
   gerechnet wird: `spf-exploded.css` invertiert im Darkmode jede
   Grafik unter /spf/images/Images/maps/ (invert(.9), gemessener
   Grund #191919). Laege der Ring im selben Element, waere er dort
   blau statt orange. Dieselbe Trennung wie bei der Stage im Finder.

   Der Ring ist in PROZENT der Bildbreite bemessen, nicht in px:
   Der ins Bild gezeichnete Nummernkreis skaliert mit dem Bild mit.
   Ein fester px-Ring saesse auf dem Handy als Reifen um eine
   winzige Ziffer. 5 % liegt knapp ueber den gemessenen 3,5 % des
   Hotspot-Rechtecks — er umschliesst die Nummer, statt sie zu
   verdecken.
   ============================================================= */
.spfloc {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.spfloc__stage {
    /* `fit-content`, nicht die volle Breite: Der Rahmen soll sich um die
       Zeichnung legen, nicht um die ganze Galeriespalte. Vorher stand ein
       955 px breiter Kasten um ein 340 px breites Bild, und die Zeichnung
       klebte links in einer leeren Flaeche (Kili, 13.08.2026). */
    display: flex;
    justify-content: center;
    /* Breite direkt hier, NICHT per `fit-content`: Das Kind rechnet mit `100%`
       dieser Buehne, und deren Breite aus dem Kind zu ziehen ist zirkulaer —
       der Browser faellt dann auf die volle Spaltenbreite zurueck. */
    width: min(100%, var(--spfloc-fit, 340px));
    margin: 0 auto;
    background: #fff;
    border: 1px solid var(--ktm-line, #e5e5e5);
    border-radius: 6px;
    overflow: hidden;
}
/* Traegt das Seitenverhaeltnis des Bildes (inline gesetzt) und begrenzt die
   Hoehe. Ohne die Begrenzung zog eine hochformatige Zeichnung die Galerie auf
   ueber 700 px und schob Preis und Warenkorb aus dem Bild (gemessen 12.08.2026).
   `max-height` mit `aspect-ratio` laesst den Rahmen proportional schrumpfen —
   das Bild fuellt ihn weiterhin randlos, der Ring bleibt an seinem Platz. */
/* ACHTUNG — hier NIEMALS `max-height` setzen.
   Der Rahmen traegt das Seitenverhaeltnis des Bildes, und der Ring wird in
   Prozent DIESES Rahmens positioniert. Eine Hoehenbegrenzung staucht den
   Rahmen, ohne die Breite mitzunehmen: Das Verhaeltnis stimmt dann nicht mehr,
   das Bild bekommt Raender (`contain`) oder wird verzerrt (`fill`) — und der
   Ring wandert sichtbar vom Teil weg. Genau das war am 12.08.2026 zu sehen.
   Wer die Darstellung kleiner haben will, begrenzt die BREITE. */
.spfloc__frame {
    position: relative;
    width: 100%;
    /* Nie staerker als 1,6-fach vergroessern. Die Zeichnungen sind nur 330 bis
       600 px breit; auf Galeriebreite gezogen werden sie matschig, in nativer
       Groesse stehen sie verloren in der Flaeche. `--spfloc-w` ist die echte
       Bildbreite und kommt inline aus der Referenztabelle. */
    /* `--spfloc-fit` kommt inline und ist bereits aus Bildbreite UND -hoehe
       gerechnet (siehe SPF_Part_Reference::figure_html). Damit ist die Hoehe
       gedeckelt, ohne dass `max-height` die Proportion bricht. */
    max-width: 100%;
}
.spfloc__img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}
/* Im Reiter etwas groesser als die Galerievorschau, aber NIE ueber die native
   Bildbreite hinaus: Die Zeichnungen sind 330 bis 600 px breit, alles darueber
   ist nur weichgezogen. `--spfloc-w` traegt die echte Breite, deshalb steht sie
   hier als dritter Kandidat im Minimum — damit skaliert der Reiter nie hoch.
   Vorher stand hier das 1,6-fache: bei einem 455-px-Bild ueber 700 px, und der
   Block fuellte den halben Bildschirm (Kili, 12.08.2026).
   Wieder ueber die BREITE, nie ueber die Hoehe — siehe Warnung weiter oben. */
.spfloc--panel .spfloc__stage {
    width: min(100%, var(--spfloc-fit, 420px), var(--spfloc-w, 420px));
}

.spfloc__ring {
    position: absolute;
    width: 5%;
    aspect-ratio: 1 / 1;
    transform: translate(-50%, -50%);
    border: 2px solid var(--o-text, var(--brand-accent, #ff6600));
    border-radius: 50%;
    pointer-events: none;
    /* Der aeussere helle Ring haelt die Markierung auch dort sichtbar, wo sie
       auf einer dunklen Linie der Zeichnung liegt. Orange allein erreicht auf
       Weiss nur rund 3:1 — als grafisches Element zulaessig (WCAG 1.4.11),
       aber ohne Reserve. */
    box-shadow: 0 0 0 2px rgba(255, 255, 255, .85);
}
.spfloc__cap {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    width: fit-content;
    max-width: 100%;
    margin: 0 auto;
    gap: 2px;
    font-size: 13px;
    line-height: 1.45;
    color: var(--ktm-text, #333);
}
.spfloc__where strong {
    font-weight: 700;
}
.spfloc__multi,
.spfloc__hint {
    font-size: 12px;
    color: #6b6b6b;
}
.spfloc--stage .spfloc__cap {
    font-size: 12px;
}

/* --- Zeichnung als Link --------------------------------------
   Die Zeichnung fuehrt in den Ersatzteilfinder, auf die Seite
   genau dieser Baugruppe. Der Link umschliesst nur das Bild, die
   Beschriftung bleibt aussen — sonst laese ein Screenreader den
   ganzen Absatz als Linktext vor. */
.spfloc__link {
    display: block;
    text-decoration: none;
    color: inherit;
    border-radius: 6px;
}
.spfloc__link:focus-visible .spfloc__img{
    opacity: .88;
}
@media (hover:hover){
.spfloc__link:hover .spfloc__img{
    opacity: .88;
}}
.spfloc__link:focus-visible {
    outline: 2px solid var(--o-text, var(--brand-accent, #ff6600));
    outline-offset: 3px;
}
.spfloc__mehr {
    margin-top: 4px;
    font-size: 12px;
    color: var(--o-text, #f96300);
}
body.spf-night .spfloc__mehr,
html.spf-night .spfloc__mehr {
    /* 10.09.2026: war --spf-brand, also die TAGfarbe (HQV #273a60, 1,63:1 auf dem
       Nachtgrund). Die Regel darf nicht entfallen: Die Grundregel traegt --o-text,
       und das ist die Textfarbe fuer WEISSEN Grund. */
    color: var(--spf-brand-night, #ff6600);
}

/* --- Darkmode ------------------------------------------------
   Die Invertierung muss HIER stehen. `spf-exploded.css` hat zwar
   eine passende Regel ueber den Bildpfad, wird auf der Produktseite
   aber nicht geladen — sie gehoert zum Finder. Ohne die Regel blieb
   die Zeichnung eine weisse Leuchtflaeche in der dunklen Buehne
   (gemessen 12.08.2026).

   invert(.9) statt invert(1): Bei voller Inversion landet der Grund
   auf #000 und damit unter dem Kartenton, die Zeichnung wirkt wie
   ein Loch im Layout. Mit .9 deckt sich der Grund praktisch mit der
   Flaeche, der Linienkontrast liegt bei rund 11:1 — dieselbe
   Abwaegung wie in `spf-exploded.css`.

   Der Filter sitzt ausdruecklich auf dem BILD, nicht auf Buehne oder
   Rahmen: sonst wuerde der Ring mitinvertiert und waere blau. */
body.spf-night .spfloc__img,
html.spf-night .spfloc__img {
    filter: invert(.9);
}
@media print {
    .spfloc__img { filter: none !important; }
}

/* --- Ausnahme fuer die neue Produktseite (.ppv2) --------------
   `spf-product-v2.css` legt auf JEDES Galeriebild
   `mix-blend-mode: multiply`, damit der weisse Rand eines auf Weiss
   freigestellten Produktfotos auf der hellen Buehne verschwindet.
   Fuer die Explosionszeichnung ist das falsch: Sie traegt im
   Nachtmodus `filter: invert(.9)` und liegt auf dunklem Grund —
   multipliziert man das invertierte Bild mit dieser Flaeche, wird
   alles nahezu schwarz und die Invertierung sieht aus, als greife
   sie gar nicht (Kili, 18.08.2026: „auf Produktfoto funktioniert
   nicht, in Einbaulage passts"). Im Reiter gibt es die Regel nicht,
   deshalb stimmte es dort.

   Nachts nimmt `spf-product-v2.css` das `multiply` inzwischen selbst
   zurueck, seit die Buehne dem Nachtmodus folgt. Diese Regel bleibt
   trotzdem noetig — sie gilt fuer den HELLMODUS, wo multiply
   weiterhin steht: Der Grund der Zeichnung ist reines Weiss und wird
   durch die Multiplikation mit dem grauen Buehnenton eingefaerbt.

   Drei Klassen schlagen die zwei Klassen plus Element der
   v2-Regel — kein `!important` noetig und keine Abhaengigkeit
   davon, welches Blatt zuerst geladen wird. */
.ppv2 .gal__buehne .spfloc__img {
    mix-blend-mode: normal;
}

/* Die Buehne traegt nachts den Rahmen allein. Seit dem 18.08.2026 folgt
   `--pp-buehne` dem Nachtmodus und trifft damit denselben Ton wie der
   Zeichnungsgrund (#191919) — zwei gleichfarbige Rahmen 14 px auseinander auf
   demselben Grund lesen sich als Fehler. Im Hellmodus bleibt der Rahmen: Dort
   unterscheiden sich Buehne (#eef0f1) und Zeichnungsgrund (#fff), und die Kante
   trennt sichtbar. */
body.spf-night .ppv2 .gal__buehne--riss .spfloc__stage,
html.spf-night .ppv2 .gal__buehne--riss .spfloc__stage {
    border-color: transparent;
}
/* Der Grund MUSS #191919 sein, nicht der Kartenton #17181a: Genau das ergibt
   invert(.9) aus dem Weiss der Zeichnung. Bei jedem anderen Wert zeichnet sich
   die Bildkante als sichtbare Naht in der Flaeche ab (beobachtet 12.08.2026). */
body.spf-night .spfloc__stage,
html.spf-night .spfloc__stage {
    background: #191919;
    border-color: #2a2c2f;
}
body.spf-night .spfloc__ring,
html.spf-night .spfloc__ring {
    box-shadow: 0 0 0 2px rgba(0, 0, 0, .75);
}
body.spf-night .spfloc__cap,
html.spf-night .spfloc__cap {
    color: #e7e7e7;
}
body.spf-night .spfloc__multi,
body.spf-night .spfloc__hint,
html.spf-night .spfloc__multi,
html.spf-night .spfloc__hint {
    color: #a4a4a4;
}

@media print {
    .spfloc__ring { box-shadow: none; }
}

/* --- Normteil-Zeichnung --------------------------------------
   Massstaebliche Darstellung genormter Kleinteile (SPF_Normteil).
   Das SVG traegt keine eigene Farbe, sondern `currentColor` — es
   folgt Hell und Dunkel damit von selbst und braucht, anders als
   die Explosionszeichnungen, keine Inversion. */
.spfloc__stage--norm {
    display: flex;
    align-items: center;
    justify-content: center;
    width: fit-content;
    max-width: 100%;
    margin: 0 auto;
    padding: 18px;
    color: #1a1a1a;
}
.spfloc__stage--norm .spfnt {
    width: 100%;
    max-width: 340px;
    height: auto;
}
body.spf-night .spfloc__stage--norm,
html.spf-night .spfloc__stage--norm {
    background: #17181a;
    color: #e7e7e7;
}

/* Modellangabe unter der Zeichnung. Sie muss auffallen: Ohne sie wirkt jede
   Zeichnung so, als gehoere sie zum Fahrzeug in der Garage — auch wenn das
   Teil dort gar nicht verbaut ist (Kili, 13.08.2026). */
.spfloc__modell {
    font-size: 12px;
    font-weight: 600;
    color: var(--ktm-text, #333);
}
body.spf-night .spfloc__modell,
html.spf-night .spfloc__modell {
    color: #e7e7e7;
}

/* ---------- OEM-Badge (Original-Ersatzteil) rechts oben am Galeriefeld ----------
   Per JS eingehaengt (spf-product-page.js setupOemBadge), Flag serverseitig aus
   class-spf-product-page.php (window.spfProductOem). Es haengt im DOM unter
   `.ktmpdp__stage` bzw. `.spfloc__stage` — und BEIDE tragen bereits
   `position: relative` (spf-product-layout.css bzw. weiter oben in dieser Datei).
   Ein eigener Anker ist deshalb nicht noetig.

   NICHT `.ktmpdp__gallery { position: relative }` setzen. Die Galerie hat aus
   spf-product-layout.css `position: sticky; top: 110px`. Wird nur `position`
   ueberschrieben, bleibt `top: 110px` stehen und bedeutet bei `relative` etwas
   voellig anderes: statt eines Klebepunkts eine VERSCHIEBUNG um 110 px nach
   unten. Die Zeichnung lag dadurch kurz richtig und rutschte dann ueber Titel,
   Preis und Reiter (Kili, 13.08.2026; gemessen: Grid-Zelle bei 175, Element bei
   285). Nebenbei ging auch das `position: static` der Media Query unter 991 px
   verloren. */
.spf-oem-flag {
  position: absolute; top: 10px; right: 10px; z-index: 5;
  display: inline-flex; align-items: center;
  background: #20242b; color: #fff;
  font-family: var(--spfcp-cond, 'Blender Pro', 'Oswald', system-ui, sans-serif);
  font-size: 11px; font-weight: 700; line-height: 1.2;
  text-transform: uppercase; letter-spacing: .05em;
  padding: 4px 10px; border-radius: 7px !important;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .3);
  pointer-events: none;
}
body.spf-night .spf-oem-flag,
html.spf-night .spf-oem-flag { background: #e8eaed; color: #16181c; box-shadow: 0 1px 4px rgba(0, 0, 0, .5); }
