/* ========================================
   Produkt-Beschreibungen mit Icons
   ======================================== */
.header-left a.logo img {
    object-fit: contain !important;
}


.product.attribute.description .value ul {
    padding-left: 0px !important;
    padding-inline-start: 0px !important;
    list-style: none;
}

.product.attribute.description .value ul li {
    position: relative;
    padding-left: 35px;
    margin-bottom: 12px;
    line-height: 1.6;
    font-family: 'Poppins', sans-serif;
    font-weight: 400;
}

.product.attribute.description .value ul li:before {
    content: '✓';
    position: absolute;
    left: 0;
    font-size: 20px;
    font-weight: 600;
    color: #4CAF50;
}


/* ========================================
   Quelle Input
   ======================================== */

#quelle_dv {
    display: flex;
    align-items: center;
    gap: 10px;
}

#quelle_dv input#quelle {
    width: 3em;
    text-align: center;
}


/* ========================================
   Grouped Product Table
   3 Spalten: Name à | Preis | Grundpreis
   Radio-Button versteckt, Zeile klickbar
   ======================================== */

#super-product-table {
    width: 100%;
    table-layout: auto;
    border-collapse: collapse;
    /* Abschluss-Hairline unter der letzten Zeile: schliesst die Optionsliste
       optisch (die Zwischenlinien kommen aus td{border-top}, unter der letzten
       Zeile fehlte sonst ein Strich) UND reserviert die 1px dauerhaft. Dadurch
       verschmilzt der gruene border-bottom von tr.selected bei der letzten
       Zeile mit dieser Linie statt 1px Hoehe zu addieren -> kein Springen der
       darunterliegenden Buttons mehr. Tabellen-Border hat im collapse-Modell
       die niedrigste Praezedenz, daher gewinnt der gruene Zeilen-Border bei
       Auswahl trotzdem. */
    border-bottom: 1px solid #e7e7e7;
}

#super-product-table td,
#super-product-table th {
    padding: 12px 10px;
    vertical-align: middle;
}

#super-product-table th {
    background: #f5f5f5;
    font-weight: 600;
    font-size: 0.9rem;
}

.table.grouped thead,
.table.grouped thead th {
    text-transform: none !important;
}

/* Verstecktes per-Zeile-Mengenfeld (number) bleibt off-screen.
   Das Radio wird NICHT mehr versteckt -> sichtbarer Auswahl-Marker (s.u.). */
#super-product-table input[type="number"] {
    position: absolute !important;
    left: -9999px !important;
    width: 1px !important;
    height: 1px !important;
    opacity: 0 !important;
    visibility: hidden !important;
}

/* Sichtbarer Auswahl-Marker: echtes Radio in Markenfarbe.
   Klarere "markierte Auswahl" als ein Seitenrahmen - der Mechanismus IST
   eine Radio-Single-Select (name=VerpackGroesse). Leerer Kreis = nicht
   gewaehlt, gefuellter gruener Kreis = gewaehlt. Plus Zeilen-Tint + fetter
   gruener Name (s. tr.selected). */
/* Marker = custom Check-Kreis (appearance:none, KEIN natives Radio):
   ungewaehlt zarter grauer Ring, gewaehlt Markengruen gefuellt. Der weisse
   Haken kommt auf DESKTOP als ::before der selektierten Zelle (Poppins-Glyphe
   \2713 - die bevorzugte Optik). MOBIL (<=767px) wird dieses Pseudo vom
   data-th-Killer entfernt (und wuerde dort ohnehin vom Radio uebermalt); dort
   traegt stattdessen das Radio selbst den Haken als background-image-SVG
   (s. Media-Query unten). Absolut in fixer Links-Spalte; Namen bleiben
   rechtsbuendig nah am Preis. */
#super-product-table .hidden-radio {
    appearance: none;
    -webkit-appearance: none;
    position: absolute !important;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    width: 20px !important;
    height: 20px !important;
    margin: 0 !important;
    opacity: 1 !important;
    visibility: visible !important;
    border: 1.5px solid #d2d2d2;
    border-radius: 50%;
    background: #fff;
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease;
}
#super-product-table tbody tr:hover .hidden-radio {
    border-color: color-mix(in srgb, var(--theme-color) 55%, #d2d2d2);
}
#super-product-table .hidden-radio:checked {
    border-color: var(--theme-color);
    background: var(--theme-color); /* gruener Kreis; Haken = ::before (Desktop) bzw. SVG (mobil, s.u.) */
}
#super-product-table td.col-name {
    position: relative;
    padding-left: 44px; /* Platz fuer das absolut positionierte Radio links */
}
/* DESKTOP-Haken: weisse Poppins-Glyphe als ::before der selektierten Zelle,
   z-index ueber dem Radio. Mobil wird dieses Pseudo vom data-th-Killer
   entfernt; dort traegt das Radio-SVG den Haken (s. Media-Query unten). */
#super-product-table tr.selected td.col-name::before {
    content: '\2713'; /* weisser Haken auf dem gruenen Kreis */
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    width: 20px;
    height: 20px;
    z-index: 2; /* ueber dem Radio-<input> (sonst verdeckt der gruene Kreis den Haken) */
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    line-height: 1;
    pointer-events: none;
}

/* Spalte 1: Name à
   KEIN nowrap: bei knappem Container darf der Name umbrechen statt hinter
   overflow-x:hidden hart abgeschnitten zu werden. Breiter Container -> bleibt
   ohnehin einzeilig. */
#super-product-table .col-name,
#super-product-table td.col-name {
    width: 45%;
    text-align: right;
}

#super-product-table td.col-name .item-name {
    font-weight: 500;
}

/* Ausverkauft-Hinweis: leise Metazeile UNTER dem Variantennamen (eigene Zeile,
   damit er die col-name nicht mehr horizontal aufblaeht und dadurch die
   Grundpreis-Spalte hinter overflow-x:hidden abschneidet). Neutrales #6b6b6b
   statt Alarm-Rot #c00 -> dezent, aber >= 4.5:1 (Status, keine Promotion). */
#super-product-table td.col-name .stock-unavailable {
    display: block;
    font-size: 0.72rem;
    font-weight: 400;
    color: #6b6b6b;
    margin-top: 1px;
    letter-spacing: .01em;
}

/* Spalte 2: Preis */
#super-product-table .col-price,
#super-product-table td.col-price {
    width: 25%;
    white-space: nowrap;
    text-align: center;
}

/* Spalte 3: Grundpreis - darf umbrechen (Textverlust bei schmalem Container
   vermeiden); rechtsbuendig, ggf. ueber 2 Zeilen. */
#super-product-table .col-baseprice,
#super-product-table td.col-grundpreis {
    width: 30%;
    text-align: right;
    font-size: 0.88rem;
}

/* Zeilen-Interaktion
   Marken-Schema (war generisches Blau #eaf3fb/#c8ddf0/#2196F3) ueber
   var(--theme-color)+color-mix -> shop-neutral. KEIN Side-Stripe mehr
   (border-left/right 4px war impeccable-Ban): Selected = flaechiger Tint
   + volle Hairline, klarere "ganze Zeile an"-Affordance. */
#super-product-table tbody tr {
    cursor: pointer;
    transition: background-color 0.15s ease;
}

#super-product-table tbody tr:hover {
    background-color: color-mix(in srgb, var(--theme-color) 7%, white);
}

/* Ausgewählte Zeile */
#super-product-table tr.selected {
    background-color: color-mix(in srgb, var(--theme-color) 12%, white);
    border-top: 1px solid color-mix(in srgb, var(--theme-color) 32%, white);
    border-bottom: 1px solid color-mix(in srgb, var(--theme-color) 32%, white);
}

#super-product-table tr.selected td.col-name .item-name {
    font-weight: 700;
    color: var(--theme-color, #2196F3);
}

#super-product-table tr.selected:hover {
    background-color: color-mix(in srgb, var(--theme-color) 16%, white);
}

/* Ausverkaufte Zeile (.oos-row): hat kein Radio -> nicht waehlbar. Die
   generische tbody-tr-Regel gibt ihr sonst cursor:pointer + Hover-Tint und
   suggeriert Klickbarkeit -> hier zuruecknehmen. Variantenname leicht gedimmt,
   damit die Zeile "nicht verfuegbar" liest, ohne laut zu sein. */
#super-product-table tbody tr.oos-row {
    cursor: default;
}
#super-product-table tbody tr.oos-row:hover {
    background-color: transparent;
}
#super-product-table tbody tr.oos-row td.col-name .item-name {
    color: #595959;
    font-weight: 400;
}

/* Price Styling */
.table.grouped .price-box .price {
    font-size: 1rem;
    font-weight: 600;
}

.table.grouped .price-box {
    margin: 0;
}


/* ========================================
   Custom-Option-Radios (Simple Products, z. B. "Größe")
   Gleiche Form-Control-Sprache wie die Grouped-Radios oben
   (#super-product-table): grauer Kreis -> gruen gefuellt + weisser Haken,
   Hover-Tint, gewaehlte Zeile gruen/fett. KEIN Tabellen-Layout - nur die
   schlanke Optionsliste als selektierbare Reihen veredelt.
   Strikt auf Radio-Optionen begrenzt (:has(> input[type=radio])), damit
   Checkbox-/Dropdown-/Text-Optionen nativ bleiben. */

/* Aufzaehlungsabstaende der Liste zuruecksetzen */
.product-options-wrapper .options-list {
    margin: 0;
}

/* Auswahlzeile: Radio links, Label fuellt den Rest, ganze Zeile als Affordance.
   Sichtbare Hairline im Ruhezustand (User-Befund kandissticks: mit
   border:transparent lasen sich die Zeilen als lose Textliste, nicht als
   klickbare Auswahl). */
.product-options-wrapper .field.choice:has(> input[type="radio"]) {
    position: relative;
    display: flex !important;
    align-items: center;
    gap: 10px;
    margin: 0 0 6px !important;
    padding: 9px 12px 9px 14px !important;
    border: 1px solid #e0e0e0;
    border-radius: 8px;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease;
}
.product-options-wrapper .field.choice:has(> input[type="radio"]):hover {
    background-color: color-mix(in srgb, var(--theme-color) 7%, white);
    border-color: color-mix(in srgb, var(--theme-color) 30%, #e0e0e0);
}

/* Mobil: Zeilenhoehe auf 48px-Touch-Target heben (9px-Padding ergibt nur ~40px) */
@media (max-width: 991px) {
    .product-options-wrapper .field.choice:has(> input[type="radio"]) {
        padding-top: 13px !important;
        padding-bottom: 13px !important;
    }
}

/* Natives Radio -> 20px Kreis (identisch zu .hidden-radio im Grouped-Table) */
.product-options-wrapper .field.choice > input[type="radio"] {
    appearance: none;
    -webkit-appearance: none;
    flex: 0 0 auto;
    width: 20px !important;
    height: 20px !important;
    margin: 0 !important;
    border: 1.5px solid #d2d2d2;
    border-radius: 50%;
    background-color: #fff;
    background-repeat: no-repeat;
    background-position: center;
    background-size: 12px 12px;
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease;
}
.product-options-wrapper .field.choice:hover > input[type="radio"] {
    border-color: color-mix(in srgb, var(--theme-color) 55%, #d2d2d2);
}

/* Gewaehlt: gruener Kreis + weisser Haken (SVG, kein Pseudo noetig) */
.product-options-wrapper .field.choice > input[type="radio"]:checked {
    border-color: var(--theme-color);
    background-color: var(--theme-color);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M2.5 6.4 4.8 8.7 9.5 3.6'/%3E%3C/svg%3E");
}
.product-options-wrapper .field.choice > input[type="radio"]:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--theme-color) 60%, white);
    outline-offset: 2px;
}

/* Label fuellt die Zeile (Klickflaeche), dunkler lesbarer Text */
.product-options-wrapper .field.choice:has(> input[type="radio"]) > label {
    flex: 1 1 auto;
    margin: 0 !important;
    padding: 0 !important;
    font-weight: 500;
    color: #2f2f2f;
    cursor: pointer;
}

/* Gewaehlte Zeile: flaechiger Tint + volle Hairline + Label gruen/fett */
.product-options-wrapper .field.choice:has(> input[type="radio"]:checked) {
    background-color: color-mix(in srgb, var(--theme-color) 12%, white);
    border-color: color-mix(in srgb, var(--theme-color) 32%, white);
}
.product-options-wrapper .field.choice:has(> input[type="radio"]:checked):hover {
    background-color: color-mix(in srgb, var(--theme-color) 16%, white);
}
.product-options-wrapper .field.choice:has(> input[type="radio"]:checked) > label {
    font-weight: 700;
    color: var(--theme-color);
}

/* Options-Titel ("Zuckerart") als echter Feldgruppen-Titel statt Porto-Default
   14px/#777 (unter AA, las sich wie Meta-Text neben dem grossen Preis). */
.product-options-wrapper .fieldset > .field > label.label {
    margin: 0 0 10px;
    font-size: 15px;
    font-weight: 600;
    color: #222529;
}

/* Pflicht-Kennzeichnung: das kryptische, unerklaerte "*" (Magento-Standard,
   ohne Legende auf der Seite) -> Badge-Pill. User-Befund kandissticks: das
   nackte Wort "erforderlich" klebte am Label ("Zuckerart erforderlich") und
   war nicht als Pflicht-Hinweis erkennbar. Bei Auswahl-Optionen wird daraus
   handlungsleitend "Bitte waehlen" in Markenfarbe; nach getroffener Wahl
   verschwindet das Badge (CSS :has). NUR in den Produktoptionen gescoped;
   Checkout/Adresse behalten ihr Standard-"*". */
.product-options-wrapper .field.required > label.label::after {
    content: "erforderlich";
    display: inline-block;
    margin-left: 8px;
    padding: 4px 9px;
    border-radius: 999px;
    background-color: #f2f2f2;
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    color: #555;
    letter-spacing: .02em;
    vertical-align: 2px;
}
.product-options-wrapper .field.required:has(input[type="radio"], input[type="checkbox"], select) > label.label::after {
    content: "Bitte wählen";
    background-color: color-mix(in srgb, var(--theme-color) 10%, white);
    color: color-mix(in srgb, var(--theme-color) 55%, #1a1d20);
}
.product-options-wrapper .field.required:has(input[type="radio"]:checked, input[type="checkbox"]:checked) > label.label::after {
    content: none;
}

/* Nicht-Auswahl-Meldung als klarer Inline-Hinweis. Strikt nur der
   Meldungsknoten (id endet auf "-error"), NICHT die input.mage-error-Radios
   (sonst wuerde jeder Kreis rot -> liest sich als "alle Optionen kaputt",
   obwohl nur die Gruppe unbeantwortet ist). Die Meldung traegt den Fehler. */
.product-options-wrapper .mage-error[id$="-error"] {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin-top: 10px;
    padding: 8px 12px;
    border-radius: 8px;
    background-color: color-mix(in srgb, #e02b27 8%, white);
    color: #b3221d;
    font-size: 0.9rem;
    font-weight: 600;
    line-height: 1.3;
}
.product-options-wrapper .mage-error[id$="-error"]::before {
    content: "!";
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background-color: #e02b27;
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    line-height: 1;
}

/* Regression-Fix: der gruene :focus-visible-Ring (Erfolgs-/Auswahlfarbe aus
   dem Radio-Styling oben) darf NICHT auf einem als Fehler fokussierten Radio
   liegen - Magento fokussiert das erste ungueltige Feld. Keine Rotfaerbung der
   Kreise; die Meldung kommuniziert den Fehler. */
.product-options-wrapper .field.choice > input[type="radio"].mage-error,
.product-options-wrapper .field.choice > input[type="radio"].mage-error:focus,
.product-options-wrapper .field.choice > input[type="radio"].mage-error:focus-visible {
    outline: none;
}


/* ========================================
   Versandtabelle
   ======================================== */

.versand {
    border-collapse: collapse;
    border-spacing: 0;
    width: 100%;
    display: block;
    overflow-x: auto;
}

.versand .kopf {
    vertical-align: middle;
    text-align: center;
    border: 1px solid;
    padding: 3px 10px;
}

.versand .mitte {
    vertical-align: middle;
    text-align: center;
    border: 1px solid;
    padding: 3px;
}

.versand .links {
    vertical-align: middle;
    text-align: left;
    border: 1px solid;
    padding: 3px;
}

.v-box {
    font-size: 0.9rem;
}

.lieferung-uebersicht h2 {
    margin: 0px;
}


/* ========================================
   Grouped Product Table - Responsive
   ======================================== */

.table-wrapper.grouped {
    overflow-x: hidden;
    container-type: inline-size;
    container-name: grouped-table;
}

/* Magento mobile override: Tabelle als Tabelle behalten */
@media (max-width: 767px) {
    #super-product-table,
    #super-product-table thead,
    #super-product-table thead tr,
    #super-product-table thead th,
    #super-product-table tbody,
    #super-product-table tbody tr,
    #super-product-table tbody td {
        display: revert !important;
    }

    /* Killt Portos mobile data-th-Labels (::before) - und damit auch den
       Desktop-Haken-::before, der mobil ohnehin vom Radio uebermalt wuerde. */
    #super-product-table tbody td:before {
        content: none !important;
        display: none !important;
    }

    /* MOBIL-Haken: da das ::before hier weg ist, traegt das Radio selbst den
       Haken als background-image-SVG (gleicher Paint wie der gruene Kreis,
       kein Stacking-Konflikt). Schlichte gleichmaessige Form wie zuvor.
       Steht spaeter im File als die globale :checked-Regel -> gewinnt <=767px. */
    #super-product-table .hidden-radio:checked {
        background: var(--theme-color)
            url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E")
            center / 12px no-repeat;
    }
}

/* Container < 400px: kompakter */
@container grouped-table (max-width: 400px) {
    #super-product-table {
        font-size: 0.85rem;
    }

    #super-product-table td,
    #super-product-table th {
        padding: 10px 6px;
    }

    .table.grouped .price-box .price {
        font-size: 0.92rem;
    }

    #super-product-table .col-baseprice,
    #super-product-table td.col-grundpreis {
        font-size: 0.8rem;
    }
}

/* Container < 300px (z. B. Produktseite 2-spaltig auf Tablet ~768px, Info-Spalte
   nur ~238px): engster Fall. Der Header "Grundpreis" ist ein unteilbares Wort
   und behielt sonst 0.9rem -> sprengte die 30%-Spalte um wenige px, die
   overflow-x:hidden am Wrapper abschnitt. Hier schrumpft der Header mit, das
   Padding wird knapper, die Grundpreis-Spalte bekommt mehr Anteil und das
   Radio-Padding wird reduziert -> Tabellen-Mindestbreite sicher unter Container. */
@container grouped-table (max-width: 300px) {
    #super-product-table {
        font-size: 0.8rem;
    }

    #super-product-table td,
    #super-product-table th {
        padding: 8px 3px;
    }

    #super-product-table th {
        font-size: 0.66rem; /* "Grundpreis" ist unteilbar -> muss klar in die Spalte passen */
    }

    #super-product-table td.col-name {
        padding-left: 38px; /* Radio (left:14px, 20px breit) braucht nur ~34px */
    }

    #super-product-table .col-name,
    #super-product-table td.col-name {
        width: 40%;
        white-space: normal;
    }

    /* Preis-Spalte gibt ihren Puffer an Grundpreis ab ("38,20 €" ist kompakt,
       "Grundpreis"-Header + Werte brauchen den Platz); Name bleibt unangetastet. */
    #super-product-table .col-price,
    #super-product-table td.col-price {
        width: 23%;
    }

    #super-product-table .col-baseprice,
    #super-product-table td.col-grundpreis {
        width: 37%;
        white-space: normal;
        font-size: 0.75rem;
    }

    .table.grouped .price-box .price {
        font-size: 0.85rem;
    }
}


/* ========================================
   Grundpreis (PAngV) bei Single-Produkten
   .grndsingle = Detailseite (unter Hauptpreis)
   .grndlist   = Kategorie-Listing + Related/Up-/Cross-Sell
   Kleiner, gedaempfter Hinweis unter dem Preis (Paritaet zu M1)
   ======================================== */
.grndsingle,
.grndlist {
    display: block;
    font-size: 0.8rem;
    line-height: 1.2;
    /* normal: im Preis-Container wuerde sonst der fette Preis-Font (600) vererbt */
    font-weight: normal;
    /* #6b6b6b statt #777: Grundpreis ist PAngV-Pflichtangabe und stand bei
       12.8px in #777 (4.48:1, unter AA). Haus-Muted haelt >=5:1. */
    color: #6b6b6b;
    margin-top: 2px;
}


/* ========================================
   Produkt-Tab-Titel Groesse (Details / Mehr Informationen / Bewertungen)
   Porto setzt sie auf 13px -> 1px KLEINER als der 14px-Body; fuer eine
   Sektions-Ueberschrift ist das rueckwaerts. Auf 15px (ueber Baseline =
   korrekte Hierarchie, keine Insel) + Tracking Richtung normal (Porto-
   Default 0.2px wirkt locker). !important, da Porto spaeter laedt
   ([[porto-css-override-important]]). Tabs sind hier vertikal gestapelt
   (wide_grid) -> kein Tab-Balken-Umbruch-Risiko; responsiv verifiziert.
   ======================================== */
.product.info.detailed .data.item.title > .switch,
.product.info.detailed .data.item.title > .switch > span {
    font-size: 15px !important;
    letter-spacing: normal !important;
}

/* ========================================
   OwnMag2Ext: Vertical-Tab Layout-Shift beim Seitenaufbau vermeiden.
   Porto rendert die aktive Tab-Inhaltsspalte (.data.item.content) als
   position:absolute (left:20%); dadurch ist der Tab-Container server-seitig nur so
   hoch wie die 20%-Titelspalte (~155px). Erst Portos Tab-JS setzt nachtraeglich die
   Container-Hoehe auf die Panel-Hoehe (~239px) -> die ganze "Verwandte Artikel"-
   Sektion darunter ruckt beim Seitenaufbau ~85px nach unten ("Sektion zu weit oben").
   Fix: Titel links floaten (clear:left -> enger linker Stapel), aktive Inhaltsspalte
   RECHTS floaten -> der Container hat schon beim First Paint die finale Hoehe
   max(Titelstapel, Inhalt). Kein JS, kein Magic-Number, content-agnostisch (auch bei
   langen Beschreibungen). KERN-Trick: Titel+Content sind im DOM verschachtelt
   (title->content->title->content); float:right nimmt den Content aus dem Fluss, sodass
   clear:left der Folge-Titel ihn IGNORIERT und die Titel eng stapeln (sonst schoebe
   in-flow-Content jeden Folge-Titel um die Panelhoehe nach unten). Nur >=768px, wo Porto
   das vertikale Absolut-Layout nutzt; mobil (<768px) stehen Titel+Inhalt ohnehin im Fluss
   (Accordion). Inaktive Panels bleiben display:none (0 Hoehe), nur das aktive bemisst. */
@media (min-width: 768px) {
    .catalog-product-view .product.info.detailed.vertical > .product.data.items > .data.item.title {
        float: left;
        clear: left;
        width: 20%;
    }
    .catalog-product-view .product.info.detailed.vertical > .product.data.items > .data.item.content {
        position: static !important;
        float: right;
        width: 80%;
    }
    .catalog-product-view .product.info.detailed.vertical > .product.data.items::after {
        content: "";
        display: block;
        clear: both;
    }
}
nav.navigation .submenu a,
nav.navigation .submenu a span {
    /* direkt auf Link + Text-Span: text-transform vererbt, ein
       Zwischenelement (ul.subchildmenu) setzt uppercase sonst direkt */
    text-transform: none !important;
}
nav.navigation .submenu .cat-label,
nav.navigation .submenu .cat-label span {
    text-transform: uppercase !important;
}


/* ========================================
   Sticky-Menue: Status-Badges ("Neu"/"Saison") ausblenden
   Top-Level-Badges sitzen mit top:-10px ueber dem Link. Im
   Sticky-Header (position:fixed; top:0) ragen sie ueber den
   oberen Viewportrand und werden zur Haelfte abgeschnitten.
   Im gehefteten Zustand daher ausblenden (im normalen Header
   bleiben sie sichtbar). !important, da Porto spaeter laedt
   ([[porto-css-override-important]]).
   ======================================== */
.page-header.sticky-header nav.navigation li.level0 > a > span.cat-label {
    display: none !important;
}


/* ========================================
   Naehrwertangaben-Tabelle (Produkt-Content)
   Content nutzt CSS-Pseudotabelle (.rTable) aus M1.
   Das zugehoerige CSS wurde nie mitmigriert -> hier nachgezogen.
   Paritaet zu M1: 1px solid #333, border-collapse, padding 3px 10px
   ======================================== */
.rTable {
    display: table;
    border-collapse: collapse;
    margin: 5px 0;
}
.rTableRow {
    display: table-row;
}
.rTableCell {
    display: table-cell;
    border: 1px solid #333;
    padding: 3px 10px;
    vertical-align: top;
}


/* ========================================
   Mengenfeld-Fehlermeldung ("Bitte Menge > 0")
   .control ist display:flex -> die Meldungs-Box wird sonst als Flex-Item in
   eine schmale Spalte neben dem Eingabefeld gequetscht.
   WICHTIG: .control bleibt position:relative (Porto-Default) - es ist der Anker
   fuer die absolut positionierten +/- Stepper-Buttons (.qty-changer > a).
   NICHT auf static setzen, sonst ankern Minus/Plus an .box-tocart und springen
   an die aeusseren Raender (Minus links, Plus rechts vom Button).

   ⚠️ NUR div/label.mage-error stylen, NICHT die nackte Klasse:
   jQuery-Validate haengt `mage-error` AUCH an das <input> selbst. Ein Selektor
   `.mage-error` zieht damit das Eingabefeld auf position:absolute -> es
   ueberlagert Plus, Zahl und Button. Tag-Einschraenkung schliesst den Input aus.
   Meldung absolut an .control ankern (linke Kante = Mengenfeld), top:100% = unter
   dem Feld, einzeilig nach rechts auslaufend.
   ======================================== */
.product-add-form .box-tocart .field.qty .control div.mage-error,
.product-add-form .box-tocart .field.qty .control label.mage-error {
    position: absolute;
    top: 100%;
    left: 0;
    width: max-content;
    max-width: 320px;
    height: auto;
    margin-top: 5px;
    white-space: normal;
    text-align: left;
    z-index: 2;
}


/* ============================================================
   product-info-main: Modernisierung (P0 Marke+Preis / P1 Ruhe /
   P2 Counter+Navigation+Fokus)
   ------------------------------------------------------------
   Farben NUR ueber var(--theme-color) + color-mix -> shop-neutral
   (edeltee gruen, naturteil eigene Farbe; KEIN Marken-Hex).
   !important, da Porto spaeter im Bundle laedt
   ([[porto-css-override-important]]). Scope: Single-Produkt-Spalte;
   Grouped-Mengen-Tabelle (.table.grouped) bleibt unberuehrt, da
   Stepper-Regeln auf .product-options-bottom .field.qty zielen.
   ============================================================ */

/* --- P0: CTA in Markenfarbe statt Near-Black (#222529) --- */
/* AA-Kontrast (Critique P1, s. base-typography.css): 85% Marke + 15%
   Schwarz statt reiner Markenfarbe - diese hoeher spezifische Regel
   (0,4,1) uebersteuerte sonst den shopweiten AA-Fix und liess den
   wichtigsten Button unter AA (Weiss auf #179c80 = 3.4:1). */
.product-add-form .box-tocart .action.tocart {
    background: color-mix(in srgb, var(--theme-color) 85%, #000) !important;
    border-radius: 8px !important;
    transition: background-color .2s ease, box-shadow .2s ease, transform .05s ease;
}
.product-add-form .box-tocart .action.tocart:hover {
    background: color-mix(in srgb, var(--theme-color) 72%, black) !important;
}
.product-add-form .box-tocart .action.tocart:active {
    transform: translateY(1px);
}
.product-add-form .box-tocart .action.tocart:focus-visible {
    outline: none;
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--theme-color) 25%, transparent) !important;
}

/* --- P0: Preis als zweitstaerkstes Element (nach Titel).
   KEIN Gradient-Text (Ban) - Gewicht/Groesse statt Farbe. --- */
.product-info-main .product-info-price .price-box .price {
    font-size: 2rem !important;
    font-weight: 700 !important;
    color: #1a1d20 !important;
    letter-spacing: -.02em;
}
/* Sale: durchgestrichener alter Preis bleibt gedaempft, special-price
   bekommt den Marken-Akzent (greift nur wenn old/special vorhanden). */
.product-info-main .product-info-price .old-price .price {
    font-weight: 600 !important;
    color: #a7a7a7 !important;
}
.product-info-main .product-info-price .special-price .price {
    color: var(--theme-color) !important;
}

/* --- P1: Hairline-Suppe entschaerfen ---
   Dekorativer 40px-Strich unter der Bewertung weg (Preis trennt schon). */
.product-info-main .product-reviews-summary:after {
    display: none !important;
}
/* tocart-Band: Doppelborder -> eine zarte, marken-getoente Trennlinie oben. */
.product-add-form .box-tocart {
    border-bottom: none !important;
    border-top: 1px solid color-mix(in srgb, var(--theme-color) 14%, #ededed) !important;
}

/* --- P0-Nicety: Titel gleichmaessiger umbrechen --- */
.product-info-main .page-title-wrapper h1 {
    text-wrap: balance;
}


/* ============================================================
   PRODUKTSEITE: Info-Spalte straffen (gegen den Leerraum unter
   dem Bild). Die Luecke ist primaer strukturell (Bild niedriger
   als die Info-Spalte) -> der Bild-Hebel laeuft separat ueber die
   Magento-Bildgroesse (view.xml). Diese drei Regeln nehmen nur die
   beitragenden Hoehen-/Typo-Faktoren zurueck.
   ============================================================ */

/* --- Kurzbeschreibung: erbte 16px/LH 27px direkt von Porto und wirkte
   dadurch groesser + luftiger als der Detail-Fliesstext (14px). Auf
   15px/1.6 zurueckgenommen = leise Lead-Hierarchie, nicht mehr dominant.
   Farbe auf AA-sicheres Ink: Porto-#777 lag bei 4.49:1 (knapp unter 4.5:1). --- */
.product-info-main .product.attribute.overview {
    font-size: 15px !important;
    line-height: 1.6 !important;
    color: #2f2f2f !important;
}

/* --- Detail-Tab-Fliesstext: gleicher #777->AA-Kontrast-Fix wie bereits
   im "Mehr Informationen"-Tab (#additional, dort schon #2f2f2f). --- */
.product.attribute.description .value,
.product.attribute.description .value p {
    color: #2f2f2f !important;
}

/* --- Auswahltabelle (Grouped): 12px-Zeilenpadding war auf Desktop zu
   hoch (5 Zeilen ~293px). Nur ab >=768px straffen; Mobile behaelt das
   groessere Padding, damit die Auswahlzeilen Tap-Target bleiben
   (~44px, vgl. Touch-Regel). --- */
@media (min-width: 768px) {
    #super-product-table td,
    #super-product-table th {
        padding-top: 7px !important;
        padding-bottom: 7px !important;
    }
}

/* --- P2: Counter als zusammenhaengendes Pill-Control ---
   .control: Rahmen + Radius + Fokus-Glow. KEIN overflow:hidden
   (wuerde die absolute Mengen-Fehlermeldung bei top:100% clippen).
   Positionswerte der absoluten ±-Buttons bleiben unangetastet.
   Scope `.box-tocart .field.qty` trifft das Einzel-Mengenfeld (Simple +
   Grouped-Sammelfeld); die Grouped-Zeilen-qtys liegen in `.table.grouped`,
   NICHT in `.box-tocart` -> bleiben unberuehrt. */
.product-add-form .box-tocart .field.qty .control {
    border: 1.5px solid color-mix(in srgb, var(--theme-color) 30%, #dadada) !important;
    border-radius: 8px !important;
    transition: border-color .2s ease, box-shadow .2s ease;
}
.product-add-form .box-tocart .field.qty .control:focus-within {
    border-color: var(--theme-color) !important;
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--theme-color) 16%, transparent) !important;
}
.product-add-form .box-tocart .field.qty .input-text.qty {
    background: transparent !important;
    border: none !important;
    font-weight: 700 !important;
    color: #1a1d20 !important;
}
.product-add-form .box-tocart .field.qty .qty-changer > a {
    color: #888 !important;
    border: none !important; /* Porto-Default #e7e7e7-Kasten raus -> nur der gruene .control-Rahmen bleibt (kein Doppel-Rahmen) */
    transition: background-color .15s ease, color .15s ease;
}
.product-add-form .box-tocart .field.qty .qty-changer > a:hover {
    background: color-mix(in srgb, var(--theme-color) 12%, transparent) !important;
    color: var(--theme-color) !important;
}

/* --- P2: Produkt-Navigation (prev/next) - klare Hover-State --- */
.product-info-main .prev-next-products .product-nav > a {
    border-color: color-mix(in srgb, var(--theme-color) 28%, #e0e0e0) !important;
    color: #555 !important;
    transition: background-color .2s ease, color .2s ease, border-color .2s ease;
}
.product-info-main .prev-next-products .product-nav > a:hover,
.product-info-main .prev-next-products .product-nav > a:focus-visible {
    background: var(--theme-color) !important;
    border-color: var(--theme-color) !important;
    color: #fff !important;
    outline: none;
}

/* --- P2: Grouped-Mengenfeld -> echter Spinner (− Zahl +) ---
   #quelle ist ein nackter Text-Input; grouped.phtml umschliesst ihn jetzt
   mit .qty-stepper (+/- Buttons + JS). Pill-Rahmen am Wrapper, Input randlos
   (kein Doppelrahmen). Fokus-Glow am Wrapper. */
#quelle_dv .qty-stepper {
    display: inline-flex;
    align-items: stretch;
    height: 44px;
    border: 1.5px solid color-mix(in srgb, var(--theme-color) 30%, #dadada);
    border-radius: 8px;
    overflow: hidden;
    transition: border-color .2s ease, box-shadow .2s ease;
}
#quelle_dv .qty-stepper:focus-within {
    border-color: var(--theme-color);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--theme-color) 16%, transparent);
}
#quelle_dv .qty-stepper button {
    width: 34px !important;     /* !important: Porto-Button-Styles setzen sonst ~80px (min-width/padding) */
    min-width: 0 !important;
    padding: 0 !important;
    flex: 0 0 auto;
    border: none;
    background: transparent;
    color: #888;
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}
#quelle_dv .qty-stepper button:hover {
    background: color-mix(in srgb, var(--theme-color) 12%, transparent);
    color: var(--theme-color);
}
#quelle_dv input#quelle {
    width: 44px !important;
    border: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    background: transparent !important;
    text-align: center;
    font-weight: 700;
    color: #1a1d20;
    height: auto !important;
    padding: 0;
}

/* --- product-info-main: Abstaende & Stock/SKU einzeilig ---
   Stock + SKU standen 2-zeilig (Porto: .product-info-stock-sku > * display:block)
   -> eine Zeile via flex; SKU ist Sekundaerinfo -> gedimmt. Gilt fuer alle
   Produkttypen. */
.product-info-main .product-info-stock-sku {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: 1.5rem;
    margin: 1em 0;
    /* Normalschreibung statt Versalien (Lesbarkeit, konsistent mit
       [[porto-allcaps-to-normal-and-css-deploy]]); "SKU" bleibt als Akronym. */
    text-transform: none !important;
}
.product-info-main .product-info-stock-sku > * {
    margin-bottom: 0 !important;
}
.product-info-main .product-info-stock-sku .product.attribute.sku {
    flex: 0 0 auto !important; /* Magento setzt flex-basis:100% -> sonst eigene Zeile */
    width: auto !important;
}
.product-info-main .product-info-stock-sku .product.attribute.sku,
.product-info-main .product-info-stock-sku .product.attribute.sku .value {
    /* #6b6b6b statt #9a9a9a: 2.8:1 war klarer AA-Fail (Critique 2026-07-19);
       Haus-Muted bleibt leise, ist aber lesbar. */
    color: #6b6b6b !important;
    font-weight: 400 !important;
}

/* Preishinweis "Alle Preise inkl. MwSt., zzgl. Versandkosten" = leise
   Fine-Print direkt am Preis. Gemeinsame Optik fuer Grouped (Preistabelle)
   und Simple (Preis-Container) -> eine Quelle, konsistentes Bild.
   #6f6f6f statt #777: haelt die leise Anmutung, klart aber >=4.5:1 Kontrast. */
.page-product-grouped .v_box,
.product-info-price .price-tax-note {
    font-size: .85rem;
    font-weight: 400;
    color: #6f6f6f;
}
/* PAngV: der Versandkosten-Link MUSS als "sprechender Link" erkennbar bleiben.
   Erkennbarkeit hier ueber abweichende Farbe (Marken-Gruen), bewusst OHNE
   Unterstreichung. #1b8268: heller/auffaelliger als das vorherige #2f6d5c,
   aber noch unter dem lauten Voll-Gruen -> haelt 4.73:1 Kontrast auf Weiss. */
.page-product-grouped .v_box a,
.product-info-price .price-tax-note a {
    color: #1b8268;
    text-decoration: none;
}
/* Grouped: gehoert zur Preistabelle darueber -> Luft NACH UNTEN zum Spinner. */
.page-product-grouped .v_box {
    margin: .25rem 0 1.25rem;
}
/* Simple: sitzt im Preis-Container nach Haupt-/Grundpreis -> kleine Luft nach
   oben vom Preis weg, etwas mehr nach unten zur Mengen-/CTA-Zeile. */
.product-info-price .price-tax-note {
    margin: .5rem 0 0;
}


/* ============================================================
   "Mehr Informationen"-Tab modernisiert (Attribut-Spezifikation +
   Naehrwert-Panel)
   ------------------------------------------------------------
   Core-Template `additional` rendert table.additional-attributes
   (Label/Wert) + teils ein verschachteltes .rTable-Pseudo-Gitter
   (Naehrwertangaben). Beides war generisch: Wert-Text #777 (~4.48:1,
   knapp UNTER 4.5:1 Body-Kontrast) und das Naehrwert-Gitter ein nacktes
   1px-#333-Raster (M1-Altlast, vgl. .rTable oben ~Z.1986).
   Ziel: ruhige, scanbare Spezifikation + modernes Naehrwert-Panel,
   das Transparenz/Vertrauen (Bio, Herkunft, Zutaten, Naehrwerte) staerkt.

   Spezifitaet: alle Selektoren fuehren mit #additional -> schlagen Portos
   klassenbasierte Tabellen-CSS ohne !important (live verifiziert), und der
   enge Scope haelt die Regeln aus Magento-weiten .data.table/.rTable-Stellen
   (Warenkorb, Bestellungen, CMS) heraus. Farben shop-neutral ueber
   var(--theme-color)+color-mix (edeltee gruen, naturteil eigene Farbe),
   8px-Radius = Theme-Standard ([[megamenu-m1-parity-and-radius-standard]]).
   ============================================================ */
/* Volle Inhaltsbreite (KEIN max-width-Cap): die Tabelle war im Original
   voll breit und soll konsistent zur Beschreibung/Seite bleiben - ein Cap
   wirkt als schmale Insel (besonders im vertikalen Tab-Layout). */
#additional .additional-attributes-wrapper {
    max-width: none;
    overflow-x: visible;
    margin-top: 4px;
}
/* Caption "Mehr Informationen" dupliziert den Tab-Titel visuell ->
   ausblenden, aber als zugaenglichen Tabellennamen erhalten (sr-only,
   nicht display:none -> sonst raus aus dem A11y-Baum). */
#additional table.additional-attributes > caption.table-caption {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

/* Werte: Kontrast-Fix (#777 -> #2f2f2f ~13:1) + Leserhythmus, global */
#additional table.additional-attributes td.col.data {
    color: #2f2f2f;
    font-size: 14px;
    line-height: 1.62;
    /* Tracking auf normal: Portos 0.2px-Default wirkt locker; der Prosa-Tab
       (#description p) liegt schon bei ~normal -> konsistent + crisper. */
    letter-spacing: normal;
}
#additional table.additional-attributes td.col.data p {
    margin: 0 0 6px;
    /* 13 -> 14: vermeidet muddy 13/14-Hierarchie zu den Klartext-Werten
       in derselben Spalte; Sekundaer-Rolle traegt die gedaempfte Farbe. */
    font-size: 14px;
    color: #707070;
}
#additional table.additional-attributes td.col.data a {
    color: var(--theme-color);
    text-decoration: underline;
    text-underline-offset: 2px;
    text-decoration-thickness: 1px;
}
#additional table.additional-attributes td.col.data a:hover {
    color: color-mix(in srgb, var(--theme-color) 70%, #000);
}
/* Siegel/Zertifikate (Bio-Siegel, EU-Bio-Blatt, Logos) als ruhige
   "Stempel" praesentieren -> staerkt Vertrauen, ohne Karte/Side-Stripe.
   Bild direkt getargetet (kein hardcodierter Text -> auch fuer rs1-5/
   maoci-logo unschaedlich), etwas groesser fuer Praesenz. */
#additional table.additional-attributes td.col.data img {
    vertical-align: middle;
    height: 40px;
    width: auto;
    padding: 7px 10px;
    margin: 2px 8px 2px 0;
    background: #fff;
    border: 1px solid #e6e6e6;
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .05);
}

/* Desktop: zwei Spalten mit Haarlinien, Label gedaempfter Fuehrungstext */
@media (min-width: 768px) {
    #additional table.additional-attributes {
        width: 100%;
        border-collapse: collapse;
        table-layout: auto;
    }
    #additional table.additional-attributes > tbody > tr {
        border-bottom: 1px solid #ececec;
    }
    #additional table.additional-attributes > tbody > tr:last-child {
        border-bottom: 0;
    }
    #additional table.additional-attributes th.col.label {
        /* Label-Spalte inhaltsbreit (width:1% + nowrap schrumpft auf das
           laengste Label) -> kurze Begriffe vergeuden keinen Raum (kein
           50/50) UND lange Labels brechen auf Desktop NICHT um (der
           Soft-Hyphen-Umbruch war nur fuers Mobile-Stacking gedacht). */
        width: 1%;
        white-space: nowrap;
        padding: 15px 32px 15px 0;
        font-weight: 600;
        /* 13 -> 14 = Body-Baseline (Beschwerde "kleiner als der Rest");
           Sekundaer-Rolle traegt weight 600 + gedaempfte Farbe, nicht Groesse. */
        font-size: 14px;
        letter-spacing: normal;
        color: #6a6a6a;
        text-align: left;
        vertical-align: top;
        line-height: 1.5;
    }
    #additional table.additional-attributes td.col.data {
        padding: 15px 0;
        vertical-align: top;
    }
}

/* Mobile (<768px): Porto blendet <th> aus und zieht das Label aus data-th
   per ::before. Gestapelte Zeilen ruhiger gruppieren, Label als fetter
   Vorlauf. (Hinweis: data-th einiger Attribute enthaelt ein doppelt
   escaptes "&shy;" -> erscheint hier roh; Fix im Attribut-Label, nicht CSS.) */
@media (max-width: 767px) {
    #additional table.additional-attributes td.col.data {
        padding: 10px 0 16px;
        border-bottom: 1px solid #ececec;
    }
    #additional table.additional-attributes > tbody > tr:last-child td.col.data {
        border-bottom: 0;
    }
    #additional table.additional-attributes td.col.data::before {
        display: block;
        margin-bottom: 4px;
        font-weight: 600;
        font-size: 14px;
        color: #6a6a6a;
    }
}

/* Naehrwert-Panel: aus dem nackten #333-Gitter ein modernes, scanbares
   Panel. Zeilen = Flex (Naehrstoff links / Wert rechts, tabular-nums),
   zarte Marken-Zebra, Brennwert als betonte Kopf-Kennzahl. */
#additional .rTable {
    display: block;
    border: 1px solid #e6e6e6;
    border-radius: 8px;
    overflow: hidden;
    max-width: 440px;
    margin: 10px 0 6px;
    background: #fff;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .03);
}
#additional .rTableBody {
    display: block;
}
#additional .rTableRow {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 18px;
    padding: 9px 16px;
    border-bottom: 1px solid #f1f1f1;
}
#additional .rTableRow:last-child {
    border-bottom: 0;
}
#additional .rTableRow:nth-child(even) {
    background: color-mix(in srgb, var(--theme-color) 4%, #fff);
}
/* Brennwert = erste Zeile, betonte Kopf-Kennzahl */
#additional .rTableRow:first-child {
    background: color-mix(in srgb, var(--theme-color) 9%, #fff);
}
#additional .rTableCell {
    display: block;
    border: 0;
    padding: 0;
    font-size: 14px;
    line-height: 1.4;
    letter-spacing: normal;
    color: #3a3a3a;
}
#additional .rTableCell:first-child {
    color: #565656;
}
#additional .rTableCell:last-child {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    text-align: right;
    color: #262626;
}
/* Brennwert-Zeile: ruhig abgesetzt ueber getoenten Hintergrund + dunklere
   Farbe, bewusst OHNE Fettung (Zahlen brauchen keine Extra-Hervorhebung). */
#additional .rTableRow:first-child .rTableCell {
    color: #1f1f1f;
}


/* ============================================================
   Bewertungs-Tab (#reviews) — Marken-Veredelung
   Stock-Magento/Porto-Default → edle, grüne Markensprache:
   - letzte Orange-Insel (Submit-Button) auf Marken-Grün gespiegelt
     (identisch zum "In den Warenkorb"-CTA: #179c80 / 8px / 700),
   - Versalien-Legende "SIE BEWERTEN" → Satzschreibung,
   - Kontrast #777 → Marken-Ink #2f2f2f,
   - Listing aus der rohen Tabellen-Optik in eine ruhige,
     scanbare Form (Titel · Sterne · Text · Meta),
   - Eingaben mit 8px-Radius + grünem Fokus-Ring.
   Porto/Smartwave laden spaeter → Overrides brauchen !important.
   ============================================================ */
#reviews {
    --o2e-rev-ink: #2f2f2f;
    --o2e-rev-muted: #6b6b6b;
    --o2e-rev-line: rgba(0, 0, 0, .10);
    --o2e-rev-gold: #f3a712;
    --o2e-rev-green: var(--theme-color, #179c80);
}

/* Sichtbar-versteckt (Screenreader behaelt Text) statt display:none.
   Trifft u. a. das redundante "Bewertung"-Label neben den Sternen im Listing
   sowie den Core-Listing-Titel "Kundenbewertungen" — der stand seit dem
   Redesign doppelt direkt unter unserer Sektions-h2 "Bewertungen". */
#reviews .o2e-vh,
#reviews .block.review-list .block-title,
#reviews .block.review-list .review-ratings .label {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    margin: -1px !important;
    padding: 0 !important;
    border: 0 !important;
    overflow: hidden !important;
    clip: rect(0 0 0 0) !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
}

/* ---------- Section-Ueberschriften (Listing + Formular) ---------- */
#reviews .block.review-list .block-title,
#reviews .block.review-add .block-title {
    display: block !important;
    margin: 0 0 1.25rem !important;
    padding-bottom: .6rem !important;
    border-bottom: 1px solid var(--o2e-rev-line) !important;
}
#reviews .block.review-list .block-title strong,
#reviews .block.review-add .block-title strong {
    color: var(--o2e-rev-ink) !important;
    font-size: 1.3rem !important;
    font-weight: 700 !important;
    line-height: 1.25 !important;
    text-transform: none !important;
}

/* Pager-Limiter ("Anzeigen 10/20/50 pro Seite") ist bei wenigen Bewertungen
   reiner Ballast und zog eine zweite Strich-Linie unter dem Listing → raus,
   Toolbar-Rahmen entfernen, damit nur EIN sauberer Trenner bleibt. */
#reviews .review-toolbar {
    border: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
}
#reviews .review-toolbar .limiter { display: none !important; }

/* Trennung Listing ↔ Formular (einziger Trenner) */
#reviews .block.review-add {
    margin-top: 2.75rem !important;
    padding-top: 2.25rem !important;
    border-top: 1px solid var(--o2e-rev-line) !important;
}

/* ---------- Listing: einzelne Bewertung ---------- */
#reviews .review-items {
    margin: 0 !important;
    padding: 0 !important;
    list-style: none !important;
}
#reviews .review-item {
    padding: 1.5rem 0 !important;
    border-bottom: 1px solid var(--o2e-rev-line) !important;
}
#reviews .review-item:first-child { padding-top: .25rem !important; }
#reviews .review-item:last-child { border-bottom: 0 !important; }

#reviews .review-title {
    color: var(--o2e-rev-ink) !important;
    font-size: 1.05rem !important;
    font-weight: 700 !important;
    line-height: 1.3 !important;
    margin: 0 0 .5rem !important;
}

/* Sterne auf eigene Zeile (Porto floatet .review-ratings → Text lief drumherum) */
#reviews .block.review-list .review-ratings,
#reviews .block.review-list .review-ratings .rating-summary {
    display: block !important;
    float: none !important;
    width: auto !important;
    margin: 0 0 .65rem !important;
}
#reviews .block.review-list .review-item { display: block !important; }
#reviews .block.review-list .rating-result > span:before { color: var(--o2e-rev-gold) !important; }

#reviews .review-content {
    color: var(--o2e-rev-ink) !important;
    /* 1rem = native Basisgroesse (16px), nicht kuenstlich verkleinert */
    font-size: 1rem !important;
    line-height: 1.75 !important;
    max-width: none !important;
    margin: 0 0 .65rem !important;
}

/* Details-Tab (#description): Porto rendert die Hauptbeschreibung in 14px,
   also kleiner als die Bewertungen. Auf 1rem (16px) anheben — gleiche Groesse
   wie der Review-Text — fuer einheitliche, gut lesbare Produkttexte. */
#reviews .review-content,
#description,
#description p,
#description li,
#description td {
    font-size: 1rem !important;
}
#description,
#description p,
#description li {
    line-height: 1.75 !important;
}
#reviews .review-details,
#reviews .review-author,
#reviews .review-details .review-details-value,
#reviews .review-details time {
    color: var(--o2e-rev-muted) !important;
    font-size: .85rem !important;
    line-height: 1.5 !important;
}
#reviews .review-author { margin: 0 !important; }
#reviews .review-details-label { font-weight: 600 !important; }

/* ---------- Formular ---------- */
#reviews .review-legend {
    text-transform: none !important;
    color: var(--o2e-rev-muted) !important;
    font-size: .95rem !important;
    font-weight: 400 !important;
    line-height: 1.5 !important;
    margin: 0 0 1.5rem !important;
}
#reviews .review-legend > strong {
    color: var(--o2e-rev-ink) !important;
    font-weight: 700 !important;
}

/* Feld-Labels: Satzschreibung, kontrastreich */
#reviews .review-form .label,
#reviews .review-field-ratings > .label {
    text-transform: none !important;
    color: var(--o2e-rev-ink) !important;
    font-weight: 600 !important;
}
#reviews .review-field-ratings > .label {
    font-size: .95rem !important;
    margin-bottom: .5rem !important;
}

/* Eingabefelder: 8px-Radius, gemessene Breite, gruener Fokus-Ring */
#reviews .review-form input[type="text"],
#reviews .review-form textarea {
    border: 1px solid var(--o2e-rev-line) !important;
    border-radius: 8px !important;
    background: #fff !important;
    color: var(--o2e-rev-ink) !important;
    transition: border-color .18s ease, box-shadow .18s ease !important;
}
#reviews .review-field-nickname .control,
#reviews .review-field-summary .control { max-width: 520px !important; }
#reviews .review-field-text .control { max-width: 640px !important; }
#reviews .review-form input[type="text"]:focus,
#reviews .review-form textarea:focus {
    border-color: var(--o2e-rev-green) !important;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--o2e-rev-green) 18%, transparent) !important;
    outline: none !important;
}

/* ---------- Submit: identisch zum "In den Warenkorb"-CTA ---------- */
#reviews button.action.submit.primary {
    background-color: var(--o2e-rev-green) !important;
    border-color: var(--o2e-rev-green) !important;
    color: #fff !important;
    border-radius: 8px !important;
    font-weight: 700 !important;
    transition: background-color .18s ease, box-shadow .18s ease, transform .12s ease !important;
}
#reviews button.action.submit.primary:hover {
    background-color: color-mix(in srgb, var(--o2e-rev-green) 88%, #000) !important;
    border-color: color-mix(in srgb, var(--o2e-rev-green) 88%, #000) !important;
}
#reviews button.action.submit.primary:active { transform: translateY(1px) !important; }
#reviews button.action.submit.primary:focus-visible {
    outline: none !important;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--o2e-rev-green) 30%, transparent) !important;
}

@media (prefers-reduced-motion: reduce) {
    #reviews .review-form input[type="text"],
    #reviews .review-form textarea,
    #reviews button.action.submit.primary { transition: none !important; }
}


/* ============================================================
   Trust-/Reassurance-Zeile unter dem Warenkorb-CTA (.om-trust)
   Block: product.info.trustbadges (trust-badges.phtml), alle Produkttypen.
   Nur universell wahre Claims (kein Bio hier). Markengrün, mobile-first.
   ============================================================ */
.product-info-main .om-trust,
.om-trust {
    display: grid !important;
    grid-template-columns: 1fr; /* nur noch 1 Claim (Versand); Rechnung entfernt, s. trust-badges.phtml */
    gap: 12px 18px;
    margin: 6px 0 6px !important;
    padding: 15px 18px;
    border: 1px solid color-mix(in srgb, var(--theme-color) 22%, #e6e6e6);
    border-radius: 8px;
    background: color-mix(in srgb, var(--theme-color) 4%, #fff);
}
.om-trust__item {
    display: flex !important;
    align-items: center;
    gap: 9px;
    font-size: 13.5px;
    line-height: 1.3;
    color: #2f2f2f !important;
    font-weight: 500;
}
.om-trust__item svg {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    color: var(--theme-color) !important;
}
.om-trust__item small {
    color: #777;
    font-weight: 400;
    font-size: .82em;
}
/* Phones: einspaltig (scanbar, kein gequetschter Umbruch).
   Spezifitaet muss .product-info-main .om-trust matchen, sonst gewinnt die
   Basisregel trotz Media Query (MQ erhoeht Spezifitaet nicht). */
@media (max-width: 480px) {
    .product-info-main .om-trust,
    .om-trust { grid-template-columns: 1fr !important; gap: 11px; }
}


/* ============================================================
   Buy-Box: Menge ÜBER dem Button, "In den Warenkorb" volle Breite.
   Single an Grouped angeglichen -> maximale CTA-Prominenz + Mobil-Tap-Target.
   Scope .box-tocart: stapelt bei Simple qty+actions (Grouped hat qty=#quelle
   ausserhalb -> nur der CTA wird voll breit). qty-Stepper bleibt links/kompakt.
   ============================================================ */
.product-add-form .box-tocart .fieldset {
    display: flex !important;
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 14px !important;
}
.product-add-form .box-tocart .actions {
    width: 100% !important;
    display: block !important;
}
.product-add-form .box-tocart .action.tocart {
    width: 100% !important;
}


/* ========================================
   PRODUKTSEITE — Staffelpreise (.prices-tier) gezaehmt
   Befund kandissticks-braun-weiss.html (edeltee): Porto rendert die
   Tier-Preis-Zahlen ("10 fuer jeweils 0,55 EUR ...") in derselben
   32px-Preisschrift wie den Hauptpreis -> zwei Riesenpreise unter dem
   Kaufpreis dominieren die Seite, die Hierarchie kippt. Der umgebende
   Satz stand zudem in #777 (4.07:1, unter AA).
   Fix: Staffelzeilen als ruhiger Fliesstext in Ink, der Stueckpreis
   fett in Textgroesse, die Ersparnis als Benefit in abgedunkelter
   Markenfarbe (reines #179c80 laege bei ~3.3:1 und faellt bei 14px
   fett noch unter AA). !important noetig: Porto laedt spaeter im
   Bundle und setzt die 32px direkt auf .prices-tier .price.
   ================================================================== */
.product-info-main .prices-tier {
    margin: 0 0 20px;
    padding: 0;
    list-style: none;
    font-size: 14px;
    line-height: 1.6;
    color: #2f2f2f;
}
.product-info-main .prices-tier .item {
    margin: 0 0 4px;
}
.product-info-main .prices-tier .price {
    font-size: 15px !important;
    font-weight: 700 !important;
    color: #222529;
}
.product-info-main .prices-tier .benefit {
    font-weight: 700;
    color: color-mix(in srgb, var(--theme-color) 78%, #1a1d20);
}


/* ============================================================
   Bewertungssterne — einheitliches Gold/Grau-Farbsystem
   Entscheidung (final): gefuellt/gewaehlt #f3a712 (Marken-Gold,
   = --o2e-rev-gold), leer/inaktiv #cfd0d2 (Neutralgrau),
   Hover-Preview beim Bewerten #f6b840 (helleres Gold).
   Ersetzt Portos Stock-Rot (#FF5B5B, per getComputedStyle gemessen
   auf .product-info-main .product-reviews-summary .rating-result)
   und gibt dem Bewertungsformular echtes Hover-/Checked-Feedback
   (bisher: Farbe fuer Hover UND Checked identisch #FFC600, keine
   Unterscheidung der Zustaende).
   ACHTUNG Scope: .rating-result/.review-control-vote kommen AUCH in
   Grid-/Karussell-Overlays vor (.type8/.type11, _listings.less
   Z.641-648/881-886) — dort ABSICHTLICH weiss auf dunklem BG OHNE
   !important. Ein globales !important auf bare .rating-result wuerde
   diese unsichtbar machen. Deshalb NIE auf bare .rating-result /
   .review-control-vote zielen — immer .product-info-main-Praefix
   bzw. #reviews-Scope. .review-control-vote selbst kommt nachweislich
   (grep) nur im Bewertungsformular vor (Magento_Review/_module.less),
   kein Karussell-Treffer.
   Porto/Smartwave laden spaeter -> Overrides brauchen !important.
   ============================================================ */
:root {
    --o2e-star-empty: #cfd0d2;
    --o2e-star-filled: #f3a712;
    --o2e-star-hover: #f6b840;
}

/* ---- Produktkopf: Rating-Zusammenfassung ---- */
.product-info-main .rating-summary .rating-result::before,
.product-info-main .product-reviews-summary .rating-summary .rating-result::before {
    color: var(--o2e-star-empty) !important;
}
.product-info-main .rating-summary .rating-result > span::before,
.product-info-main .product-reviews-summary .rating-summary .rating-result > span::before {
    color: var(--o2e-star-filled) !important;
}

/* Review-Liste: leere Sterne ebenfalls neutral-grau
   (gefuellt ist bereits --o2e-rev-gold, s. Zeile ~4971) */
#reviews .block.review-list .rating-result::before {
    color: var(--o2e-star-empty) !important;
}

/* ---- Bewertungsformular: progressive Fuellung bei Hover/Klick ----
   Reales DOM (gemessen china-white-monkey.html, Tab "Bewertung
   schreiben"): pro Stern EIN <input type="radio" id="Bewertung_N">
   gefolgt von <label class="rating-N">, in VORWAERTS-Reihenfolge
   N=1..5 (kein reverse-DOM-Trick, kein "~"-Geschwister-Selektor
   noetig). Porto stapelt die Labels absolut uebereinander
   (z-index 6..2 fuer rating-1..rating-5, Breite wachsend), und JEDES
   Label enthaelt bereits SEIN EIGENES N-Sterne-Glyph als content
   (rating-4::before = 4 Zeichen). Sichtbarkeit laeuft ausschliesslich
   ueber opacity (0 -> 1 bei label:hover bzw. bei
   input:checked + label), NICHT ueber Farbe — die Farbe war bislang
   fuer Hover- und Checked-Reveal identisch (#FFC600). Wir lassen
   Portos opacity-Mechanik unangetastet und tunen nur die Farben:
   Basis/Hover-Reveal = Hover-Gold, Checked-Reveal (hoehere Spezifitaet
   durch input:checked+label) = Marken-Gold. */
.review-control-vote::before {
    color: var(--o2e-star-empty) !important;
}
.review-control-vote label::before {
    color: var(--o2e-star-hover) !important;
}
.review-control-vote input[type="radio"]:checked + label::before {
    color: var(--o2e-star-filled) !important;
}


/* ========================================
   Produktseite: Info-Bereich "Expanded Sections" im Zweispalter
   (details.phtml-Override, Issue produktseite-info/01) — ersetzt
   Portos Vertikal-Tabs.
   Datenquelle Fakten-Spalte: OwnMag2Ext\ProductInfo\ViewModel\ProductInfo.
   Tokens: Markenfarbe nur ueber var(--theme-color), Fliesstext/Labels
   #2f2f2f, Headings #222529, Muted #6b6b6b, Radius 8px, Karten-Border
   1.5px color-mix(in srgb, var(--theme-color) 30%, #dadada).
   ======================================== */
.o2e-pinfo {
    display: grid;
    /* 32.65% = gemessene Breite von Portos .product-info-main (457/1400 bzw.
       385/1180) — die Fakten-Spalte fluchtet damit buendig mit der Kauf-/
       Optionen-Box darueber (rechte Kante ist durch das Grid automatisch
       buendig, nur die Spaltenbreite musste angeglichen werden). */
    grid-template-columns: minmax(0, 1fr) minmax(300px, 32.65%);
    /* Bewertungen als eigenes Grid-Kind: Desktop unter der Erzaehlspalte,
       mobil NACH den Fakten (kaufrelevante Fakten vor dem Review-Formular). */
    grid-template-areas:
        "main facts"
        "reviews facts";
    /* auto 1fr: die Bewertungen starten direkt nach der Erzaehlspalte.
       Ohne das verteilt das Grid die Hoehe der (oft laengeren) Fakten-
       Spalte auf beide Zeilen -> Loch zwischen Beschreibung und
       Bewertungen bei kurzen Beschreibungen. */
    grid-template-rows: auto 1fr;
    column-gap: clamp(32px, 4vw, 56px);
    row-gap: 40px;
    align-items: start; /* bewusst kein sticky */
    margin-top: 10px;
}
.o2e-pinfo--single {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
        "main"
        "reviews";
}
.o2e-pinfo__main,
.o2e-pinfo__facts {
    min-width: 0;
}
.o2e-pinfo__main {
    grid-area: main;
}
.o2e-pinfo__facts {
    grid-area: facts;
    display: grid;
    gap: 24px;
    align-content: start;
}
.o2e-pinfo__section + .o2e-pinfo__section {
    border-top: 1px solid #e7e7e7;
    margin-top: 36px;
    padding-top: 32px;
}
.o2e-pinfo__section--bewertungen {
    grid-area: reviews;
    /* Trennlinie frueher via Section-Adjazenz in __main; als eigenes
       Grid-Kind bringt die Sektion sie selbst mit. */
    border-top: 1px solid #e7e7e7;
    padding-top: 32px;
    min-width: 0;
}
.o2e-pinfo__title {
    font-size: 20px;
    font-weight: 700;
    color: #222529;
    margin: 0 0 14px;
    text-transform: none;
    letter-spacing: normal;
}
.o2e-pinfo__main .o2e-pinfo__title,
.o2e-pinfo__section--bewertungen .o2e-pinfo__title {
    font-size: 22px;
}

/* Erzaehlspalte: Beschreibung fuellt die Grid-Spalte — der fruehere
   68ch-Cap riss eine ~250px-Luecke zur Fakten-Spalte, waehrend die
   Bewertungen volle Breite laufen. Lesbarkeits-Ausgleich: 16px wie der
   Review-Text (#reviews .review-content) + 1.75; die harten <br> je Satz
   im M1-Altbestand halten die realen Zeilen ohnehin meist kuerzer. */
.o2e-pinfo__section--beschreibung .value {
    line-height: 1.75;
    color: #2f2f2f;
    font-size: 16px;
}
.o2e-pinfo__zubereitung-text {
    max-width: 68ch;
    line-height: 1.75;
    color: #2f2f2f;
    font-size: 15px;
}

/* Fakten-Karten */
.o2e-pinfo__card {
    border: 1.5px solid color-mix(in srgb, var(--theme-color) 30%, #dadada);
    border-radius: 8px;
    padding: 20px 22px;
    background: #fff;
}
.o2e-pinfo__kv {
    margin: 0;
    display: grid;
    grid-template-columns: minmax(90px, auto) 1fr;
    gap: 10px 18px;
    font-size: 14px;
}
.o2e-pinfo__kv dt {
    font-weight: 600;
    color: #2f2f2f;
    margin: 0;
}
.o2e-pinfo__kv dd {
    margin: 0;
    color: #2f2f2f;
    overflow-wrap: anywhere;
}

/* Bio-Badge: gleiche AA-gesicherte Pill-Formel wie .o2e-zub__badge
   (65%-Mischung, gemessen ~5.0:1 auf der getoenten Flaeche). */
.o2e-bio-badge {
    display: inline-flex;
    align-items: center;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--theme-color) 65%, #1a1d20);
    background: color-mix(in srgb, var(--theme-color) 8%, #fff);
    border: 1px solid color-mix(in srgb, var(--theme-color) 30%, transparent);
    padding: 6px 11px;
    border-radius: 999px;
    white-space: nowrap;
}
/* Bio-Zertifizierung in "Auf einen Blick": EU-Logo + Kontrollstellencode +
   Landwirtschafts-Herkunft im selben Sichtfeld (Art. 32 Abs. 2/3 VO (EU)
   2018/848) — dieselbe Anordnung wie auf der Packung. Fehlt eine Pflicht-
   Begleitangabe, rendert das Template fail-closed die Text-Pill statt des
   Logos. Das Logo bleibt unveraendert (keine Radius-/Farb-Anpassung,
   Anhang V), 57x38px wahrt das 1,5:1-Seitenverhaeltnis deutlich ueber der
   Print-Mindestgroesse. */
.o2e-bio-cert {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 14px;
    padding-bottom: 14px;
    border-bottom: 1px solid #ececec;
}
.o2e-bio-cert:last-child {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: 0;
}
.o2e-bio-cert__logo {
    display: block;
    width: 57px;
    height: 38px;
    flex: none;
}
.o2e-bio-cert__meta {
    margin: 0;
    font-size: 13px;
    line-height: 1.45;
    color: #6b6b6b;
}
.o2e-bio-cert__code {
    display: block;
    font-weight: 600;
    color: #2f2f2f;
}

/* Pflichtangaben: ruhiger Fine-Print, sichtbar (LMIV) — gestapelt statt zweispaltig */
.o2e-pinfo__fineprint {
    font-size: 13px;
    line-height: 1.6;
    color: #6b6b6b;
    padding: 0 4px;
    scroll-margin-top: 90px; /* Sprungziel #o2e-produktinformationen (Meine Tees): nicht unter dem Sticky-Header */
}
.o2e-pinfo__fineprint .o2e-pinfo__title {
    font-size: 14px;
    color: #2f2f2f;
    margin-bottom: 10px;
}
.o2e-pinfo__kv--fineprint {
    grid-template-columns: 1fr;
    gap: 2px;
}
.o2e-pinfo__kv--fineprint dt {
    margin-top: 12px;
    color: #2f2f2f;
}
.o2e-pinfo__kv--fineprint dt:first-child {
    margin-top: 0;
}
.o2e-pinfo__kv--fineprint dd {
    color: #6b6b6b;
    /* Zutatenlisten: deutsche Silbentrennung statt harter Flatterkante
       (html[lang=de] gesetzt) */
    hyphens: auto;
}
.o2e-pinfo__fineprint a {
    /* rohes Markengruen faellt mit 3.44:1 auf Weiss durch AA;
       65%-Mischung ist das etablierte Muster dieser Datei. */
    color: color-mix(in srgb, var(--theme-color) 65%, #000);
    text-decoration: underline;
}

/* Naehrwerte: vorhandenes .rTable-DIV-HTML (M1-Altbestand) lesbar machen —
   Feinschliff aus Issue 03. border:0 vor border-bottom noetig: die
   globale .rTableCell-Regel weiter oben in dieser Datei setzt border:1px
   solid #333 auf allen vier Seiten; ohne den Reset blieben Top/Links/Rechts
   auf dem alten M1-Grau haengen, da die neue Regel nur border-bottom
   ueberschreibt. */
.o2e-pinfo__nw-bezug {
    margin: 0 0 10px;
    font-size: 13px;
    font-weight: 500;
    color: #2f2f2f;
}
.o2e-pinfo__naehrwerte {
    font-size: 13.5px;
    color: #2f2f2f;
}
.o2e-pinfo__naehrwerte .rTable {
    display: table;
    width: 100%;
    border-collapse: collapse;
}
.o2e-pinfo__naehrwerte .rTableBody {
    display: table-row-group;
}
.o2e-pinfo__naehrwerte .rTableRow {
    display: table-row;
}
.o2e-pinfo__naehrwerte .rTableCell {
    display: table-cell;
    padding: 5px 8px 5px 0;
    border: 0;
    border-bottom: 1px solid #ececec;
    font-variant-numeric: tabular-nums;
    /* kompakte Zeilen: 1.45 statt geerbtem 1.7 — Pflichtangabe, kein
       Lese-Fliesstext; die Zeilenhoehe waechst bei mehrzeiligen Labels
       von selbst (auto-height) */
    line-height: 1.45;
    /* 375px-Schutz gegen unteilbare lange Naehrstoffnamen (Muster wie
       .o2e-pinfo__kv dd); hyphens liefert saubere Trennstellen, bevor
       anywhere hart bricht */
    hyphens: auto;
    overflow-wrap: anywhere;
}
.o2e-pinfo__naehrwerte .rTableCell:last-child {
    text-align: right;
    /* Werte sind kurze Normformen ("16 kJ / 4 kcal") — Umbruch hier
       machte Zeilen grundlos zweizeilig */
    white-space: nowrap;
}
.o2e-pinfo__naehrwerte .rTableRow:last-child .rTableCell {
    border-bottom: 0;
}
.o2e-pinfo__naehrwerte .rTableCell--sub {
    padding-left: 16px;
    color: #6b6b6b;
}
.o2e-pinfo__naehrwerte p {
    margin: 8px 0;
    font-size: 12.5px;
    line-height: 1.55;
    color: #6b6b6b;
}
.o2e-pinfo__naehrwerte p:first-child {
    margin-top: 0;
}
.o2e-pinfo__naehrwerte p:last-child {
    margin-bottom: 0;
}
.o2e-pinfo__nw-fussnote {
    margin: 10px 0 0;
    font-size: 12.5px;
    line-height: 1.55;
    color: #6b6b6b;
}

/* Bewertungen behalten volle Hauptspaltenbreite (Formular), kein 68ch-Limit */

/* Mobil/Tablet: einspaltig — Fakten (inkl. Zubereitung) direkt nach der
   Beschreibung, Bewertungen ans Ende */
@media (max-width: 991.98px) {
    .o2e-pinfo {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "main"
            "facts"
            "reviews";
        grid-template-rows: none; /* Desktop-auto-1fr gilt nur im Zweispalter */
        row-gap: 32px;
    }
}


/* ========================================
   Zubereitungs-Karte (.o2e-zub) — Issue produktseite-info/02,
   statisch seit 2026-07 (Umschalter/Pills + JS entfernt: alle
   Ziehzeiten stehen jetzt gestaffelt in der Ziehzeit-Kachel, das
   Badge traegt die Aufguss-Anzahl). Icon-Kacheln (Loeffel/Uhr/
   Thermometer) aus den zub_*-Attributen (details.phtml).
   House-Tokens: Radius 8px, var(--theme-color) statt Hex-Gruen,
   Muted #6b6b6b, Headings #222529; Karten-Border wie die
   Fakten-Karten rechts (1.5px color-mix 30%). Kein !important
   noetig: alles neue o2e-Klassen ohne Porto-Konkurrenz.
   Kachel-Trennlinien = 1px-Grid-Gap auf Linienfarbe als Hintergrund;
   auto-fit statt repeat(3,1fr), damit bei fehlenden Kacheln
   (leere zub_*-Attribute) keine leere Farbspur entsteht.
   ======================================== */
.o2e-zub {
    border: 1.5px solid color-mix(in srgb, var(--theme-color) 30%, #dadada);
    border-radius: 8px;
    background: #fff;
    overflow: hidden;
    max-width: 560px;
}
/* Kopfzeile: Titel links, Mehrfachaufguss-Badge rechts — EINE Zeile
   (Feedback 2026-07: Titel und Badge standen zweizeilig versetzt).
   Auf schmalen Viewports darf das Badge kontrolliert umbrechen. */
.o2e-zub__headrow {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px 12px;
    margin-bottom: 2px;
}
.o2e-zub__headrow .o2e-pinfo__title {
    margin: 0;
}
.o2e-zub__teapot {
    color: var(--theme-color);
    line-height: 0;
}
/* Icon-Verkleinerung (Feedback 2026-07: Karte zu laut) — ueberstimmt
   die width/height-Attribute der Inline-SVGs aus details.phtml */
.o2e-zub__teapot svg {
    width: 30px;
    height: 30px;
}
.o2e-pinfo__title--zub {
    display: flex;
    align-items: center;
    gap: 10px;
}
.o2e-zub__badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    /* 65% statt der ueblichen 78%-Mischung: auf der gruen getoenten
       Badge-Flaeche faellt 78% auf 4.43:1 (unter AA bei 12px/600),
       65% liegt gemessen bei ~5.0:1. */
    color: color-mix(in srgb, var(--theme-color) 65%, #1a1d20);
    background: color-mix(in srgb, var(--theme-color) 8%, #fff);
    border: 1px solid color-mix(in srgb, var(--theme-color) 30%, transparent);
    padding: 6px 11px;
    border-radius: 999px;
    white-space: nowrap;
}
.o2e-zub__tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 1px;
    background: #e7e7e7;
    border-top: 1px solid #e7e7e7;
    margin-top: 16px;
}
.o2e-zub__tile {
    background: #fff;
    padding: 12px 12px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 5px;
}
.o2e-zub__ic {
    color: var(--theme-color);
    line-height: 0;
}
.o2e-zub__ic svg {
    width: 20px;
    height: 20px;
}
.o2e-zub__lbl {
    font-size: 12px;
    font-weight: 600;
    color: #6b6b6b;
}
.o2e-zub__val {
    font-size: 15px;
    font-weight: 700;
    color: #222529;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}
.o2e-zub__unit {
    display: block;
    font-size: 12px;
    font-weight: 600;
    color: #6b6b6b;
    margin-top: 2px;
}
/* Ziehzeit-Staffel: mehrere Aufguesse statisch untereinander in der
   Ziehzeit-Kachel (Wert prominent, Aufguss-Label als Unit darunter) */
.o2e-zub__zeiten {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* Hinweis (zub_hinweis verbatim, escaped; das ViewModel unterdrueckt
   Hinweise, die nur die Badge-Aussage wiederholen) */
.o2e-zub__note {
    padding: 0 20px 18px;
    margin: 14px 0 0;
    color: #6b6b6b;
    font-size: 13px;
    line-height: 1.5;
}
.o2e-zub__tiles + .o2e-zub__note {
    margin-top: 12px;
}

/* Dampf-Animation der Teekanne im Kartenkopf */
.o2e-zub__steam {
    animation: o2e-zub-rise 3s ease-in-out infinite;
    transform-origin: center;
}
.o2e-zub__steam--s2 { animation-delay: 1s; }
.o2e-zub__steam--s3 { animation-delay: 2s; }
@keyframes o2e-zub-rise {
    0% { opacity: 0; transform: translateY(2px) scaleY(.6); }
    40% { opacity: .7; }
    100% { opacity: 0; transform: translateY(-4px) scaleY(1.1); }
}

@media (prefers-reduced-motion: reduce) {
    .o2e-zub__steam { animation: none; opacity: .5; }
}

/* Schmale Viewports (<=560px): Kacheln stapeln, aber als kompakte
   Zeilen (Icon links, Label, Wert rechtsbuendig) statt zentrierter
   Grosskacheln — drei ~130px-Kacheln uebereinander machten die Karte
   sonst einen halben Handy-Viewport hoch. flex-wrap laesst lange
   Werte in eine eigene Zeile wachsen statt zu ueberlaufen. */
@media (max-width: 560px) {
    .o2e-zub__tiles {
        grid-template-columns: 1fr;
    }
    .o2e-zub__tile {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        text-align: left;
        padding: 12px 20px;
        gap: 6px 12px;
    }
    .o2e-zub__val {
        margin-left: auto;
        text-align: right;
    }
    .o2e-zub__unit {
        display: inline;
        margin: 0 0 0 4px;
    }
    /* Zeit-Staffel in der Zeilen-Kachel: rechtsbuendig wie die
       Einzelwerte der anderen Zeilen */
    .o2e-zub__zeiten {
        margin-left: auto;
        text-align: right;
        gap: 4px;
    }
    .o2e-zub__zeiten .o2e-zub__val {
        margin-left: 0;
    }
}

/* Zubereitung als Fakten-Karte (Redesign 2026-07): sitzt jetzt in der
   rechten Spalte unter "Auf einen Blick". Die Karte liefert das Chrome
   (Rahmen/Radius/Titel), die o2e-zub-Innereien laufen rahmenlos —
   Regeln stehen bewusst NACH dem .o2e-zub-Basisblock (gleiche
   Spezifitaet, spaetere Regel gewinnt). */
.o2e-pinfo__card--zub {
    padding: 20px 0 0;
    overflow: hidden; /* weisse Kachel-Ecken vs. 8px-Kartenradius */
}
.o2e-pinfo__card--zub .o2e-zub__headrow {
    padding: 0 22px;
}
.o2e-zub--flat {
    border: 0;
    border-radius: 0;
    max-width: none;
}

/* ============================================================
   Bewertungen: dezenter Leer-Zustand (Redesign 2026-07, ersetzt die
   Empty-State-Box aus Issue produktseite-info/05). Baymard/NN/g:
   leere Riesen-Sterne + Primary-CTA betonen genau die Abwesenheit
   von Social Proof — stattdessen eine ruhige Textzeile, der Link
   springt zum Disclosure-Formular (#review-form) und oeffnet es
   (web/js/o2e-review-disclosure.js).
   ============================================================ */
.o2e-reviews-none {
    margin: 0 0 6px;
    font-size: 14px;
    color: #6b6b6b;
}
.o2e-reviews-none a {
    /* 65%-Mischung = AA-Muster dieser Datei (rohes Markengruen 3.44:1) */
    color: color-mix(in srgb, var(--theme-color) 65%, #000);
    text-decoration: underline;
    text-underline-offset: 2px;
}
.o2e-reviews-none a:hover {
    color: color-mix(in srgb, var(--theme-color) 45%, #000);
}
.o2e-reviews-none a:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--theme-color) 65%, #000);
    outline-offset: 2px;
}

/* ============================================================
   Bewertungsformular als natives <details>-Disclosure
   (Magento_Review::form.phtml-Override): zugeklappt bis zum
   Bedarf (NN/g Progressive Disclosure), Summary = ruhiger
   Sekundaer-Trigger statt grossem Primary-Button.
   ============================================================ */
.o2e-review-add {
    margin-top: 10px;
}
.o2e-review-add__summary {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    min-height: 48px;
    padding: 0 20px;
    border: 1px solid #cdd6d2;
    border-radius: 8px;
    background: #fff;
    font-size: 14px;
    font-weight: 600;
    color: #2f2f2f;
    cursor: pointer;
    list-style: none;
    user-select: none;
    transition: border-color .2s, background .2s;
}
.o2e-review-add__summary::-webkit-details-marker {
    display: none;
}
.o2e-review-add__summary::marker {
    content: "";
}
.o2e-review-add__summary:hover {
    border-color: var(--theme-color);
    background: color-mix(in srgb, var(--theme-color) 4%, #fff);
}
.o2e-review-add__summary:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--theme-color) 65%, #000);
    outline-offset: 2px;
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--theme-color) 16%, transparent);
}
.o2e-review-add__chevron {
    color: color-mix(in srgb, var(--theme-color) 65%, #000);
    transition: transform .2s;
}
.o2e-review-add[open] .o2e-review-add__chevron {
    transform: rotate(180deg);
}
.o2e-review-add__content {
    padding-top: 24px;
}
@media (prefers-reduced-motion: reduce) {
    .o2e-review-add__summary,
    .o2e-review-add__chevron {
        transition: none;
    }
}

/* Bei 0 Bewertungen gibt es keine Liste ueber dem Formular — der kraeftige
   Listing<->Formular-Trenner (#reviews .block.review-add weiter oben,
   !important) wuerde die dezente Leer-Zeile erdruecken. Modifier kommt
   serverseitig aus details.phtml (getReviewsCount() === 0). */
#reviews.o2e-pinfo__section--no-reviews .block.review-add {
    margin-top: .5rem !important;
    padding-top: 0 !important;
    border-top: 0 !important;
}

/* Lieferzeit visuell von der LMIV-Kennzeichnung getrennt (gleicher
   ruhiger Fineprint-Block "Produktinformationen", Hairline dazwischen) */
.o2e-pinfo__kv--lieferung {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid #ececec;
}

/* --- letter-spacing-Vererbungs-Trap im Preisblock entschaerfen ---
   Porto (styles-m) setzt .product-info-price/.product-options-bottom auf
   -0.02em; das erbt als BERECHNETER px-Wert (-0.48px @24px) an den
   13px-Fine-Print (Steuerhinweis, Versandhinweis, Grundpreis) und wirkt
   dort wie -0.037em — Buchstaben kleben. Reset am Container; der
   32px-Preis behaelt sein eigenes -.02em (Regel bei "P0: Preis" oben). */
.product-info-main .product-info-price,
.product-info-main .product-options-bottom {
    letter-spacing: normal;
}

/* Beschreibungs-Content hat harte <br> je Satz (M1-Altbestand) — jede
   Satzzeile bricht sonst in lange Zeile + Ein-Wort-Orphan. pretty zieht
   mehr Woerter in die Fragmentzeile, der Flatterrand wird ruhiger. */
.o2e-pinfo__section--beschreibung .value {
    text-wrap: pretty;
}

/* ============================================================
   Herkunfts-Block (tee-herkunft Issue 01 — Basis-CSS;
   Steckbrief + Design-Polish: Issue 02)
   Karte = Inline-SVG-Build-Artefakt (tools/origin-maps): Regionen
   als path[data-region], Fill-/Marker-Klassen injiziert das ViewModel.
   ============================================================ */
.o2e-origin__map {
    flex: 1 1 300px;
    max-width: 480px;
}
.o2e-origin__map svg {
    display: block;
    width: 100%;
    height: auto;
    /* Hochformat-Laender (Vietnam H=1473, Thailand H=1299) wuerden sonst
       ~850-980px hoch rendern; viewBox-SVG letterboxt bei gekappter Hoehe
       zentriert statt zu verzerren. Sri Lanka (H=741.17) und Taiwan (H=716.52)
       sind seit Issue 07 (Rahmen-Weitung) annaehernd quadratisch und rendern
       bei max-width 480px nur noch ~490/478px hoch - der Cap greift dort
       praktisch nicht mehr. */
    max-height: 600px;
}
.o2e-origin__map path {
    fill: #eceae4;
    stroke: #fff;
    stroke-width: 1;
}
/* Nachbarland-Kontext (Issue 05): liegt unter dem Hauptland, deutlich
   heller ausgeblasst; ueberstimmt den Alle-Pfade-Selektor oben allein
   ueber hoehere Spezifitaet (Klasse .o2e-origin__context zusaetzlich). */
.o2e-origin__map .o2e-origin__context path {
    fill: #f5f4f0;
    stroke: #fff;
    stroke-width: 1;
}
.o2e-origin__map path.o2e-origin__fill {
    fill: color-mix(in srgb, var(--theme-color) 55%, #eceae4);
}
.o2e-origin__marker {
    fill: var(--theme-color);
    stroke: #fff;
    stroke-width: 2;
}
.o2e-origin__place {
    margin: 0 0 4px;
    color: #2f2f2f;
}
.o2e-origin__region {
    font-family: Georgia, 'Times New Roman', serif;
    font-size: 22px;
    line-height: 1.3;
    color: #222529;
}
.o2e-origin__country {
    color: #6b6b6b;
}
.o2e-origin__country::before {
    content: "\00b7\0020";
}

/* --- Issue 02: Zweispalter (Karte | Ortsname + Terroir-Steckbrief) --- */
.o2e-origin__body {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 20px 36px;
}
.o2e-origin__info {
    flex: 1 1 280px;
    min-width: 0;
}
/* Sonderfall ohne Steckbrief (z. B. nur-Umriss): einsame Ortszeile mittig
   neben der Karte statt oben in der Leere; ohne :has-Support greift schlicht
   die Top-Ausrichtung — nichts bricht. */
.o2e-origin__body:not(:has(.o2e-origin__facts)) .o2e-origin__info {
    align-self: center;
}

/* Terroir-Steckbrief: ruhige Zeilenliste, Muster wie o2e-zub (Label 12/600 muted, Wert 15 ink) */
.o2e-origin__facts {
    margin: 18px 0 0;
}
.o2e-origin__fact {
    padding: 12px 0;
    border-top: 1px solid #e7e7e7;
}
.o2e-origin__fact-lbl {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    font-weight: 600;
    color: #6b6b6b;
}
.o2e-origin__fact-ic {
    color: var(--theme-color, #179c80);
    line-height: 0;
    flex: none;
}
.o2e-origin__fact-ic svg {
    width: 18px;
    height: 18px;
    display: block;
}
.o2e-origin__fact-val {
    margin: 4px 0 0 26px;
    font-size: 15px;
    line-height: 1.6;
    color: #2f2f2f;
    max-width: 55ch;
}

/* Motion: Karten-Fade beim Laden + Marker-Puls — rein CSS, reduced-motion → statisch */
@keyframes o2e-origin-fade {
    from { opacity: 0; }
    to { opacity: 1; }
}
.o2e-origin__map svg {
    animation: o2e-origin-fade .7s ease-out both;
}
@keyframes o2e-origin-pulse {
    0%, 100% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.3); opacity: .75; }
}
.o2e-origin__marker {
    transform-box: fill-box;
    transform-origin: center;
    animation: o2e-origin-pulse 2.6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
    .o2e-origin__map svg,
    .o2e-origin__marker {
        animation: none;
    }
}



/* ==============================================
   Add-to-Cart-Feedback als Toast (Critique 2026-07-19, P0)
   Magento rendert die Erfolgs-/Fehlermeldung nach dem (AJAX-)Add-to-Cart
   in .page.messages GANZ OBEN im Dokument - wer am CTA steht, hat sie
   gemessen bei top:-193px: der kaufkritischste Moment blieb stumm
   (Doppelklick-/Abbruchrisiko). Fix ohne JS: die Meldung wird auf den
   Katalogseiten als fixierter Toast am oberen Viewport-Rand gezeigt und
   blendet nach ~6s selbst aus (animation-fill-mode forwards haelt den
   Endzustand; visibility im Keyframe nimmt sie auch aus der Hit-Area).
   Scope bewusst NUR Katalog (.catalog-product-view/-category-view/
   Suche): im Checkout/Konto haben Meldungen ihre etablierten Plaetze
   im Flow. z-index 1000: unter dem Off-Canvas-Menue (1001,
   mobile-menu.css), ueber Sticky-Header/Content.
   FALLE: .page.messages selbst ist IMMER im DOM (leer) - fixiert wird
   nur die konkrete .message, sonst laege ein unsichtbarer Layer ueber
   dem Header.
   ============================================== */
.catalog-product-view .page.messages .message,
.catalog-category-view .page.messages .message,
.catalogsearch-result-index .page.messages .message {
    position: fixed;
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
    width: min(92vw, 520px);
    z-index: 1000;
    margin: 0;
    border-radius: 8px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, .18);
    animation: o2e-toast 6s cubic-bezier(.16, 1, .3, 1) forwards;
}
@keyframes o2e-toast {
    0%   { opacity: 0; transform: translateX(-50%) translateY(-8px); }
    6%   { opacity: 1; transform: translateX(-50%) translateY(0); }
    88%  { opacity: 1; visibility: visible; }
    100% { opacity: 0; visibility: hidden; }
}
@media (prefers-reduced-motion: reduce) {
    .catalog-product-view .page.messages .message,
    .catalog-category-view .page.messages .message,
    .catalogsearch-result-index .page.messages .message {
        /* kein Slide - nur zeitgesteuertes Aus-/Einblenden ohne Bewegung */
        animation: o2e-toast-static 6s step-end forwards;
    }
    @keyframes o2e-toast-static {
        0%   { opacity: 1; visibility: visible; }
        100% { opacity: 0; visibility: hidden; }
    }
}


/* ============================================================
   PRODUKTSEITE - Ruecksprung-Link ("← Zurueck zum Merkzettel")
   Versteckter Platzhalter (ruecksprung.phtml), js/o2e-ruecksprung blendet ihn ein. Kleiner Sand-Knopf;
   steht in .actions unter Knopf/Herz (volle Zeile), unter dem Herz (nicht lieferbar) und am Ende von
   "Produktinformationen".
   [hidden]: Porto setzt display fuer p global mit !important -> hier absichern.
   ============================================================ */
.o2e-ruecksprung {
    margin: 12px 0 0 !important;
    width: 100%;
}
.o2e-ruecksprung[hidden] {
    display: none !important;
}
/* Kleiner Knopf in warmem Sand statt Markengruen: hebt sich als "nur jetzt da" vom gruenen
   Warenkorb-Knopf ab, ohne mit ihm zu konkurrieren (Inhaber 2026-11-01). Ink auf Sand ~12:1. */
.o2e-ruecksprung a.o2e-ruecksprung__link {
    background: #f5efe4 !important;
    border: 1px solid #ddd0b9 !important;
    border-radius: 8px;
    color: #2f2f2f !important;
    display: inline-block;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.5;
    padding: 7px 14px;
    text-decoration: none !important;
    transition: background-color .15s ease, border-color .15s ease;
}
.o2e-ruecksprung a.o2e-ruecksprung__link:hover,
.o2e-ruecksprung a.o2e-ruecksprung__link:focus-visible {
    background: #ebe1cf !important;
    border-color: #cbb995 !important;
    color: #1a1d20 !important;
    text-decoration: none !important;
}
.o2e-ruecksprung a.o2e-ruecksprung__link:focus-visible {
    box-shadow: 0 0 0 4px rgba(203, 185, 149, .35);
    outline: 0;
}
@media (prefers-reduced-motion: reduce) {
    .o2e-ruecksprung a.o2e-ruecksprung__link {
        transition: none;
    }
}
@media (max-width: 991px) {
    /* unter dem Warenkorb-Knopf mittig, als Touch-Ziel >= 44px */
    .o2e-ruecksprung {
        text-align: center;
    }
    .o2e-ruecksprung a.o2e-ruecksprung__link {
        min-height: 44px;
        padding: 10px 18px;
    }
    /* Zweiter Platz am Ende von "Produktinformationen": buendig mit den Angaben statt zentriert */
    .o2e-pinfo__fineprint .o2e-ruecksprung {
        text-align: left;
    }
}
