/*
Theme Name:  Knöll & Vogel — Divi Child
Theme URI:   https://knoellundvogel.de
Description: Divi 5 child theme for Weingut Knöll & Vogel. Fonts, bird-track motif, GSAP layer, schwarm canvas. All layout/styling lives in Divi global variables + presets; this file only covers what Divi decoration attrs cannot express (pseudo-elements, SVG strokes, blend modes, header scroll behavior).
Template:    Divi
Version:     1.0.0
Author:      Knöll & Vogel
*/

/* ---------- bird-footpath motif (kv_tracks) ----------
   JS scatters .footprint groups along a hidden guide path. */
.kv-tracks { position: absolute; inset: 0; pointer-events: none; overflow: hidden; z-index: 0; }
.kv-tracks svg { width: 100%; height: 100%; overflow: visible; }
.kv-tracks .footprint { fill: none; stroke: var(--gcid-kv-gold, #b9a170); stroke-width: 1.4; stroke-linecap: round; opacity: .85; }
.kv-tracks--navy .footprint { stroke: var(--gcid-kv-gold-bright, #cbb585); opacity: .55; }
/* sections that host a track need stacking context so content sits above */
.kv-has-tracks { position: relative; }
.kv-has-tracks > :not(.kv-tracks) { position: relative; z-index: 1; }

/* bird watermark */
.kv-bird-watermark { position: absolute; pointer-events: none; opacity: .05; z-index: 0; }
.kv-bird-watermark.on-navy { opacity: .07; fill: var(--gcid-kv-gold-bright, #cbb585); }

/* ---------- bottle photo trick ----------
   White packshot background melts into parchment. Parent must carry
   the parchment background for the blend to work. */
.kv-bottle-blend img { mix-blend-mode: multiply; filter: brightness(1.12); }

/* ---------- reveal on scroll (fallback-safe) ---------- */
.kv-reveal { opacity: 1; transform: none; }
html.kv-js .kv-reveal { opacity: 0; transform: translateY(26px); transition: opacity .9s cubic-bezier(.22,.61,.36,1), transform .9s cubic-bezier(.22,.61,.36,1); }
html.kv-js .kv-reveal.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  html.kv-js .kv-reveal { opacity: 1; transform: none; transition: none; }
}

/* ---------- header: logo scrolls away, nav bar sticks / returns on scroll-up ---------- */
.kv-nav-bar { position: sticky; top: 0; z-index: 60; transition: transform .4s cubic-bezier(.22,.61,.36,1); }
html.kv-js .kv-nav-bar.kv-nav-hidden { transform: translateY(-110%); }
.kv-nav-bar .kv-nav-link { position: relative; }
.kv-nav-bar .kv-nav-link a::after {
  content: ''; position: absolute; left: 0; right: 100%; bottom: -4px; height: 1.5px;
  background: var(--gcid-kv-gold, #b9a170); transition: right .35s cubic-bezier(.22,.61,.36,1);
}
.kv-nav-bar .kv-nav-link a:hover::after { right: 0; }

/* ---------- schwarm canvas host ---------- */
.kv-schwarm-host { position: relative; overflow: hidden; }
.kv-schwarm-host canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.kv-schwarm-vig { position: absolute; inset: 0; pointer-events: none; z-index: 1; background: radial-gradient(120% 100% at 50% 50%, transparent 45%, rgba(10,15,22,.66) 100%); }

/* ---------- schwarm word-formation dock ---------- */
.kv-schwarm-dock {
  position: absolute; left: 50%; bottom: 26px; transform: translateX(-50%); z-index: 3;
  display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  background: rgba(20, 28, 40, .55); border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 60px; backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 20px 50px -20px rgba(0, 0, 0, .6);
}
.kv-schwarm-btn {
  display: inline-flex; align-items: center; gap: 9px;
  border: 1px solid rgba(255, 255, 255, .16); background: rgba(255, 255, 255, .05); color: #fff;
  font-family: inherit; font-size: 12px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  padding: 11px 18px; border-radius: 40px; cursor: pointer; white-space: nowrap;
  transition: background .25s ease, border-color .25s ease, transform .25s ease;
}
.kv-schwarm-btn:hover { background: rgba(255, 255, 255, .14); border-color: rgba(255, 255, 255, .3); transform: translateY(-1px); }
.kv-schwarm-btn svg { width: 15px; height: 15px; }
.kv-schwarm-btn--primary {
  background: var(--gcid-kv-gold, #b9a170); border-color: var(--gcid-kv-gold, #b9a170);
  color: var(--gcid-kv-navy, #223246);
}
.kv-schwarm-btn--primary:hover { background: #f0e4c2; border-color: #f0e4c2; }
.kv-schwarm-word {
  font-family: "Cormorant Garamond", Georgia, serif; font-variant: small-caps;
  font-size: 16px; letter-spacing: .06em; min-width: 92px; text-align: center;
  color: #cbb585;
}
@media (max-width: 720px) {
  .kv-schwarm-dock { gap: 7px; padding: 8px 10px; bottom: 16px; max-width: calc(100% - 24px); }
  .kv-schwarm-btn { padding: 9px 13px; font-size: 11px; }
  .kv-schwarm-word { min-width: 64px; font-size: 14px; }
}

/* ---------- GSAP: avoid FOUC on split headlines ---------- */
html.kv-js .kv-headline-anim .et_pb_heading_container { will-change: transform; }

/* ============================================================
   == B: product ==  single-product Theme Builder body (19675)
   Layout/colour/spacing live in the Divi block attrs (see
   kv-build/gen-single-product.py). Only what a Divi decoration
   attr cannot express is here: font-variant, pseudo-elements,
   blend modes, the category pill, the qty box, fact rows.
   ============================================================ */

/* ---------- readable quiet text (WCAG 1.4.3 AA) ----------
   The quietest text on a product page is the text the law requires to be
   readable: the Grundpreis (€/Liter, PAngV §4), "inkl. 19 % MwSt., zzgl.
   Versandkosten" (PAngV §3), Lieferzeit, and the Inhalt/Alkohol/Allergene
   line (LMIV / EU 2021/2117). All of it inherits --gcid-kv-muted, and
   #7c7e82 on the offwhite hero is 3.89:1 at 12.7-14.4px — below the 4.5:1
   AA floor. Same story for the loop cards in the related row (4.07:1 on
   white) and for gold-deep eyebrows/labels on parchment (3.21:1).

   Fixed by REDEFINING the two custom properties for this template's sections
   instead of rewriting a dozen module colours: every var(--gcid-kv-muted) /
   var(--gcid-kv-gold-deep) reference below — Divi module attrs, Woo markup,
   the loop-card partial — resolves against these. The global palette itself
   is piece A's, so it is left untouched and this survives a re-seed.
     #6b6e73 on #fafaf8 = 4.90:1, on #ffffff = 5.12:1
     #7d6a45 on #f5f2ea = 4.67:1, on #fafaf8 = 5.00:1
   Scoped away from .kv-facts on purpose: on navy a darker grey would go the
   wrong way, and that section already uses white/alpha-white throughout. */
.kv-pd, .kv-pd-related { --gcid-kv-muted: #6b6e73; }
.kv-pd-related, .kv-pd .kv-pd-trust, .kv-pd .kv-plate { --gcid-kv-gold-deep: #7d6a45; }

/* small-caps has no Divi font field */
.kv-smallcaps h1, .kv-smallcaps h2, .kv-smallcaps h3,
.kv-fh h3 { font-variant: small-caps; }

/* ---------- top section ---------- */
.kv-pd-info { max-width: 540px; }

/* Divi columns add a 30px flex row-gap between modules; the vertical rhythm of
   this template is set per module in the block attrs, so switch it off here. */
.kv-pd-info, .kv-facts-cols .et_pb_column { row-gap: 0; }

/* Woo category meta → the design's badge pill (drop the "Kategorie:" prefix
   and Woo's own separator rule above it) */
.kv-pd-badge .product_meta { margin: 0 !important; font-size: 0; border: 0 !important; padding: 0 !important; }
.kv-pd-badge .product_meta > span { font-size: 0; }
.kv-pd-badge .posted_in a {
  display: inline-block; font-size: 16px; font-variant: small-caps; line-height: 1.35;
  background: var(--gcid-kv-parchment, #f3efe4);
  border: 1px solid var(--gcid-kv-line, #e4ded1);
  border-radius: var(--gvid-kv-radius, 3px);
  padding: 4px 16px; margin: 0 6px 6px 0;
  transition: border-color .3s ease, color .3s ease;
}
.kv-pd-badge .posted_in a:hover { border-color: var(--gcid-kv-gold, #b9a170); color: var(--gcid-kv-gold-deep, #8a7031); }

/* price + Grundpreis */
.kv-pd-price .price { margin: 0; padding: 0; }
.kv-pd-price .price del { opacity: .55; margin-right: 8px; }
.kv-pd-price .price ins { text-decoration: none; }
.kv-pd-price .woocommerce-price-suffix,
.kv-pd-price .wc-gzd-additional-info,
.kv-pd-price .price-unit { display: none; }
.kv-pd-liter .kv-grundpreis-line,
.kv-pd-liter .kv-grundpreis-line * { font-size: inherit; color: inherit; font-weight: 400; }

/* qty box + add-to-cart row (skin of the button itself: piece A) */
.kv-pd-buy .cart { display: flex; gap: 12px; align-items: stretch; flex-wrap: wrap; margin: 0; }
.kv-pd-buy .quantity {
  display: flex; align-items: center; margin: 0;
  border: 1px solid var(--gcid-kv-navy, #223246); border-radius: var(--gvid-kv-radius, 3px);
}
.kv-pd-buy .quantity input.qty {
  width: 58px; min-height: 50px; text-align: center; border: none; background: none;
  font-family: var(--gvid-kv-font-sans, sans-serif); font-size: 16px;
  color: var(--gcid-kv-navy, #223246);
}
.kv-pd-buy .single_add_to_cart_button { flex: 1 1 200px; min-height: 50px; }
.kv-pd-buy .wc-gzd-additional-info, .kv-pd-buy .woocommerce-variation-price { margin-top: 10px; }

/* products without a description (gift packages) must not leave the
   description module's top rule floating above the key-data list */
.kv-pd-desc:not(:has(p)) { display: none !important; }

/* compact key-data + legal list */
.kv-pd-kurzdaten .kv-pd-meta { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.kv-pd-kurzdaten .kv-pd-meta li { margin: 0; padding: 0; }
.kv-pd-kurzdaten .kv-pd-meta b { color: var(--gcid-kv-ink, #2a2a26); font-weight: 600; }
.kv-pd-kurzdaten .kv-pd-legal { font-size: .92em; }
.kv-pd-kurzdaten .kv-pd-legal a { color: inherit; text-decoration: underline; }

/* trust row */
.kv-pd-trust { list-style: none; }
.kv-pd-trust .et_pb_icon_list_item { align-items: center; }

/* bottle stage: the white packshot multiplies onto the parchment column.
   The track wrapper's sibling rule gives every module z-index:1, which opens a
   stacking context and ISOLATES the blend (white box, no melt) — so this column
   opts out of it and lets the bottle blend against the column background and
   the footprints painted underneath. */
.kv-pd-stage.kv-has-tracks > :not(.kv-tracks) { z-index: auto; }
.kv-pd-stage .woocommerce-product-gallery,
.kv-pd-stage .woocommerce-product-gallery__wrapper,
.kv-pd-stage .woocommerce-product-gallery__image,
.kv-pd-stage .et_pb_module_inner { background: transparent; }

/* --- how tall the bottle stands ---------------------------------------
   In design/single-product.jpg the bottle owns ~80% of the hero's height.
   WooCommerce hands Divi a 500px-wide `woocommerce_single` image which, left
   alone, renders at its intrinsic 500x500 inside a 942px section — half the
   height the design asks for, and visibly soft on a retina screen.
   The box height below is the one value the whole hero scales from;
   inc/product-image.php widens `sizes` so the browser fetches a candidate
   that matches it.
   The box is never WIDER than it is tall: `cover` crops whichever axis
   overflows, so a wide-and-short box would slice the cap and the punt off a
   square packshot once the row collapses to one column. */
.kv-pd { --kv-shot-h: clamp(440px, 54vw, 780px); }
body.kv-shot-wide .kv-pd { --kv-shot-h: clamp(300px, 34vw, 520px); }

/* four classes deep on purpose: WooCommerce ships
   `.woocommerce div.product div.images img { height:auto }` at (0,3,3), which
   outranks any two-class selector and flattens the stage back to a square. */
.kv-pd .kv-pd-stage .woocommerce-product-gallery .woocommerce-product-gallery__image img {
  mix-blend-mode: multiply;
  display: block;
  width: min(100%, var(--kv-shot-h));
  height: var(--kv-shot-h);
  max-width: none;
  margin-inline: auto;
  /* square packshots (the 52 wine bottles) already fill their frame top to
     bottom — only `cover` lets one fill a portrait stage, and the margin it
     trims is white space that the multiply blend had erased anyway. */
  object-fit: cover;
  object-position: center;
}
/* a genuinely portrait or landscape shot must keep all of itself */
body.kv-shot-tall .kv-pd .kv-pd-stage .woocommerce-product-gallery .woocommerce-product-gallery__image img,
body.kv-shot-wide .kv-pd .kv-pd-stage .woocommerce-product-gallery .woocommerce-product-gallery__image img { object-fit: contain; }
/* the landscape shots are cellar photographs, not cut-out packshots: multiply
   has no white to erase there, it just muddies the picture */
body.kv-shot-wide .kv-pd .kv-pd-stage .woocommerce-product-gallery .woocommerce-product-gallery__image img { mix-blend-mode: normal; }

/* the trail may never walk over the glass: the packshot owns the centre of
   the stage, so the track layer is masked to the side margins — prints fade
   out approaching the bottle and re-emerge on the far side, reading as the
   bird passing behind it (the design keeps trails strictly off the bottle) */
.kv-pd .kv-pd-stage > .kv-tracks {
  -webkit-mask-image: linear-gradient(to right, #000 0 14%, transparent 28% 74%, #000 88% 100%);
          mask-image: linear-gradient(to right, #000 0 14%, transparent 28% 74%, #000 88% 100%);
}

.kv-pd-stage .flex-control-thumbs { margin-top: 14px; }
.kv-pd-stage .flex-control-thumbs img { mix-blend-mode: multiply; }
.kv-pd-stage .onsale {
  background: #fff; color: var(--gcid-kv-navy, #223246);
  border: 1px solid var(--gcid-kv-line, #e4ded1); border-radius: var(--gvid-kv-radius, 3px);
  min-height: 0; min-width: 0; padding: 5px 14px; line-height: 1; text-transform: none;
}

/* --- products whose only "packshot" is the legacy blank keinbild.jpg -------
   Eight of them. Hiding the stage column collapsed the hero to one centred
   track and left the text block indented past its own breadcrumb; showing the
   blank painted a white rectangle across half the hero. Both read as a page
   that failed to load. So the stage keeps its half of the grid and holds a
   plate instead — same height as a bottle, brand swift, stated intent.
   Markup: kv_shot_plate_html() in inc/product-image.php. */
.kv-shot-plate { display: block; }
/* the gallery's inline opacity:0 is cleared by wc's single-product.js, which
   aborts early here (no .woocommerce-product-gallery__image to slide) — this
   is the belt to that braces, for when the script is deferred or blocked */
.kv-pd-stage .woocommerce-product-gallery:has(.kv-shot-plate) { opacity: 1 !important; }
/* the plate stands shorter than a bottle on purpose: at the full --kv-shot-h
   it towered over the four lines of copy these products have and reopened the
   void from the other side */
.kv-plate {
  position: relative;
  margin: 0;
  min-height: clamp(340px, 38vw, 560px);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(18px, 2.4vw, 30px);
  padding: clamp(28px, 4vw, 52px);
  background: var(--gcid-kv-parchment, #f3efe4);
  border: 1px solid var(--gcid-kv-line, #e4ded1);
  border-radius: var(--gvid-kv-radius, 3px);
}
/* inset gold hairline — the bookplate frame that turns "picture missing" into
   a printed card the cellar meant to put there */
.kv-plate::before {
  content: ""; position: absolute; inset: 13px; pointer-events: none;
  border: 1px solid var(--gcid-kv-gold, #b9a170); opacity: .3; border-radius: 2px;
}
/* four classes deep: WooCommerce ships `.woocommerce div.product div.images
   img { width:100% }` at (0,3,3) and the plate sits inside that `div.images`
   gallery wrapper, so three classes lose and the swift fills the card */
.kv-pd .kv-pd-stage .kv-shot-plate .kv-plate__bird {
  display: block; width: min(55%, 172px); height: auto; max-width: none;
  opacity: .2;
}
/* the plate is opaque, so the stage's footprint trail would run behind it and
   surface as two disconnected scraps of track. The plate carries its own bird. */
body.kv-no-shot .kv-pd-stage > .kv-tracks { display: none !important; }
/* tall/wide shots are edge-to-edge PHOTOGRAPHS (paket scenes, cellar shots), not
   white-padded packshots: prints rendered onto a photo read as dirt, and the
   stage-percentage mask can't know where the photo ends — so no trail at all.
   Only the square (sq) white packshots carry the trail. */
body.kv-shot-tall .kv-pd-stage > .kv-tracks,
body.kv-shot-wide .kv-pd-stage > .kv-tracks { display: none !important; }
/* tall photos outgrow the info column: centring then floats the badge ~145px below
   the photo's top edge — start both columns at the same height like the design */
body.kv-shot-tall #et-boc .et-l .kv-pd-grid.et_grid_row { align-items: start !important; }
.kv-plate__cap { display: flex; flex-direction: column; gap: 8px; text-align: center; }
.kv-plate__brand {
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", Georgia, serif);
  font-variant: small-caps; font-size: clamp(19px, 2vw, 24px); line-height: 1.2;
  letter-spacing: .04em; color: var(--gcid-kv-gold-deep, #8a7031);
}
.kv-plate__note {
  font-family: var(--gvid-kv-font-sans, sans-serif);
  font-size: 12px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--gcid-kv-muted, #6b6e73);
}

/* ---------- FACTS (navy) ---------- */
.kv-facts { position: relative; }
.kv-frow {
  display: flex; justify-content: space-between; gap: 20px; padding: 7px 0;
  border-bottom: 1px dotted rgba(255, 255, 255, .16);
}
.kv-frow > span:first-child { color: rgba(255, 255, 255, .66); white-space: nowrap; }
.kv-frow > span:last-child { color: #fff; text-align: right; }
.kv-ftable--prose p { color: rgba(255, 255, 255, .82); margin: 0 0 .6em; }
.kv-fnote { margin: 14px 0 0; font-size: .88em; color: rgba(255, 255, 255, .62); line-height: 1.55; }

/* the bottles inside a Probier-/Genuss-/Geschenkpaket. The shop stores them
   only as prose in the short description; inc/food-shortcodes.php parses that
   into this list, which is what fills the navy band on the ~17 package pages
   that used to render it empty. */
.kv-plist-lead {
  margin: 0 0 10px; font-size: var(--gvid-kv-text-xs, 12px); font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase; color: var(--gcid-kv-gold-bright, #cbb585);
}
.kv-plist { list-style: none; margin: 0; padding: 0; }
.kv-plist li {
  display: grid; grid-template-columns: 56px minmax(0, 1fr); column-gap: 16px;
  padding: 10px 0; border-bottom: 1px dotted rgba(255, 255, 255, .16);
}
.kv-plist-nr {
  grid-row: 1 / span 2; align-self: start; white-space: nowrap;
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif);
  font-size: 17px; line-height: 1.5; color: var(--gcid-kv-gold-bright, #cbb585);
}
.kv-plist-name {
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif);
  font-size: var(--gvid-kv-text-md, 19px); line-height: 1.3; color: #fff; text-wrap: balance;
}
.kv-plist-meta { font-size: .9em; line-height: 1.45; color: rgba(255, 255, 255, .62); margin-top: 2px; }

/* a fact block whose shortcode found no data (packages have no wine attributes,
   alcohol-free wines no calculable energy value) must not leave an orphan
   heading behind — hide the empty body and the heading in front of it */
.kv-empty { display: none; }
.kv-facts-cols .et_pb_text:has(.kv-empty) { display: none !important; }
.kv-facts-cols .et_pb_heading:has(+ .et_pb_text .kv-empty) { display: none !important; }
.kv-facts-cols .et_pb_wc_additional_info:not(:has(table tr)) { display: none !important; }
.kv-facts-cols .et_pb_heading:has(+ .et_pb_wc_additional_info:not(:has(table tr))) { display: none !important; }

/* ---- how much the navy band actually has to say ----
   One Theme-Builder layout serves 89 products of four kinds. Hiding the empty
   modules was not enough: the two-column grid and the section's own padding
   stayed, so a paper bag got an ~800px navy void with a bird in it. The body
   class comes from kv_facts_state() (inc/food-shortcodes.php) and is computed
   from DATA ROWS, before render.
     full         two populated columns — the design's layout, untouched
     left/right   one populated column  — collapse the grid, centre what is left
     bare         nothing to say        — drop the FACTS head and the grid
                                          entirely, keep the signature band */
body.kv-facts-left .kv-facts-cols,
body.kv-facts-right .kv-facts-cols { grid-template-columns: minmax(0, 1fr) !important; }
/* the row's own max-width is set by Divi behind an #et-boc selector this file
   cannot outrank — narrow the surviving COLUMN instead */
body.kv-facts-left .kv-facts-cols > .et_pb_column:first-child,
body.kv-facts-right .kv-facts-cols > .et_pb_column:last-child {
  max-width: 660px; width: 100%; justify-self: center;
}
body.kv-facts-left .kv-facts-cols > .et_pb_column:last-child,
body.kv-facts-right .kv-facts-cols > .et_pb_column:first-child { display: none !important; }
/* one column of rows does not need the full-bleed section rhythm around it */
body.kv-facts-left .kv-facts,
body.kv-facts-right .kv-facts {
  padding-top: var(--gvid-kv-space-xl, 64px) !important;
  padding-bottom: var(--gvid-kv-space-xl, 64px) !important;
}
/* `bare` means the shortcodes found NOTHING: no attribute worth printing, no
   Zutaten, no Nährwerte — true for the two spirits and the five packaging
   items, whose every wine attribute is literally "nicht definiert". Keeping
   the band and hiding only its rows left a 224px navy strip carrying one
   75px name rule: a section that exists to announce it has nothing to say.
   The signature line has nothing to sign, so the whole section goes and the
   hero hands straight over to "Aus demselben Keller". */
body.kv-facts-bare .kv-facts { display: none !important; }
/* the subtitle names what follows; on a product with no facts it names nothing */
body.kv-kind-plain .kv-facts-sub { display: none !important; }
/* on a package the bottle list IS the story — it leads, the attributes follow */
body.kv-kind-paket .kv-facts-cols > .et_pb_column:last-child { order: -1; }

/* native Woo attribute table, dressed as the design's fact rows */
.kv-fattrs table.shop_attributes { width: 100%; border: none; margin: 0; }
.kv-fattrs table.shop_attributes tr { background: none !important; border: none; }
.kv-fattrs table.shop_attributes th,
.kv-fattrs table.shop_attributes td {
  border: none; border-bottom: 1px dotted rgba(255, 255, 255, .16);
  font-style: normal; font-weight: 400; background: none;
}
.kv-fattrs table.shop_attributes th { text-align: left; color: rgba(255, 255, 255, .66) !important; white-space: nowrap; }
.kv-fattrs table.shop_attributes td { text-align: right; color: #fff !important; }
.kv-fattrs table.shop_attributes td p { margin: 0; }

/* rows that the page already shows elsewhere, plus internal/technical ones.
   Selector is row-level and :is()-based so it still wins under WooCommerce's
   smallscreen sheet (see the phone override below, which re-declares display
   on every tr with !important). */
.kv-fattrs table.shop_attributes tr:is(
  .woocommerce-product-attributes-item--weight,
  .woocommerce-product-attributes-item--attribute_pa_award1,
  .woocommerce-product-attributes-item--attribute_pa_awards-desc,
  .woocommerce-product-attributes-item--attribute_pa_fact-sheet,
  .woocommerce-product-attributes-item--attribute_pa_expertise,
  .woocommerce-product-attributes-item--attribute_pa_weinnr,
  .woocommerce-product-attributes-item--attribute_pa_ap-nr,
  .woocommerce-product-attributes-item--attribute_pa_liter,
  .woocommerce-product-attributes-item--attribute_pa_allergene,
  .woocommerce-product-attributes-item--attribute_pa_temperature,
  .woocommerce-product-attributes-item--attribute_pa_empfehlung,
  .woocommerce-product-attributes-item--attribute_pa_geschmacksrichtung,
  .woocommerce-product-attributes-item--attribute_pa_qualitaetsstufe,
  .woocommerce-product-attributes-item--attribute_pa_besonderheiten,
  .woocommerce-product-attributes-item--attribute_pa_auslobung
) { display: none !important; }

/* WooCommerce's smallscreen sheet re-blocks every table row (display:block
   !important) below 768px, which stacks label over value. Keep the design's
   two-column fact rows on phones. */
@media (max-width: 768px) {
  .kv-fattrs table.shop_attributes tr {
    display: flex !important; justify-content: space-between; gap: 18px;
    border-bottom: 1px dotted rgba(255, 255, 255, .16);
  }
  .kv-fattrs table.shop_attributes th,
  .kv-fattrs table.shop_attributes td {
    display: block !important; width: auto; padding: 7px 0; border-bottom: 0;
  }
  .kv-fattrs table.shop_attributes th { flex: 0 0 auto !important; width: auto !important; text-align: left !important; }
  .kv-fattrs table.shop_attributes td { flex: 1 1 auto !important; width: auto !important; text-align: right !important; }
  .kv-frow { gap: 14px; }
  .kv-plist li { grid-template-columns: 46px minmax(0, 1fr); column-gap: 12px; }
  /* on one-column layouts the track band has nowhere to run without crossing
     the fact rows — the motif stays in the hero stage instead */
  .kv-facts > .kv-tracks { display: none; }
}

/* Below the two-column breakpoint the fact rows run the full width, so the
   watermark has no margin left to sit in and starts crossing the data.
   Same specificity trick as the bare-band rule above (Divi owns the attr). */
@media (max-width: 980px) {
  body #et-boc .kv-facts.kv-facts.kv-facts.kv-facts { background-image: none !important; }
}

/* ---------- related ---------- */
.kv-pd-related section.related > h2 { display: none; }

/* The band is topped up to four cards server-side (inc/related-products.php),
   so `columns-4` is honest in practice. These are the belt-and-braces rules for
   the edge case where the whole shop can't supply four visible products: the
   grid then tracks the real card count instead of leaving empty cells, and a
   band with nothing in it removes itself rather than reserving blank parchment.
   `.woocommerce` is a BODY class here, not a wrapper inside the section, so
   these selectors must not descend through it; the section's own display comes
   from Divi's ID-scoped `#et-boc .et_pb_section`, hence the !important. */
.kv-pd-related ul.products.columns-4:not(:has(li.product:nth-child(4))) {
  grid-template-columns: repeat(auto-fit, minmax(260px, 320px));
  justify-content: start;
}
.kv-pd-related:not(:has(li.product)) { display: none !important; }

@media (max-width: 980px) {
  .kv-pd-info { max-width: none; }
  .kv-pd-stage { min-height: 340px; }
}

/* ============================================================
   PRODUCT CARDS — global (archive, homepage featured, related)
   Markup enriched by inc/woo-loop-card.php. One look everywhere.
   ============================================================ */
.woocommerce ul.products { margin: 0 !important; padding: 0; list-style: none; display: grid; gap: 22px; }
/* columns class on the .woocommerce WRAPPER (Divi archive layout) */
.woocommerce.columns-1 ul.products { grid-template-columns: 1fr; }
.woocommerce.columns-2 ul.products { grid-template-columns: repeat(2, 1fr); }
.woocommerce.columns-3 ul.products { grid-template-columns: repeat(3, 1fr); }
.woocommerce.columns-4 ul.products { grid-template-columns: repeat(4, 1fr); }
.woocommerce.columns-5 ul.products { grid-template-columns: repeat(5, 1fr); }
.woocommerce.columns-6 ul.products { grid-template-columns: repeat(6, 1fr); }
/* columns class on the UL itself (Divi 5 shop / related-products modules) */
.woocommerce ul.products.columns-1 { grid-template-columns: 1fr; }
.woocommerce ul.products.columns-2 { grid-template-columns: repeat(2, 1fr); }
.woocommerce ul.products.columns-3 { grid-template-columns: repeat(3, 1fr); }
.woocommerce ul.products.columns-4 { grid-template-columns: repeat(4, 1fr); }
.woocommerce ul.products.columns-5 { grid-template-columns: repeat(5, 1fr); }
.woocommerce ul.products.columns-6 { grid-template-columns: repeat(6, 1fr); }
@media (max-width: 1024px) {
  .woocommerce.columns-3 ul.products,
  .woocommerce.columns-4 ul.products,
  .woocommerce.columns-5 ul.products,
  .woocommerce.columns-6 ul.products,
  .woocommerce ul.products.columns-3,
  .woocommerce ul.products.columns-4,
  .woocommerce ul.products.columns-5,
  .woocommerce ul.products.columns-6 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) { .woocommerce ul.products { grid-template-columns: 1fr !important; } }

.woocommerce ul.products li.product {
  width: auto !important; margin: 0 !important; float: none !important; padding: 0;
  background: #fff; border: 1px solid var(--gcid-kv-line, #e4ded1);
  display: flex; flex-direction: column; position: relative;
  transition: box-shadow .4s var(--kv-ease, ease), transform .4s var(--kv-ease, ease), border-color .4s var(--kv-ease, ease);
}
/* The UL is a CSS grid, so the LI must fill its cell. Woo core
   (woocommerce-smallscreen.css: 48%/float:left) and — the one that actually
   wins — Divi's own
   `.et_pb_wc_related_products ul.products.columns-N li.product{width:48%!important}`
   and `.woocommerce-page ul.products li.product:nth-child(n){width:…!important}`
   both out-specify the rule above (0,3,2 vs 0,2,2), so below 1024px every card
   collapsed to ~48% of its grid cell and its contents (badge pill, legal note)
   spilled outside the card box. Repeating .product lifts us to (0,4,2). */
.woocommerce ul.products li.product.product.product {
  width: auto !important; float: none !important; margin: 0 !important;
}
.woocommerce ul.products li.product::before,
.woocommerce ul.products li.product::after { display: none !important; content: none !important; }
/* Woo/Divi clearfix pseudo-elements become GRID ITEMS on the ul and steal the
   first cell (first card gets pushed to the next cell/row). Kill them. */
.woocommerce ul.products::before,
.woocommerce ul.products::after,
ul.products::before,
ul.products::after { display: none !important; content: none !important; }
.woocommerce ul.products li.product:hover {
  box-shadow: 0 22px 48px -16px rgba(20, 32, 54, .34);
  border-color: var(--gcid-kv-gold, #cbb585); transform: translateY(-3px); z-index: 2;
}
.woocommerce ul.products li.product > a.woocommerce-LoopProduct-link { display: flex; flex-direction: column; flex: 1; }

/* media */
.woocommerce ul.products li.product .et_shop_image {
  position: relative; aspect-ratio: 3 / 4; background: var(--gcid-kv-parchment, #f3efe4);
  display: flex; align-items: center; justify-content: center; overflow: hidden; margin: 0;
}
.woocommerce ul.products li.product .et_shop_image img {
  mix-blend-mode: multiply; height: 84% !important; width: auto !important; max-width: 86%;
  object-fit: contain; margin: 0; border-radius: 0; transition: transform .6s var(--kv-ease, ease);
}
.woocommerce ul.products li.product:hover .et_shop_image img { transform: translateY(-4px) scale(1.03); }
.woocommerce ul.products li.product .et_overlay { display: none !important; }

/* sale flag */
.woocommerce ul.products li.product .onsale {
  position: absolute !important; top: 14px; left: 14px; right: auto; margin: 0; z-index: 3;
  min-height: 0; min-width: 0; border-radius: 2px;
  background: rgba(255, 255, 255, .94); color: var(--gcid-kv-navy, #142036);
  border: 1px solid var(--gcid-kv-line, #e4ded1);
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif); font-variant: small-caps;
  font-weight: 500; letter-spacing: .06em; font-size: 14px; line-height: 1; padding: 5px 12px; text-transform: none;
}

/* head: category / line label */
.woocommerce ul.products li.product .kv-head { padding: 22px 24px 0; display: flex; align-items: center; gap: 10px; }
.woocommerce ul.products li.product .kv-line {
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: 11px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--gcid-kv-gold-deep, #8a7031);
  background: var(--gcid-kv-parchment, #f3efe4); padding: 5px 12px; border-radius: 40px; white-space: nowrap; line-height: 1;
}

/* name */
.woocommerce ul.products li.product h2.woocommerce-loop-product__title {
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif) !important;
  font-variant: small-caps; text-transform: none; font-weight: 500;
  font-size: var(--gvid-kv-text-lg, 22px); line-height: 1.14; letter-spacing: .015em;
  color: var(--gcid-kv-navy, #142036) !important; padding: 12px 24px 0; margin: 0; text-wrap: balance;
}

/* meta + price + grundpreis pinned to card bottom as a group */
.woocommerce ul.products li.product .kv-meta { margin-top: auto; padding: 12px 24px 0;
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: 13px;
  color: var(--gcid-kv-muted, #8b8674); display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.woocommerce ul.products li.product:not(:has(.kv-meta)) .price { margin-top: auto; }
.woocommerce ul.products li.product .price {
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif) !important;
  font-size: 24px !important; font-weight: 600; color: var(--gcid-kv-navy, #142036) !important;
  padding: 8px 24px 0; margin: 0 !important; display: block; line-height: 1.05;
}
.woocommerce ul.products li.product .price del { opacity: .5; font-weight: 400; margin-right: 6px; font-size: .72em; color: var(--gcid-kv-muted, #8b8674); }
.woocommerce ul.products li.product .price ins { text-decoration: none; }
.woocommerce ul.products li.product .price .woocommerce-Price-currencySymbol { font-size: .7em; font-weight: 400; }
.woocommerce ul.products li.product .kv-grundpreis,
.woocommerce ul.products li.product .kv-grundpreis * {
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif) !important; font-size: 11.5px !important;
  font-weight: 400 !important; color: var(--gcid-kv-muted, #8b8674) !important; line-height: 1.35 !important;
}
.woocommerce ul.products li.product .kv-grundpreis { padding: 3px 24px 0; }

/* Germanized prints its own loop notices — unit price, "inkl. 19 % MwSt.",
   "zzgl. Versandkosten", "Lieferzeit" — as unpadded <p>s scattered between the
   card's parts. inc/woo-loop-card.php already restates all four in the card's
   own typography (.kv-grundpreis + .kv-card-legal), so the raw ones rendered as
   a second, flush-left copy of the same legal text. Hide them ONLY where our
   replacement is actually present, so a card without .kv-card-legal keeps the
   PAngV/Preisangaben notices Germanized is responsible for. */
.woocommerce ul.products li.product:has(.kv-card-legal) p.wc-gzd-additional-info {
  display: none !important;
}

/* circular add-to-cart plus (native loop button, restyled).
   SHAPE AND MOTION ONLY. Every colour and every state of this control is owned
   by "== A: buttons ==" §8 — one button system, one source of truth. This block
   used to restate them (46px vs 48px, a gold card-hover ring vs A's navy one),
   so the circle's appearance depended on which rule happened to come last in
   the file. Nothing below repeats a declaration §8 makes. */
.woocommerce ul.products li.product a.button.kv-add {
  position: absolute; right: 22px; bottom: 22px; z-index: 4; min-width: 0;
  border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; padding: 0; margin: 0;
  background: #fff; border-style: solid; border-width: 1px;
  font-size: 0; line-height: 0; text-indent: 0; box-shadow: 0 3px 10px -2px rgba(20, 32, 54, .18);
  transition: background .3s var(--kv-ease, ease), color .3s var(--kv-ease, ease), border-color .3s var(--kv-ease, ease), box-shadow .3s var(--kv-ease, ease), transform .3s var(--kv-ease, ease);
}
.woocommerce ul.products li.product a.button.kv-add::after {
  /* --kv-btn-ff is the one button typeface, declared in "== A: buttons ==" */
  content: "+" !important; font-family: var(--kv-btn-ff, "Source Sans 3", Helvetica, Arial, sans-serif) !important; font-size: 26px !important; font-weight: 300; line-height: 1; color: currentColor; margin-top: -2px;
}
.woocommerce ul.products li.product a.button.kv-add:hover { transform: scale(1.06); }
.woocommerce ul.products li.product a.button.kv-add.loading { color: transparent; }
.woocommerce ul.products li.product a.button.kv-add.loading::after {
  width: 16px; height: 16px; border-style: solid; border-width: 2px;
  border-radius: 50%; animation: kv-add-spin .6s linear infinite;
}
.woocommerce ul.products li.product a.added_to_cart { display: none !important; }
@keyframes kv-add-spin { to { transform: rotate(360deg); } }

/* pagination */
.woocommerce nav.woocommerce-pagination { margin-top: 44px; text-align: center; border: 0; width: 100%; }
.woocommerce nav.woocommerce-pagination ul { display: inline-flex; gap: 6px; border: 0 !important; margin: 0; padding: 0; }
.woocommerce nav.woocommerce-pagination ul li { border: 0 !important; margin: 0; overflow: visible; }
.woocommerce nav.woocommerce-pagination ul li a,
.woocommerce nav.woocommerce-pagination ul li span {
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: 14px; min-width: 44px; height: 44px;
  line-height: 44px; padding: 0 8px; border: 1px solid var(--gcid-kv-line, #e4ded1) !important;
  background: #fff; color: var(--gcid-kv-navy, #142036); border-radius: 2px; display: inline-block;
}
.woocommerce nav.woocommerce-pagination ul li span.current { background: var(--gcid-kv-navy, #142036); color: #fff; border-color: var(--gcid-kv-navy, #142036) !important; }
.woocommerce nav.woocommerce-pagination ul li a:hover { background: var(--gcid-kv-navy, #142036); color: #fff; border-color: var(--gcid-kv-navy, #142036) !important; }

/* ---------- loop card: link + legal fine print ----------
   Now emitted as direct <li> children (outside the product <a>) — carry the
   same 24px horizontal card rhythm as .price/.kv-grundpreis. .kv-card-legal
   reserves right/bottom room so it clears the absolute plus button
   (46px, at right:22px / bottom:22px). */
.woocommerce ul.products li.product .kv-card-link {
  display: inline-block; align-self: flex-start; margin: 12px 24px 0; font-size: var(--gvid-kv-text-xs, 12px); font-weight: 600;
  letter-spacing: .06em; color: var(--gcid-kv-navy, #223246);
  border-bottom: 1px solid var(--gcid-kv-gold, #b9a170); padding-bottom: 2px; transition: color .3s var(--kv-ease, ease);
}
.woocommerce ul.products li.product .kv-card-link:hover { color: var(--gcid-kv-gold-deep, #9c8456); }
.woocommerce ul.products li.product .kv-card-legal {
  margin: 8px 0 0; padding: 0 84px 24px 24px;
  font-size: var(--gvid-kv-text-2xs, 11px); color: var(--gcid-kv-muted, #7c7e82); line-height: 1.5;
}
.woocommerce ul.products li.product .kv-card-legal a { color: inherit; text-decoration: underline; }

/* ---------- shop category tiles (TB body 19682) ----------
   Styled here, NOT via the modules' css.freeForm: Divi 5's Theme-Builder
   re-prefix pass (".et-db #et-boc .et-l") corrupts multi-rule freeForm at rule
   boundaries (emits ".et-db <last-decl>}" garbage that swallows the following
   rule) — verified live 2026-07-14. Uniform tiles: the fixed 4/5 aspect ratio
   sits on the image CONTAINER (flex-centered), the img is only max-constrained,
   so squat photos (jars, packages) fill the same box height as tall bottles and
   every title starts at the same y. Parchment stays on the CONTAINER only —
   a bg behind the img double-multiplies letterbox strips under multiply. */
.et_pb_blurb.kv-cat-tile { transition: border-color .45s ease, box-shadow .45s ease; }
.et_pb_blurb.kv-cat-tile:hover { box-shadow: 0 18px 40px -24px rgba(20, 33, 61, .35); }
.et_pb_blurb.kv-cat-tile .et_pb_main_blurb_image { display: block; margin-bottom: var(--gvid-kv-space-sm, 20px); }
.et-db #et-boc .et-l .et_pb_blurb.kv-cat-tile .et_pb_main_blurb_image .et_pb_image_wrap {
  display: flex !important; align-items: center; justify-content: center;
  width: 100%; aspect-ratio: 4 / 5;
  background: var(--gcid-kv-parchment, #f3efe4);
  border-radius: var(--gvid-kv-radius, 2px);
  overflow: hidden; padding: var(--gvid-kv-space-sm, 20px); box-sizing: border-box;
}
.et_pb_blurb.kv-cat-tile .et_pb_main_blurb_image img {
  mix-blend-mode: multiply; background: none;
  max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain;
}
.et_pb_blurb.kv-cat-tile .et_pb_module_header { font-variant: small-caps; letter-spacing: .03em; }

/* ============================================================
   == D: cart-checkout ==
   Warenkorb / Kasse / Mein Konto render native WooCommerce +
   Germanized shortcode markup (no Divi blocks to attach presets
   to), so the design system is applied here via the same tokens
   Divi presets use elsewhere, scoped to each page's body class.
   Buttons (.button, #place_order, .checkout-button, "Zurück zum
   Shop", cart/checkout CTAs) are Piece A's territory — untouched.
   ============================================================ */

/* ---------- readable quiet text (WCAG 1.4.3 AA) ----------
   Same problem as piece B's product template, same fix: --gcid-kv-muted
   resolves to the global palette's #7c7e82, which the checkout/cart markup
   uses for statutory copy — the Germanized Lieferzeit/Füllmenge lines under
   each cart line item (#order_review td.product-name .wc-gzd-cart-info) and
   the binding payment-terms copy inside the selected gateway's payment_box
   ("Bitte überweisen Sie den Gesamtbetrag innerhalb von 14 Tagen …"). Both
   sit on near-white/parchment fills and land at 3.6-4.1:1, below the 4.5:1
   floor. Re-point the token for this page family only — #666a6f keeps a
   safety margin over 4.5:1 against BOTH backing colours in use here:
     #666a6f on #ffffff  = 5.45:1   (order review card, cart table meta)
     #666a6f on #f3efe4  = 4.74:1   (payment_box, legal-checkbox parchment)
   The global palette itself is piece A's and stays untouched. */
body.woocommerce-cart,
body.woocommerce-checkout,
body.woocommerce-account { --gcid-kv-muted: #666a6f; }

body.woocommerce-cart article.post-62,
body.woocommerce-checkout article.post-61,
body.woocommerce-account article.post-60 {
  max-width: var(--gvid-kv-content-max, 1180px);
  margin: 0 auto;
  /* the summe/order-review cards otherwise sit flush on the navy footer —
     their bottom border needs air to read as a closed card */
  padding-bottom: clamp(48px, 6vw, 96px);
}
body.woocommerce-cart h1.entry-title,
body.woocommerce-checkout h1.entry-title,
body.woocommerce-account h1.entry-title {
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif) !important;
  font-weight: 500; font-size: clamp(32px, 4vw, 46px); color: var(--gcid-kv-navy, #142036) !important;
  letter-spacing: -.01em; margin: var(--gvid-kv-space-lg, 40px) 0 var(--gvid-kv-space-md, 26px);
  padding-bottom: var(--gvid-kv-space-sm, 20px); border-bottom: 1px solid var(--gcid-kv-line, #e4ded1);
}

/* ---------- shared field language (checkout inputs, cart coupon, account forms) ---------- */
body.woocommerce-cart .woocommerce input.input-text,
body.woocommerce-cart .woocommerce input[type="text"],
body.woocommerce-cart .woocommerce input[type="number"],
body.woocommerce-checkout .woocommerce input.input-text,
body.woocommerce-checkout .woocommerce input[type="text"],
body.woocommerce-checkout .woocommerce input[type="email"],
body.woocommerce-checkout .woocommerce input[type="tel"],
body.woocommerce-checkout .woocommerce input[type="number"],
body.woocommerce-checkout .woocommerce input[type="password"],
body.woocommerce-checkout .woocommerce select,
body.woocommerce-checkout .woocommerce textarea,
body.woocommerce-account .woocommerce input.input-text,
body.woocommerce-account .woocommerce input[type="text"],
body.woocommerce-account .woocommerce input[type="email"],
body.woocommerce-account .woocommerce input[type="password"] {
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: var(--gvid-kv-text-base, 15px);
  color: var(--gcid-kv-charcoal, #33302a); background: #fff; border: 1px solid var(--gcid-kv-line, #e4ded1);
  border-radius: var(--gvid-kv-radius, 2px); padding: 12px 15px; transition: border-color .25s ease, box-shadow .25s ease;
}
body.woocommerce-cart .woocommerce input.input-text:focus,
body.woocommerce-checkout .woocommerce input:focus,
body.woocommerce-checkout .woocommerce select:focus,
body.woocommerce-checkout .woocommerce textarea:focus,
body.woocommerce-account .woocommerce input:focus {
  outline: none; border-color: var(--gcid-kv-gold, #b9a170); box-shadow: 0 0 0 3px rgba(185, 161, 112, .14);
}
body.woocommerce-checkout .woocommerce-checkout .form-row label:not(.woocommerce-form__label-for-checkbox),
body.woocommerce-account .woocommerce-form-row label:not(.woocommerce-form__label-for-checkbox) {
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: var(--gvid-kv-text-2xs, 11.5px);
  font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--gcid-kv-ink, #33302a);
}
/* checkbox labels (legal/AGB consent, "Ein Konto erstellen?", "Angemeldet bleiben" …) read as a
   normal sentence, not a micro form-label — they carry running text + inline links, not a field name. */
body.woocommerce-checkout .form-row .woocommerce-form__label-for-checkbox,
body.woocommerce-checkout .woocommerce-form__label-for-checkbox .woocommerce-gzd-legal-checkbox-text,
body.woocommerce-checkout .woocommerce-gzd-legal-checkbox-text {
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: var(--gvid-kv-text-sm, 14.5px);
  font-weight: 400; letter-spacing: normal; text-transform: none; color: var(--gcid-kv-ink, #222220); line-height: 1.5;
}
body.woocommerce-checkout .select2-container--default .select2-selection--single,
body.woocommerce-account .select2-container--default .select2-selection--single {
  border: 1px solid var(--gcid-kv-line, #e4ded1) !important; border-radius: var(--gvid-kv-radius, 2px) !important;
  height: 46px !important; padding: 6px 15px !important;
}

/* custom checkbox (Germanized legal checkbox, "Ein Konto erstellen?", "Angemeldet bleiben" …) */
body.woocommerce-checkout .woocommerce-form__input-checkbox,
body.woocommerce-account .woocommerce-form__input-checkbox,
body.woocommerce-cart input[type="checkbox"] {
  /* !important required: Woo core's ".woocommerce form .form-row .input-checkbox" (0,3,1)
     outranks this selector (0,2,1) and forces display:inline, which makes appearance:none
     collapse the box to its border box (2x21px) regardless of the width/height below. */
  display: inline-block !important; appearance: none; -webkit-appearance: none; width: 19px !important; height: 19px !important;
  margin: 0 2px 0 0 !important; flex-shrink: 0;
  border: 1.5px solid var(--gcid-kv-muted, #8b8674); border-radius: 4px; background: #fff; position: relative;
  vertical-align: -4px !important; cursor: pointer; transition: background .2s ease, border-color .2s ease;
}
body.woocommerce-checkout .woocommerce-form__input-checkbox:checked,
body.woocommerce-account .woocommerce-form__input-checkbox:checked {
  background: var(--gcid-kv-navy, #142036); border-color: var(--gcid-kv-navy, #142036);
}
body.woocommerce-checkout .woocommerce-form__input-checkbox:checked::after,
body.woocommerce-account .woocommerce-form__input-checkbox:checked::after {
  content: ""; position: absolute; left: 5px; top: 1px; width: 5px; height: 10px;
  border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(40deg);
}
body.woocommerce-checkout .woocommerce-form__input-checkbox:focus-visible,
body.woocommerce-account .woocommerce-form__input-checkbox:focus-visible {
  outline: none; box-shadow: 0 0 0 3px rgba(185, 161, 112, .3);
}

/* ---------- Warenkorb ---------- */
body.woocommerce-cart table.shop_table { border: 1px solid var(--gcid-kv-line, #e4ded1); border-radius: var(--gvid-kv-radius, 2px); border-collapse: separate; border-spacing: 0; }
body.woocommerce-cart table.shop_table thead th {
  background: var(--gcid-kv-parchment, #f3efe4); font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif);
  font-size: var(--gvid-kv-text-2xs, 11px); font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--gcid-kv-navy, #142036); border-bottom: 1px solid var(--gcid-kv-line, #e4ded1); padding: 14px 16px;
}
body.woocommerce-cart table.shop_table td { border-top: 1px solid var(--gcid-kv-line-soft, #ece6d8); padding: 18px 16px; vertical-align: middle; }
body.woocommerce-cart td.product-thumbnail img {
  background: var(--gcid-kv-parchment, #f3efe4); border: 1px solid var(--gcid-kv-line, #e4ded1); border-radius: var(--gvid-kv-radius, 2px);
  mix-blend-mode: multiply; padding: 6px; width: 64px; height: auto;
}
body.woocommerce-cart td.product-name a {
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif) !important; font-variant: small-caps;
  font-size: var(--gvid-kv-text-lg, 20px); color: var(--gcid-kv-navy, #142036) !important; letter-spacing: .015em;
}
body.woocommerce-cart td.product-name a:hover { color: #7a6528 !important; text-decoration: underline; } /* AA-safe gold accent on hover (5.65:1 on white); not the fill --gcid-kv-gold-deep, which fails at 3.6:1 */
body.woocommerce-cart td.product-name dl.variation,
body.woocommerce-cart td.product-name .kv-cart-meta {
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: var(--gvid-kv-text-xs, 12.5px); color: var(--gcid-kv-muted, #8b8674);
}
body.woocommerce-cart td.product-price,
body.woocommerce-cart td.product-subtotal { font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif); font-size: var(--gvid-kv-text-md, 17px); font-weight: 600; color: var(--gcid-kv-navy, #142036); }
/* the Grundpreis / Lieferzeit / Füllmenge lines are statutory fine print, not
   prices: identical 14px Source Sans muted on cart AND checkout, every width */
body.woocommerce-cart .wc-gzd-cart-info,
body.woocommerce-cart td.product-price .wc-gzd-cart-info,
body.woocommerce-cart td.product-price .wc-gzd-cart-info .amount {
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: 14px;
  font-weight: 400; color: var(--gcid-kv-muted, #8b8674);
}
body.woocommerce-cart td.product-remove a.remove {
  color: var(--gcid-kv-muted, #8b8674) !important; background: transparent !important; border: 1px solid var(--gcid-kv-line, #e4ded1) !important;
  border-radius: 50%; width: 26px; height: 26px; line-height: 24px !important;
}
body.woocommerce-cart td.product-remove a.remove:hover { color: #fff !important; background: var(--gcid-kv-rose, #b5545a) !important; border-color: var(--gcid-kv-rose, #b5545a) !important; }
body.woocommerce-cart td.product-quantity .quantity input.qty {
  width: 60px; text-align: center; padding: 10px 8px;
}
body.woocommerce-cart .cart-collaterals { display: flex; justify-content: flex-end; }
body.woocommerce-cart .cart_totals {
  background: #fff; border: 1px solid var(--gcid-kv-line, #e4ded1); border-radius: var(--gvid-kv-radius, 2px); overflow: hidden;
  width: 100%; max-width: 420px; float: none;
}
body.woocommerce-cart .cart_totals h2 {
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif) !important; font-variant: small-caps; font-weight: 500;
  font-size: var(--gvid-kv-text-xl, 24px); color: var(--gcid-kv-navy, #142036) !important; letter-spacing: .02em;
  background: var(--gcid-kv-parchment, #f3efe4); margin: 0 !important; padding: 18px 24px;
}
body.woocommerce-cart .cart_totals table.shop_table { border: none; border-radius: 0; }
body.woocommerce-cart .cart_totals table.shop_table th,
body.woocommerce-cart .cart_totals table.shop_table td { padding: 14px 24px; border-top: 1px solid var(--gcid-kv-line-soft, #ece6d8); font-size: var(--gvid-kv-text-sm, 14px); }
body.woocommerce-cart .cart_totals table.shop_table th { font-weight: 600; color: var(--gcid-kv-ink, #33302a); width: 40%; }
body.woocommerce-cart .cart_totals .order-total th,
body.woocommerce-cart .cart_totals .order-total td { border-top: 1px solid var(--gcid-kv-line, #e4ded1); }
body.woocommerce-cart .cart_totals .order-total td strong {
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif); font-size: var(--gvid-kv-text-2xl, 28px); font-weight: 600; color: var(--gcid-kv-navy, #142036);
}
body.woocommerce-cart .cart_totals .woocommerce-shipping-methods { list-style: none; margin: 0; padding: 0; }
body.woocommerce-cart .cart_totals .woocommerce-shipping-methods li { padding: 4px 0; }
body.woocommerce-cart .cart_totals input[type="radio"] { accent-color: var(--gcid-kv-navy, #142036); margin-right: 6px; }
body.woocommerce-cart form.woocommerce-shipping-calculator { display: none; } /* shipping already resolved via cart totals, avoid a redundant on-brand-less form */
body.woocommerce-cart .coupon .input-text { min-width: 220px; }
/* Divi core's own style-static.min.css ships a same-page selector
   (".woocommerce-cart table.cart td.actions .coupon .input-text") that is
   MORE specific (5 classes/2 elements) than the shared field-language block
   above (3 classes/2 elements), so #coupon_code was still rendering Divi's
   stock grey fill (#eeeeee) with a #999999 placeholder — 2.46:1, and the
   only un-branded control left on the Warenkorb. Never edit the core file;
   out-specify it here instead (ID selector + matching Divi's own ancestor
   chain) so this always wins regardless of stylesheet load order. */
body.woocommerce-cart table.cart td.actions .coupon input#coupon_code {
  appearance: none; -webkit-appearance: none;
  background: #fff; color: var(--gcid-kv-charcoal, #33302a);
  border: 1px solid var(--gcid-kv-line, #e4ded1); border-radius: var(--gvid-kv-radius, 2px);
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: var(--gvid-kv-text-base, 15px);
  padding: 12px 15px; line-height: normal;
}
body.woocommerce-cart table.cart td.actions .coupon input#coupon_code::placeholder { color: var(--gcid-kv-muted, #666a6f); opacity: 1; }
body.woocommerce-cart table.cart td.actions .coupon input#coupon_code:focus {
  outline: none; border-color: var(--gcid-kv-gold, #b9a170); box-shadow: 0 0 0 3px rgba(185, 161, 112, .14);
}
body.woocommerce-cart .woocommerce-cart-form .actions { border-top: 1px solid var(--gcid-kv-line, #e4ded1); padding-top: var(--gvid-kv-space-md, 24px); margin-top: var(--gvid-kv-space-sm, 16px); }

/* ---------- Kasse ---------- */
body.woocommerce-checkout .col2-set { display: flex; flex-wrap: wrap; gap: var(--gvid-kv-space-xl, 48px); justify-content: space-between; }
body.woocommerce-checkout .col2-set .col-1,
body.woocommerce-checkout .col2-set .col-2 { flex: 1 1 380px; width: auto; float: none; }
body.woocommerce-checkout .woocommerce-billing-fields h3,
body.woocommerce-checkout .woocommerce-shipping-fields h3,
body.woocommerce-checkout #order_review_heading,
body.woocommerce-checkout #order_payment_heading {
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif) !important; font-variant: small-caps; font-weight: 500;
  font-size: var(--gvid-kv-text-xl, 25px) !important; color: var(--gcid-kv-navy, #142036) !important; letter-spacing: .02em;
  margin: var(--gvid-kv-space-lg, 40px) 0 var(--gvid-kv-space-md, 22px) !important; padding-bottom: 10px;
  border-bottom: 1px solid var(--gcid-kv-line, #e4ded1);
}
body.woocommerce-checkout .col-1 .woocommerce-billing-fields h3 { margin-top: 0 !important; }
body.woocommerce-checkout .woocommerce-additional-fields h3 { display: none; } /* empty heading Woo prints even with no extra fields */
body.woocommerce-checkout .create-account { margin-top: var(--gvid-kv-space-sm, 16px); }

/* order review — one bordered card, navy summary bar, big total (mirrors cart_totals) */
body.woocommerce-checkout #order_review {
  background: #fff; border: 1px solid var(--gcid-kv-line, #e4ded1); border-radius: var(--gvid-kv-radius, 2px);
  padding: var(--gvid-kv-space-lg, 28px); margin-top: var(--gvid-kv-space-md, 22px);
}
/* explicit bg: without it table.shop_table/th/td fall back to WooCommerce core's stock grey
   (rgb(238,238,238) via its responsive shop-table rules), which the design's gold/navy text
   was never checked against. Pin it to the card's own white so every text color here is
   verified against a known, on-brand background. */
body.woocommerce-checkout #order_review table.shop_table,
body.woocommerce-checkout #order_review table.shop_table th,
body.woocommerce-checkout #order_review table.shop_table td { border: none; background: #fff; }
/* header row (Produkt / Zwischensumme labels): bottom rule only, value column flush right
   so it lines up with every value below it */
body.woocommerce-checkout #order_review table.shop_table thead th {
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: var(--gvid-kv-text-2xs, 11px); font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--gcid-kv-navy, #142036);
  border-bottom: 1px solid var(--gcid-kv-line, #e4ded1); padding-bottom: 12px;
}
body.woocommerce-checkout #order_review table.shop_table thead th.product-total { text-align: right; }
/* every row below the header — line-item AND tfoot totals (Zwischensumme/Sendung/
   Gesamtsumme/MwSt.) — gets the SAME top divider on both cells, th included. Previously only
   td had border-top so the tfoot dividers stopped dead at the value column: the left ~2/3 of
   each totals row (the th label) showed no rule at all. */
body.woocommerce-checkout #order_review table.shop_table tbody td,
body.woocommerce-checkout #order_review table.shop_table tfoot th,
body.woocommerce-checkout #order_review table.shop_table tfoot td { border-top: 1px solid var(--gcid-kv-line-soft, #ece6d8); padding: 12px 0; }
body.woocommerce-checkout #order_review table.shop_table tfoot th {
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: var(--gvid-kv-text-2xs, 11px); font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--gcid-kv-navy, #142036); text-align: left;
}
/* value column: right-aligned throughout (was left/inherited, so €-amounts floated mid-row
   instead of stacking flush against the right edge like the header label above them) */
body.woocommerce-checkout #order_review table.shop_table tbody td.product-total,
body.woocommerce-checkout #order_review table.shop_table tfoot td { text-align: right; }
body.woocommerce-checkout #order_review table.shop_table tfoot td {
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: var(--gvid-kv-text-sm, 14px); color: var(--gcid-kv-ink, #33302a);
}
/* line-item layout: the ACTUAL live markup here (verified via rendered DOM, not the germanized
   template source alone — this Germanized version injects checkout thumbnails through
   wc-gzd-template-functions.php's woocommerce_gzd_template_inject_checkout_table_thumbnails,
   which produces a different tree than the plain review-order-product-table.php file) is:
     td.product-name
       > div.wc-gzd-cart-item-name-wrapper   (thumbnail + name text + qty, ALREADY flex via
                                               germanized's own layout.scss on desktop)
       > p.wc-gzd-cart-info.delivery-time-info   (Lieferzeit — a SIBLING after the wrapper, not
       > p.wc-gzd-cart-info.units-info            nested inside it, and with no left indent)
   Two bugs: (1) germanized's own .wc-gzd-cart-item-thumbnail is a percentage width (max-width:15%)
   with no matching img width, so it resizes with the column and never lines up with the fixed
   64px thumbnails used everywhere else on this page; (2) the two trailing <p class="wc-gzd-cart-info">
   siblings have no indent, so they render flush at the td's left edge — under the IMAGE, not
   under the name — instead of reading as one compact unit with it. Pin the thumbnail to the
   same 64px used on the Warenkorb table and indent the meta lines to the text column (64px image
   + 14px gap) so image, name and every meta line share one tight block. */
body.woocommerce-checkout #order_review td.product-name { padding: 16px 0; }
body.woocommerce-checkout #order_review td.product-name .wc-gzd-cart-item-name-wrapper {
  display: flex; align-items: flex-start; gap: 14px;
}
body.woocommerce-checkout #order_review td.product-name .wc-gzd-cart-item-thumbnail {
  flex: 0 0 64px; width: 64px; max-width: 64px; min-width: 64px; margin: 0;
}
body.woocommerce-checkout #order_review td.product-name .wc-gzd-cart-item-thumbnail img {
  width: 64px; height: auto; display: block; margin: 0;
  background: var(--gcid-kv-parchment, #f3efe4); border: 1px solid var(--gcid-kv-line, #e4ded1);
  border-radius: var(--gvid-kv-radius, 2px); mix-blend-mode: multiply; padding: 5px;
}
body.woocommerce-checkout #order_review td.product-name .wc-gzd-cart-info,
body.woocommerce-checkout #order_review td.product-name dl.variation {
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: 14px; /* statutory copy: same 14px as the cart page, every width */
  color: var(--gcid-kv-muted, #8b8674); margin: 4px 0 0 78px; line-height: 1.4; /* 78px = 64px thumb + 14px gap */
}
body.woocommerce-checkout #order_review .product-name { font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif); font-variant: small-caps; color: var(--gcid-kv-navy, #142036); font-size: var(--gvid-kv-text-md, 16px); }
body.woocommerce-checkout #order_review .product-total,
body.woocommerce-checkout #order_review .amount { font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif); color: var(--gcid-kv-navy, #142036); font-weight: 600; }
/* tfoot values (Zwischensumme/Sendung/MwSt.): the .amount rule above sets the nested
   <span class="amount"> to serif, but the surrounding <td> text (e.g. the shipping method
   label) stays on the inherited sans body font — one row, two money-adjacent fonts. Pin the
   whole tfoot value cell (and its .amount span) to the same sans as its th label so each row
   reads as one font; only the Gesamtsumme gets the serif accent below. */
body.woocommerce-checkout #order_review tfoot td .amount { font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-weight: 600; color: var(--gcid-kv-navy, #142036); }
/* the PAngV Grundpreis renders inside td.product-total (not product-name!) and the
   .amount rule above would set it serif — statutory fine print is sans, 14px, muted,
   on cart AND checkout alike */
body.woocommerce-checkout #order_review td.product-total .wc-gzd-cart-info,
body.woocommerce-checkout #order_review td.product-total .wc-gzd-cart-info .amount {
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: 14px;
  font-weight: 400; color: var(--gcid-kv-muted, #8b8674);
}
/* prices anchor to the first line of the product name, not the middle of a tall row */
body.woocommerce-checkout #order_review table.shop_table tbody th,
body.woocommerce-checkout #order_review table.shop_table tbody td { vertical-align: top; }
/* a wrapped payment-method label must indent under its own first word, not the
   radio. inline-block shrink-to-fit drops the whole label BELOW the radio once
   it stops fitting beside it (seen at 320) — grid keeps radio and label in
   fixed columns at every width, and the payment_box spans both. */
body.woocommerce-checkout ul.wc_payment_methods li.wc_payment_method { display: grid; grid-template-columns: auto 1fr; column-gap: 10px; align-items: start; }
body.woocommerce-checkout ul.wc_payment_methods li.wc_payment_method > input.input-radio { grid-column: 1; margin: 2px 0 0; }
body.woocommerce-checkout ul.wc_payment_methods li.wc_payment_method > label { grid-column: 2; display: block; max-width: none; }
body.woocommerce-checkout ul.wc_payment_methods li.wc_payment_method > .payment_box { grid-column: 1 / -1; }
body.woocommerce-checkout #order_review tfoot .order-total td strong .amount { font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif); font-size: var(--gvid-kv-text-2xl, 26px); font-weight: 600; }
body.woocommerce-checkout #order_review tfoot .order-total td small { display: block; margin-top: 4px; font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: var(--gvid-kv-text-2xs, 11.5px); color: var(--gcid-kv-muted, #8b8674); text-align: right; }

/* payment method list — card rows with a fake radio dot (mirrors design/checkout.html .opt-card) */
body.woocommerce-checkout ul.wc_payment_methods { list-style: none; margin: 0 0 var(--gvid-kv-space-md, 22px); padding: 0; }
body.woocommerce-checkout ul.wc_payment_methods li.wc_payment_method {
  background: #fff; border: 1px solid var(--gcid-kv-line, #e4ded1); border-radius: var(--gvid-kv-radius, 2px); margin-bottom: 10px; padding: 15px 18px; transition: border-color .25s ease;
} /* explicit white pins the row against any translucent tint a gateway plugin (e.g. PayPal's ppcp placeholder) paints behind its own label */
body.woocommerce-checkout ul.wc_payment_methods li.wc_payment_method:has(input:checked) { border-color: var(--gcid-kv-navy, #142036); background: var(--gcid-kv-parchment, #f3efe4); }
body.woocommerce-checkout ul.wc_payment_methods input.input-radio {
  display: inline-block; appearance: none; -webkit-appearance: none; width: 19px; height: 19px; border: 1.5px solid var(--gcid-kv-muted, #8b8674);
  border-radius: 50%; margin: 0 10px 0 0; vertical-align: -5px; position: relative; cursor: pointer; flex-shrink: 0;
}
body.woocommerce-checkout ul.wc_payment_methods input.input-radio:checked { border-color: var(--gcid-kv-navy, #142036); }
body.woocommerce-checkout ul.wc_payment_methods input.input-radio:checked::after {
  content: ""; position: absolute; inset: 3px; border-radius: 50%; background: var(--gcid-kv-navy, #142036);
}
body.woocommerce-checkout ul.wc_payment_methods label { font-weight: 600; color: var(--gcid-kv-navy, #142036); }
body.woocommerce-checkout ul.wc_payment_methods .payment_box {
  font-size: var(--gvid-kv-text-sm, 13.5px); color: var(--gcid-kv-muted, #8b8674); margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--gcid-kv-line, #e4ded1);
}
/* WooCommerce core paints #payment (lavender tint, 5px radius) and
   .woocommerce-checkout #payment div.payment_box (grey box + a triangle
   ::before pointer) with an id selector — the rules above lose that
   specificity fight and the core lavender box shows through untouched.
   Match core's id-anchored selectors 1:1 and force with !important so this
   wins regardless of core CSS load order. */
body.woocommerce-checkout #payment,
body.woocommerce-checkout #payment ul.payment_methods {
  background: transparent !important; border: none !important; border-radius: 0 !important;
}
body.woocommerce-checkout #payment div.payment_box,
.woocommerce-checkout #payment div.payment_box {
  background: var(--gcid-kv-parchment, #f3efe4) !important;
  color: var(--gcid-kv-muted, #8b8674) !important;
  font-size: var(--gvid-kv-text-sm, 13.5px) !important;
  border: none !important; border-radius: var(--gvid-kv-radius, 2px) !important;
  margin: 10px 0 0 !important; padding: 14px 16px !important;
}
body.woocommerce-checkout #payment div.payment_box::before,
.woocommerce-checkout #payment div.payment_box::before {
  content: none !important; /* kill the core lavender triangle pointer */
}

/* legal checkbox (AGB/Widerruf/Datenschutz) — give the mandatory acceptance its own weight */
body.woocommerce-checkout .wc-gzd-checkbox-placeholder-legal p.legal {
  background: var(--gcid-kv-parchment, #f3efe4); border: 1px solid var(--gcid-kv-line, #e4ded1); border-radius: var(--gvid-kv-radius, 2px);
  padding: 16px 18px; margin: 0 0 var(--gvid-kv-space-md, 22px); font-size: var(--gvid-kv-text-sm, 14px); line-height: 1.55;
}
body.woocommerce-checkout .wc-gzd-checkbox-placeholder-legal label { display: flex; align-items: flex-start; gap: 10px; }
body.woocommerce-checkout .wc-gzd-checkbox-placeholder-legal .woocommerce-form__input-checkbox { margin-top: 2px; }
body.woocommerce-checkout .wc-gzd-checkbox-placeholder-legal a { color: var(--gcid-kv-navy, #142036); text-decoration: underline; } /* gold-deep on the parchment box is 3.1:1, fails AA — the AGB/Widerruf/Datenschutz links are the mandatory §312j part, they need to read */
/* same fix for the account-registration privacy consent ("Ja, ich möchte ein Kundenkonto
   eröffnen und akzeptiere die Datenschutzerklärung") — its link inherits the site's default
   gold-deep link color, 3.59:1 on white, also below AA for a mandatory consent link. */
body.woocommerce-account .woocommerce-gzd-reg_data_privacy-checkbox-text a,
body.woocommerce-account .woocommerce-form-row .woocommerce-gzd-legal-checkbox-text a { color: var(--gcid-kv-navy, #142036); text-decoration: underline; }
body.woocommerce-checkout .wc-gzd-checkbox-placeholder-legal a:hover { color: var(--gcid-kv-navy, #142036); }

/* fine-print notices Germanized attaches (MwSt/Lieferzeit/etc.) inside checkout.
   --gcid-kv-muted itself only clears 3.65:1 on white — too low for a Pflichtangabe — so this
   scoped override uses a darker tone (5.74:1+) instead of touching the shared design token. */
body.woocommerce-checkout .wc-gzd-additional-info,
body.woocommerce-checkout small.wc-gzd-additional-costs-info,
body.woocommerce-checkout #order_review small.includes_tax,
body.woocommerce-cart small.includes_tax { color: #6b6656 !important; font-size: var(--gvid-kv-text-2xs, 11.5px); } /* !important: Germanized's own build CSS colors .includes_tax directly and otherwise wins */

@media (max-width: 980px) {
  body.woocommerce-checkout .col2-set { gap: var(--gvid-kv-space-lg, 32px); }
}

/* ---------- Mein Konto ---------- */
body.woocommerce-account .woocommerce-MyAccount-navigation ul { list-style: none; display: flex; flex-wrap: wrap; gap: 4px 28px; margin: 0 0 var(--gvid-kv-space-xl, 40px); padding: 0 0 4px; border-bottom: 1px solid var(--gcid-kv-line, #e4ded1); }
body.woocommerce-account .woocommerce-MyAccount-navigation li { margin: 0; }
body.woocommerce-account .woocommerce-MyAccount-navigation a {
  display: inline-block; padding: 10px 0; font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: var(--gvid-kv-text-xs, 13px);
  font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--gcid-kv-muted, #8b8674); border-bottom: 2px solid transparent;
}
body.woocommerce-account .woocommerce-MyAccount-navigation a:hover { color: var(--gcid-kv-navy, #142036); }
body.woocommerce-account .woocommerce-LostPassword a { color: var(--gcid-kv-navy, #142036); text-decoration: underline; } /* default link gold-deep is 3.59:1 on white, fails AA */
body.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a { color: var(--gcid-kv-navy, #142036); border-bottom-color: var(--gcid-kv-gold, #b9a170); }

body.woocommerce-account #customer_login h2,
body.woocommerce-account .woocommerce-MyAccount-content h2,
body.woocommerce-account .woocommerce-MyAccount-content h3 {
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", serif) !important; font-variant: small-caps; font-weight: 500;
  font-size: var(--gvid-kv-text-xl, 26px); color: var(--gcid-kv-navy, #142036) !important; letter-spacing: .02em; margin-bottom: var(--gvid-kv-space-md, 22px);
}
body.woocommerce-account .u-columns.col2-set { display: flex; flex-wrap: wrap; gap: var(--gvid-kv-space-xl, 48px); }
body.woocommerce-account .u-columns.col2-set .u-column1,
body.woocommerce-account .u-columns.col2-set .u-column2 { flex: 1 1 320px; width: auto; float: none; }
body.woocommerce-account .woocommerce-form-row { margin-bottom: 16px; }
body.woocommerce-account table.woocommerce-orders-table,
body.woocommerce-account table.shop_table { border: 1px solid var(--gcid-kv-line, #e4ded1); border-radius: var(--gvid-kv-radius, 2px); border-collapse: separate; }
body.woocommerce-account table.woocommerce-orders-table thead th {
  background: var(--gcid-kv-parchment, #f3efe4); font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: var(--gvid-kv-text-2xs, 11px);
  font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--gcid-kv-navy, #142036); padding: 14px 16px; border-bottom: 1px solid var(--gcid-kv-line, #e4ded1);
}
body.woocommerce-account table.woocommerce-orders-table td { padding: 14px 16px; border-top: 1px solid var(--gcid-kv-line-soft, #ece6d8); font-size: var(--gvid-kv-text-sm, 14px); }
body.woocommerce-account mark.order-status { background: var(--gcid-kv-parchment-deep, #ece0c4); color: var(--gcid-kv-navy, #142036); border-radius: 20px; padding: 4px 12px; font-size: var(--gvid-kv-text-2xs, 11px); font-weight: 600; letter-spacing: .04em; }
body.woocommerce-account .woocommerce-Address { border: 1px solid var(--gcid-kv-line, #e4ded1); border-radius: var(--gvid-kv-radius, 2px); padding: var(--gvid-kv-space-md, 22px); }
body.woocommerce-account .woocommerce-Address-title h3 { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
@media (max-width: 700px) {
  body.woocommerce-account .woocommerce-MyAccount-navigation ul { gap: 4px 18px; }
}

/* ---------- collaterals row: trust aside fills the dead left half ---------- */
body.woocommerce-cart .cart-collaterals { justify-content: space-between; align-items: flex-start; gap: var(--gvid-kv-space-xl, 48px); flex-wrap: wrap; }
.kv-cart-aside { flex: 1 1 320px; max-width: 480px; padding-top: var(--gvid-kv-space-md, 22px); }
.kv-cart-aside .kv-cart-continue {
  display: inline-block; font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif); font-size: var(--gvid-kv-text-xs, 13px);
  font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--gcid-kv-navy, #142036);
  border-bottom: 2px solid var(--gcid-kv-gold, #b9a170); padding-bottom: 4px; margin-bottom: var(--gvid-kv-space-md, 22px);
}
.kv-cart-aside .kv-cart-trust { list-style: none !important; margin: 0; padding: 0; }
.kv-cart-aside .kv-cart-trust li { list-style: none !important; }
.kv-cart-aside .kv-cart-trust li {
  padding: 10px 0 10px 26px; border-bottom: 1px solid var(--gcid-kv-line-soft, #ece6d8);
  font-size: var(--gvid-kv-text-sm, 14.5px); color: var(--gcid-kv-ink, #33302a); position: relative;
}
.kv-cart-aside .kv-cart-trust li::before { content: "✓"; position: absolute; left: 2px; color: var(--gcid-kv-gold-deep, #9a8352); font-weight: 700; }

/* ---------- totals card: close the empty band above the checkout button ---------- */
body.woocommerce-cart .cart_totals .wc-proceed-to-checkout { padding: 0 24px 24px; margin: 0; }
body.woocommerce-cart .cart_totals .wc-proceed-to-checkout .checkout-button { margin-bottom: 0; }

/* ---------- phone: the order-review table may never break out of its card ----------
   min-content of the letter-spaced uppercase footer th + the product cell pins the
   auto-layout table wider than the card's content box below ~480px (measured 317.7px
   vs 263.5px at 390): fixed layout + wrap-anywhere lets every column shrink. */
@media (max-width: 600px) {
  body.woocommerce-checkout #order_review table.shop_table { table-layout: fixed; width: 100%; }
  body.woocommerce-checkout #order_review table.shop_table th.product-name,
  body.woocommerce-checkout #order_review table.shop_table td.product-name { width: 64%; }
  body.woocommerce-checkout #order_review table.shop_table th,
  body.woocommerce-checkout #order_review table.shop_table td { overflow-wrap: break-word; letter-spacing: .02em; }
  /* the desktop media-row (64px thumb flex slot + 78px meta indent) starves the
     narrow fixed column into sliver names. Collapse to block flow instead: the
     thumbnail stacks above, the × qty runs inline right after the name's last
     word, and the price cell top-aligns with the thumbnail row. */
  body.woocommerce-checkout #order_review td.product-name .wc-gzd-cart-item-name-wrapper { display: block; }
  body.woocommerce-checkout #order_review td.product-name .wc-gzd-cart-item-name-wrapper > * { display: inline; }
  body.woocommerce-checkout #order_review td.product-name .wc-gzd-cart-info,
  body.woocommerce-checkout #order_review td.product-name dl.variation { margin-left: 0; font-size: 14px; }
  /* the letter-spaced ZWISCHENSUMME header would wrap mid-word in its fixed column */
  body.woocommerce-checkout #order_review table.shop_table thead th { font-size: 10px; letter-spacing: .02em; white-space: nowrap; overflow-wrap: normal; }
}
@media (max-width: 360px) {
  /* nowrap 'Zwischensumme' fits its ~74px cell only below 10px — and the column
     itself needs a wider share of the fixed table at this width */
  body.woocommerce-checkout #order_review table.shop_table thead th { font-size: 9px; letter-spacing: 0; }
  body.woocommerce-checkout #order_review table.shop_table th.product-name,
  body.woocommerce-checkout #order_review table.shop_table td.product-name { width: 56%; }
  /* Divi's 80% .container leaves a 206px measure at 320 — the payment copy
     breaks into 2-4 word lines. Widen the shop pages' column on tiny screens. */
  body.woocommerce-checkout .container,
  body.woocommerce-cart .container,
  body.woocommerce-account .container { width: 92%; max-width: 92%; }
  body.woocommerce-checkout .woocommerce-checkout-review-order { padding-left: 16px; padding-right: 16px; }
  /* the legally required fine print may not be the least readable text on the page */
  body.woocommerce-cart .wc-gzd-cart-info,
  body.woocommerce-checkout .wc-gzd-cart-info,
  body.woocommerce-cart td.product-name .wc-gzd-cart-info,
  body.woocommerce-checkout #order_review .wc-gzd-cart-info { font-size: 14px; }
}

/* ============================================================
   == A: buttons ==
   ONE button system for the whole site — Divi module buttons AND
   the native WooCommerce / WordPress buttons that have no Divi
   module to hang a preset on (cart, checkout, account, the single
   add-to-cart, Woo notices).

   COLOUR lives in the Divi Design Presets (kv-build/seed-buttons.php:
   kv-btn / kv-btn-ghost / kv-btn-gold / kv-btn-neon). This block adds
   the four things Divi cannot express, and applies the same palette
   to the native markup:

     0. THE TYPEFACE — `--kv-btn-ff` below, hard-coded rather than read
        from the `--gvid-kv-font-sans` global variable. Divi emits font
        variables as `--gvid-…: '<esc_attr(value)>'`: it supplies the
        quotes, so a whole stack stored in one came back out as a single
        HTML-escaped family that matches nothing, and every call site's
        fallback list was skipped because the variable WAS defined. The
        hero CTA and the single add-to-cart rendered in the browser
        default serif while cart/checkout — pages that emit no Divi
        variable block at all — rendered in real Source Sans 3: two
        typefaces for one button system, on the two most important
        buttons on the site. The stored variables are repaired (bare
        family names now), but this system no longer depends on them.
     1. GEOMETRY — `button.decoration.spacing` is a verified Divi 5
        no-op for divi/button presets (saves, class lands, emits no
        padding rule), so Divi's own `.et_pb_button{padding:.3em 1em}`
        was leaving every brand button 32px tall against a 50px
        design spec. Padding/min-height are set here for both button
        families at once.
        ⚠ The ONE thing that can still outrank this block is a
        divi/button BUCKET DEFAULT preset with a body: Divi emits it as
        `.preset--…--default_wrapper .preset--…--default{padding-top:0
        !important}` (0-2-0) against this block's 0-1-1, and it did —
        the home hero primary rendered 174x50 beside a 188x65 ghost at
        390px. The cure is to empty the default preset
        (kv-build/seed-buttons.php unsets `kv-btn-default`), NOT to add
        specificity here: geometry has exactly one owner, this file.
     2. THE ETmodules ARROW — Divi ships `:after{content:"5";opacity:0}`
        on every button and reveals it on hover while shifting padding
        (`padding:.3em 2em .3em .7em`), so buttons visibly resize under
        the cursor. The KV design system (design/css/kv.css `.btn`) has
        no button icon; killed. That same rule is what rendered the
        loop-card plus circle EMPTY — our `+` was there all along,
        painted at opacity 0 and pulled 1em out of the box by
        `.woocommerce a.button:after{opacity:0;position:absolute;
        margin-left:-1em}`. Restored in §8.
     3. :focus-visible — no Divi field exists; keyboard users had no
        visible focus ring at all.

   SCOPE — `:is(body.woocommerce, body .woocommerce)` on purpose:
   cart/checkout/account wrap their markup in a `.woocommerce` DIV,
   but the Theme-Builder product template does not (WooCommerce only
   puts the class on <body> there), so a plain descendant selector
   silently missed the single add-to-cart — the site's single most
   important button was still a Divi-default outline in Open Sans.

   WCAG AA, measured from the real hex values (not eyeballed):
     navy #223246 / #fff .................... 13.02:1
     navy-deep #1b2736 / #fff ............... 15.11:1
     navy #223246 on parchment #f5f2ea ...... 11.64:1
     gold #b9a170 / navy text ................ 5.21:1
     gold-bright #cbb585 / navy text (hover) . 6.50:1
     neon #d2e000 / pink-deep #8d1338 ........ 6.31:1
     focus ring gold-deep #9c8456 ............ 3.59:1 on white, 3.79:1 on navy
   Three rest-state failures were found and corrected:
     - gold button's own-colour border on parchment 2.24:1 -> gold-deep 3.21:1
     - loop-card plus ring `--gcid-kv-line` on white 1.35:1 -> navy 13.02:1
     - "Weiter zur Kasse" wore Divi's stock blue #2ea3f2 outline -> navy fill
   Never white-on-gold-deep: that pairing is 3.59:1 and fails AA for text,
   which is why kv-btn-gold now BRIGHTENS on hover instead of darkening.
   ============================================================ */

:root {
  --kv-btn-py: 15px;
  --kv-btn-px: 30px;
  --kv-btn-h: 50px;      /* matches the product qty box in "== B: product ==" */
  --kv-btn-fs: 13px;
  /* TYPEFACE — deliberately NOT `var(--gvid-kv-font-sans, …)`.
     Divi emits its font variables as `--gvid-…: '<esc_attr(value)>'` — it adds
     the quotes itself — so a stack stored in that variable came back out as one
     quoted, HTML-escaped, nonexistent family, and every call site's fallback
     list was skipped because the variable WAS defined. Result: the two most
     important CTAs on the site (hero "WEINE ENTDECKEN", "IN DEN WARENKORB")
     rendered in the browser default serif while cart/checkout — pages that emit
     no Divi variable block — rendered in real Source Sans 3. Two typefaces, one
     button system. The stored variable is repaired (bare family name now), but
     this system does not depend on it: hard-coded here to the exact stack Divi
     itself emits for the button presets, so preset-styled and native
     WooCommerce buttons resolve to the same face under every cascade. */
  --kv-btn-ff: "Source Sans 3", Helvetica, Arial, Lucida, sans-serif;
}

/* ---------- 1. shared geometry (both button families) ---------- */
body .et_pb_button,
body .et_pb_button:hover,
body .wp-block-button__link,
:is(body.woocommerce, body .woocommerce) a.button:not(.kv-add),
:is(body.woocommerce, body .woocommerce) a.button:not(.kv-add):hover,
:is(body.woocommerce, body .woocommerce) button.button,
:is(body.woocommerce, body .woocommerce) button.button:hover,
:is(body.woocommerce, body .woocommerce) button.button:disabled,
:is(body.woocommerce, body .woocommerce) button.button:disabled[disabled],
:is(body.woocommerce, body .woocommerce) button.button.disabled,
:is(body.woocommerce, body .woocommerce) input.button,
:is(body.woocommerce, body .woocommerce) input.button:hover,
:is(body.woocommerce, body .woocommerce) input.button:disabled,
:is(body.woocommerce, body .woocommerce) #respond input#submit {
  font-family: var(--kv-btn-ff) !important;
  font-size: var(--kv-btn-fs) !important;
  font-weight: 600 !important;
  letter-spacing: .14em !important;
  text-transform: uppercase !important;
  line-height: 1.25 !important;
  padding: var(--kv-btn-py) var(--kv-btn-px) !important;
  min-height: var(--kv-btn-h);
  border-width: 1px !important;
  border-style: solid !important;
  border-radius: var(--gvid-kv-radius, 3px) !important;
  text-align: center;
  /* German CTA labels are long ("Jetzt zahlungspflichtig bestellen", "Neues
     Kundenkonto anlegen") and several of them have to wrap in a narrow column
     on a phone. Balanced breaking keeps the lines even instead of dropping a
     single orphaned word under a full one, so a wrapped button still reads as
     the same object as an unwrapped one. Ignored by browsers that lack it. */
  text-wrap: balance;
  transition: background-color .3s var(--kv-ease, ease), border-color .3s var(--kv-ease, ease),
              color .3s var(--kv-ease, ease), transform .3s var(--kv-ease, ease) !important;
}
/* `.alt` (the WooCommerce "primary" flag) carries its own Divi rule at
   `.woocommerce button.button.alt{line-height:1.7em!important}` — 0-3-1, one
   notch above the block above — which left "Jetzt zahlungspflichtig bestellen"
   4px taller than every other button. Same declarations, enough specificity. */
:is(body.woocommerce, body .woocommerce) :is(a, button, input).button.alt,
:is(body.woocommerce, body .woocommerce) :is(a, button, input).button.alt:hover,
:is(body.woocommerce, body .woocommerce) button.button.alt:disabled,
:is(body.woocommerce, body .woocommerce) button.button.alt:disabled[disabled],
:is(body.woocommerce, body .woocommerce) button.button.alt.disabled {
  font-size: var(--kv-btn-fs) !important;
  line-height: 1.25 !important;
  padding: var(--kv-btn-py) var(--kv-btn-px) !important;
  border-width: 1px !important;
}

/* anchors/buttons centre their label in the 50px box; <input> cannot be a flex
   container, but padding + min-height already give it the same silhouette */
body .et_pb_button,
body .wp-block-button__link,
:is(body.woocommerce, body .woocommerce) a.button:not(.kv-add),
:is(body.woocommerce, body .woocommerce) button.button {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
}

/* the design system lifts on hover instead of growing an arrow */
body .et_pb_button:hover,
:is(body.woocommerce, body .woocommerce) a.button:not(.kv-add):hover,
:is(body.woocommerce, body .woocommerce) button.button:not(:disabled):hover,
:is(body.woocommerce, body .woocommerce) input.button:not(:disabled):hover { transform: translateY(-1px); }

/* ---------- 2. kill Divi's ETmodules arrow ---------- */
body .et_pb_button::after,
body .et_pb_button::before,
body .wp-block-button__link::after,
:is(body.woocommerce, body .woocommerce) a.button:not(.kv-add)::after,
:is(body.woocommerce, body .woocommerce) a.button:not(.kv-add)::before,
:is(body.woocommerce, body .woocommerce) button.button::after,
:is(body.woocommerce, body .woocommerce) button.button::before,
:is(body.woocommerce, body .woocommerce) input.button::after,
:is(body.woocommerce, body .woocommerce) input.button::before,
:is(body.woocommerce, body .woocommerce) #respond input#submit::after {
  content: none !important; display: none !important;
}
/* Divi 5 re-adds the glyph per MODULE from an id-carrying selector
   (`.et-db #et-boc .et-l .et_pb_wc_add_to_cart_0_tb_body .button::after{
   content:attr(data-icon)!important}`), which no class-only rule can outrank —
   so this one mirrors Divi's own id and adds a class to win on specificity.
   Scoped to the WooCommerce button modules; Divi module buttons that WANT an
   icon (none in this design) are untouched elsewhere. */
.et-db #et-boc .et-l [class*="et_pb_wc_"] .button.et_pb_button::after,
.et-db #et-boc .et-l [class*="et_pb_wc_"] .button.et_pb_button::before {
  content: none !important; display: none !important;
}

/* ---------- 3. keyboard focus (WCAG 2.4.7 / 2.4.11) ---------- */
body .et_pb_button:focus-visible,
body .wp-block-button__link:focus-visible,
:is(body.woocommerce, body .woocommerce) a.button:focus-visible,
:is(body.woocommerce, body .woocommerce) button.button:focus-visible,
:is(body.woocommerce, body .woocommerce) input.button:focus-visible,
:is(body.woocommerce, body .woocommerce) #respond input#submit:focus-visible,
.woocommerce ul.products li.product a.button.kv-add:focus-visible {
  outline: 2px solid var(--gcid-kv-gold-deep, #9c8456) !important;
  outline-offset: 3px;
}
/* `outline-offset:3px` draws the ring OUTSIDE the button, so the colour it has
   to survive is the section ground, not the button's own fill. Gold-deep clears
   3:1 on every ground the design uses — parchment 3.21, offwhite 3.44, white
   3.59, navy-deep 4.77 — except one: on pink-deep #8d1338 it measures 2.56:1,
   so keyboard focus on the two sOur / club CTAs ("Zur sOur-Kollektion",
   "Jetzt beitreten") was effectively invisible. White on that ground is 9.24:1.
   Scoped to the pink section rather than the neon preset: the ground is what
   fails, so the ground is what should decide. */
.preset--module--divi-section--kv-sec-pink :is(a, button, input):is(
  .et_pb_button, .button, .wp-block-button__link):focus-visible {
  outline-color: #fff !important;
}

/* ---------- 4. secondary (navy outline) is the baseline ----------
   Deliberately low specificity: any Divi preset class
   (`preset--module--divi-button--kv-*`, 0-4-1 with !important on colour)
   still wins on module buttons, so the presets stay the source of truth. */
body .et_pb_button,
:is(body.woocommerce, body .woocommerce) a.button:not(.kv-add),
:is(body.woocommerce, body .woocommerce) button.button,
:is(body.woocommerce, body .woocommerce) button.button:disabled,
:is(body.woocommerce, body .woocommerce) button.button:disabled[disabled],
:is(body.woocommerce, body .woocommerce) button.button.disabled,
:is(body.woocommerce, body .woocommerce) input.button,
:is(body.woocommerce, body .woocommerce) #respond input#submit {
  background-color: rgba(0, 0, 0, 0);
  border-color: var(--gcid-kv-navy, #223246);
  color: var(--gcid-kv-navy, #223246);
}
body .et_pb_button:hover,
:is(body.woocommerce, body .woocommerce) a.button:not(.kv-add):hover,
:is(body.woocommerce, body .woocommerce) button.button:not(:disabled):hover,
:is(body.woocommerce, body .woocommerce) input.button:not(:disabled):hover,
:is(body.woocommerce, body .woocommerce) #respond input#submit:hover {
  background-color: var(--gcid-kv-navy, #223246);
  border-color: var(--gcid-kv-navy, #223246);
  color: #fff;
}

/* ---------- 5. primary (navy fill) ----------
   Every "commit" step of the shop funnel wears the same shape, so the eye
   lands in the same place from product page to order confirmation.
   `body button.single_add_to_cart_button` intentionally needs no
   `.woocommerce` ancestor — see the SCOPE note in the block header. */
body button.single_add_to_cart_button,
body .wp-block-button__link,
:is(body.woocommerce, body .woocommerce) a.button.alt,
:is(body.woocommerce, body .woocommerce) button.button.alt,
:is(body.woocommerce, body .woocommerce) input.button.alt,
:is(body.woocommerce, body .woocommerce) #respond input#submit.alt,
:is(body.woocommerce, body .woocommerce) a.checkout-button,
:is(body.woocommerce, body .woocommerce) #place_order,
:is(body.woocommerce, body .woocommerce) button.button.woocommerce-form-login__submit,
:is(body.woocommerce, body .woocommerce) button.button.woocommerce-form-register__submit,
:is(body.woocommerce, body .woocommerce) .return-to-shop a.button {
  background-color: var(--gcid-kv-navy, #223246);
  border-color: var(--gcid-kv-navy, #223246);
  color: #fff;
}
body button.single_add_to_cart_button:hover,
body .wp-block-button__link:hover,
:is(body.woocommerce, body .woocommerce) a.button.alt:hover,
:is(body.woocommerce, body .woocommerce) button.button.alt:not(:disabled):hover,
:is(body.woocommerce, body .woocommerce) input.button.alt:not(:disabled):hover,
:is(body.woocommerce, body .woocommerce) #respond input#submit.alt:hover,
:is(body.woocommerce, body .woocommerce) a.checkout-button:hover,
:is(body.woocommerce, body .woocommerce) #place_order:hover,
:is(body.woocommerce, body .woocommerce) button.button.woocommerce-form-login__submit:hover,
:is(body.woocommerce, body .woocommerce) button.button.woocommerce-form-register__submit:hover,
:is(body.woocommerce, body .woocommerce) .return-to-shop a.button:hover {
  background-color: var(--gcid-kv-navy-deep, #1b2736);
  border-color: var(--gcid-kv-navy-deep, #1b2736);
  color: #fff;
}

/* the two decisive funnel steps own their whole column */
:is(body.woocommerce, body .woocommerce) a.checkout-button,
:is(body.woocommerce, body .woocommerce) #place_order { width: 100%; }

/* ---------- 6. inverse (inside Divi's navy Woo notices) ----------
   Divi's customizer paints .woocommerce-message/-info/-error navy
   (`background:#223246!important`), so an outline button in there is
   navy-on-navy — invisible. White fill, navy label: 13.02:1 both ways. */
:is(body.woocommerce, body .woocommerce) :is(.woocommerce-message, .woocommerce-info, .woocommerce-error) a.button,
:is(body.woocommerce, body .woocommerce) :is(.woocommerce-message, .woocommerce-info, .woocommerce-error) button.button {
  background-color: #fff;
  border-color: #fff;
  color: var(--gcid-kv-navy, #223246);
}
:is(body.woocommerce, body .woocommerce) :is(.woocommerce-message, .woocommerce-info, .woocommerce-error) a.button:hover,
:is(body.woocommerce, body .woocommerce) :is(.woocommerce-message, .woocommerce-info, .woocommerce-error) button.button:hover {
  background-color: var(--gcid-kv-parchment, #f5f2ea);
  border-color: var(--gcid-kv-parchment, #f5f2ea);
  color: var(--gcid-kv-navy, #223246);
}

/* ---------- 7. disabled ----------
   "Warenkorb aktualisieren" ships disabled until a quantity changes; it must
   read as the same button, dimmed — not as a different grey control. */
:is(body.woocommerce, body .woocommerce) a.button.disabled,
:is(body.woocommerce, body .woocommerce) button.button:disabled,
:is(body.woocommerce, body .woocommerce) button.button.disabled,
:is(body.woocommerce, body .woocommerce) input.button:disabled,
body .et_pb_button:disabled {
  opacity: .45; cursor: not-allowed; transform: none !important;
}

/* ---------- 8. loop-card plus circle ----------
   Divi's `.woocommerce a.button:after{opacity:0;position:absolute;
   margin-left:-1em}` is what emptied this circle. Reinstate the glyph and
   swap the 1.35:1 `--gcid-kv-line` ring for the navy ring the design file
   specifies (design/Produktkarte - Legal.html `.wcard__add`), 13.02:1. */
.woocommerce ul.products li.product a.button.kv-add {
  border-color: var(--gcid-kv-navy, #223246);
  color: var(--gcid-kv-navy, #223246);
  width: 48px; height: 48px;
  /* the circle carries no text of its own (font-size:0, the `+` lives in
     ::after) but it still inherits a family — keep it the system's, so a DOM
     audit of every button on the site returns exactly one typeface */
  font-family: var(--kv-btn-ff) !important;
}
.woocommerce ul.products li.product a.button.kv-add::after {
  position: static !important;
  opacity: 1 !important;
  margin-left: 0 !important;
  margin-top: -2px;
  display: block !important;
  color: var(--gcid-kv-navy, #223246) !important;
  transition: none;
}
/* Divi's customizer ships an ID-carrying twin of its Woo link colour
   (`.et-db #et-boc .et-l .woocommerce a.button{color:#223246}`) that no
   class-only rule can outrank — so the circle's own :hover/.added rules never
   flipped the glyph to white, and hovering produced a navy `+` on a navy fill
   (1:1). Painting the pseudo-element directly sidesteps the id war. */
.woocommerce ul.products li.product a.button.kv-add:hover::after,
.woocommerce ul.products li.product a.button.kv-add.added::after { color: #fff !important; }
/* `.loading` is given the same navy fill as :hover and .added on purpose. The
   AJAX add is a three-frame sequence — press, spin, tick — and it only reads as
   one gesture if the disc stays navy through all three. It also makes the
   spinner's colour decidable: the ring used to be navy, which is invisible on
   the navy fill the pointer had already produced (the state was reached by
   hover in practice, so the spinner never appeared at all), while a white ring
   would have been invisible on the white rest fill a keyboard press leaves. */
.woocommerce ul.products li.product a.button.kv-add:hover,
.woocommerce ul.products li.product a.button.kv-add.loading,
.woocommerce ul.products li.product a.button.kv-add.added { background: var(--gcid-kv-navy, #223246); }
.woocommerce ul.products li.product a.button.kv-add.loading::after {
  border-color: #fff !important; border-top-color: transparent !important;
}
/* WooCommerce core drops every `.loading` button to `opacity:.25`. On a normal
   button that is a legible dimming; on this 48px disc it washed the navy fill
   out to a pale grey and took the white spinner with it (~1.3:1) — the one
   moment the control has to prove it heard the click, and it went blank.
   Full opacity for the disc; .6 for the rest of the family, which still reads
   as "busy" while keeping white-on-navy above 4.5:1. */
:is(body.woocommerce, body .woocommerce) a.button.loading,
:is(body.woocommerce, body .woocommerce) button.button.loading,
:is(body.woocommerce, body .woocommerce) input.button.loading { opacity: .6; }
.woocommerce ul.products li.product a.button.kv-add.loading { opacity: 1; }
.woocommerce ul.products li.product:hover a.button.kv-add {
  border-color: var(--gcid-kv-navy, #223246);
  box-shadow: 0 6px 16px -3px rgba(20, 32, 54, .26);
}
/* The `+` above had to be authored `!important` to beat Divi's ETmodules glyph
   — which also blocked the AJAX feedback states from ever swapping it, so the
   spinner drew a `+` inside its ring and the success tick never appeared.
   Same weapon, later in the cascade. */
.woocommerce ul.products li.product a.button.kv-add.loading::after {
  content: "" !important; opacity: 1 !important; font-size: 0 !important;
}
.woocommerce ul.products li.product a.button.kv-add.added::after {
  content: "\2713" !important; font-size: 20px !important; opacity: 1 !important;
}

/* ---------- 9. contextual grounds ----------
   The four presets are tuned for the light grounds they mostly sit on. Two
   section colours break them, and both were measured live, not guessed:

   PINK #b71f4a is a MID tone — dark enough to swallow navy (2.00:1), light
   enough to swallow gold (2.58:1). Only kv-btn-neon is built for it (6.31:1).
   NAVY #223246 / #141c28 swallow the navy fill and the navy outline outright
   (1.00:1): /weingut/ "Das Team kennenlernen" only read at rest because that
   module overrides its colours by hand, and collapsed into a navy-on-navy
   block the instant you hovered it.

   Both are fixed by inverting to white, which clears 3:1 on either ground.
   ⚠ SPECIFICITY: the preset CSS marks `color` (and font-size/letter-spacing)
   `!important` at `body #page-container .et_pb_section .preset--…` = 0-4-2, so
   a colour override has to out-specify that, not merely repeat !important.
   Border/background are NOT !important in the preset, hence the two tiers. */

/* border + background: preset declarations here are plain, so class scope wins */
.preset--module--divi-section--kv-sec-pink :is(
  .preset--module--divi-button--kv-btn,
  .preset--module--divi-button--kv-btn-gold,
  .preset--module--divi-button--kv-btn-ghost) { border-color: #fff !important; }
:is(.preset--module--divi-section--kv-sec-navy,
    .preset--module--divi-section--kv-sec-navy-deep) :is(
  .preset--module--divi-button--kv-btn,
  .preset--module--divi-button--kv-btn-ghost) { border-color: rgba(255, 255, 255, .6) !important; }

/* label colour: must out-specify the preset's own !important rule (0-4-2) */
body #page-container .et_pb_section.preset--module--divi-section--kv-sec-pink
  .et_pb_button.preset--module--divi-button--kv-btn-ghost,
body #page-container .et_pb_section:is(
    .preset--module--divi-section--kv-sec-navy,
    .preset--module--divi-section--kv-sec-navy-deep) .et_pb_button:is(
    .preset--module--divi-button--kv-btn,
    .preset--module--divi-button--kv-btn-ghost) {
  color: #fff !important;
}
body #page-container .et_pb_section.preset--module--divi-section--kv-sec-pink
  .et_pb_button.preset--module--divi-button--kv-btn-ghost:hover {
  background-color: #fff !important;
  border-color: #fff !important;
  color: var(--gcid-kv-pink-deep, #8d1338) !important;
}
body #page-container .et_pb_section:is(
    .preset--module--divi-section--kv-sec-navy,
    .preset--module--divi-section--kv-sec-navy-deep) .et_pb_button:is(
    .preset--module--divi-button--kv-btn,
    .preset--module--divi-button--kv-btn-ghost):hover {
  background-color: #fff !important;
  border-color: #fff !important;
  color: var(--gcid-kv-navy, #223246) !important;
}

/* ---------- 10. the product page's buy row ----------
   "In den Warenkorb" is the single most important button on the site and was
   the only one that wasn't 50px tall. `.kv-pd-buy .cart` is a flex row with
   `align-items:stretch`, and the quantity <input> beside it keeps Divi's stock
   form padding (16 + 27.2 + 16 = 59.2px, +2px on the wrapper's border = 61.2),
   so the row dragged the CTA 11px past every other button on the site — the
   one place a visitor compares a button against nothing but itself.
   Pin the input to the button height rather than letting Divi's form padding
   decide it; the two controls then read as one 50px unit. */
.kv-pd-buy .cart .quantity input.qty {
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  min-height: 0;
  height: calc(var(--kv-btn-h) - 2px);
  line-height: calc(var(--kv-btn-h) - 2px);
}
body button.single_add_to_cart_button { min-height: var(--kv-btn-h); }

/* ---------- 11. schwarm dock chips ----------
   The dock's secondary chip sat on a 16 %-white hairline over the near-black
   canvas: 1.65:1, i.e. no perceivable control boundary. 38 % clears 3:1
   without turning the chip into a hard-edged box over the animation. */
.kv-schwarm-btn:not(.kv-schwarm-btn--primary) { border-color: rgba(255, 255, 255, .38); }
.kv-schwarm-btn:not(.kv-schwarm-btn--primary):hover { border-color: rgba(255, 255, 255, .62); }
.kv-schwarm-btn:focus-visible {
  outline: 2px solid var(--gcid-kv-gold-bright, #cbb585); outline-offset: 3px;
}

@media (max-width: 600px) {
  /* narrower gutter so a long German label ("Neues Kundenkonto anlegen") still
     fits without the letter-spacing collapsing */
  :root { --kv-btn-px: 22px; }
  /* cart/account actions go full width; the product page's add-to-cart is
     deliberately excluded — it shares its row with the quantity box (see
     "== B: product ==" .kv-pd-buy) and must stay a flex sibling. */
  :is(body.woocommerce, body .woocommerce) .woocommerce-cart-form .actions .button,
  :is(body.woocommerce, body .woocommerce) .wc-proceed-to-checkout a.button,
  :is(body.woocommerce, body .woocommerce) button.button.woocommerce-form-login__submit,
  :is(body.woocommerce, body .woocommerce) button.button.woocommerce-form-register__submit { width: 100%; }
  /* "Gutschein anwenden" was 141px wide with its label broken over two lines
     and 65px tall, sitting directly above a 50px "Warenkorb aktualisieren".
     WooCommerce pins it at `width:48%` from a 0-5-1 selector
     (`.woocommerce-cart table.cart td.actions .coupon .button`) that outranks
     the full-width rule above, so the German label — which is simply longer
     than the English one Woo sized that percentage for — had nowhere to go.
     Given its own row the cart's three actions read as three instances of one
     button instead of two buttons and an accident. */
  :is(body.woocommerce, body .woocommerce) .woocommerce-cart-form .actions .coupon .button { width: 100% !important; }
}

/* ============================================================
   == E: ajax cart ==
   Header cart-icon badge. Divi 5's menu module renders
   `.et_pb_menu__cart-count` natively once "Show Cart Quantity" is
   on (header layout 19643, Main Menu module) — this just turns
   that plain inline text into a small gold counter pinned to the
   cart glyph, hidden while the cart is empty, and gives it a bump
   on change (class toggled by assets/js/kv-cart.js). Divi renders
   one cart icon per menu module (mobile reuses the same element,
   shown/hidden by breakpoint, not re-rendered) so scoping to
   .kv-nav-bar — the section wrapping the header's Main Menu
   module — covers it everywhere it appears.
   ============================================================ */

.kv-nav-bar a.et_pb_menu__cart-button {
  position: relative;
}
.kv-nav-bar a.et_pb_menu__icon__with_count:after {
  margin-right: 0; /* badge is pinned absolutely now, reclaim Divi's default gap */
}
.et_pb_menu__cart-count {
  position: absolute;
  top: -7px;
  right: -9px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--gcid-kv-gold, #b9a170);
  color: var(--gcid-kv-navy-deep, #0c1626);
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif);
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  border-radius: 999px;
  pointer-events: none;
  transform: scale(1);
  transition: transform .3s cubic-bezier(.34,1.56,.64,1);
}
.et_pb_menu__cart-count.kv-cart-count--zero {
  display: none;
}
.et_pb_menu__cart-count.kv-cart-bump {
  transform: scale(1.35);
}
/* No-JS fallback: nothing hides the "0" badge before kv-cart.js runs, and
   that is fine — .kv-js gates the opposite direction (JS-only reveals)
   elsewhere in this file, but a numeral badge reading "0" is not broken UI. */

/* ============================================================
   == F: launcher ==
   "Das Regal" — the shared quick-launcher for the five guided
   shop-start pages (kv-shop-guided-v1…v5). Markup comes from
   inc/launcher.php, behaviour from assets/js/kv-launcher.js.

   Three pieces:
     .kv-launcher-handle  the gold handle JS clones into the navy
                          nav bar, before the cart icon. It is the
                          ONLY filled colour field in that bar —
                          navy-on-navy tested at ~2.2:1 and read as
                          a sixth menu item, so it is now solid gold
                          with navy type at 7.51:1.
     .kv-launcher-open    the class the two in-page Divi Button
                          modules carry (hero twin, mid-page
                          reprise). No styling here — they keep the
                          shop's own button presets.
     #kv-launcher         the panel: a hanging dropdown at ≥1025px,
                          a real modal sheet below that, a bottom
                          sheet on phones.

   Deliberately NOT a fixed badge in a screen corner: nothing here
   uses position:fixed with a bottom/right offset, so the launcher
   can never sit on top of the page's own content or a CTA.
   ============================================================ */

/* ---- M1: the handle ------------------------------------------------ */

.kv-launcher-handle-slot {
  position: relative;
  display: inline-flex;
  flex: none;
  width: 286px;
  min-height: 40px;
  margin-right: 18px;
}
.kv-launcher-handle {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  box-sizing: border-box;
  width: 100%;
  /* min-height, never height: the label is never allowed to shrink below 14px
     (round-9 rule), so on the widths where four words at 14px do not fit on one
     line the handle grows a second line instead of setting 11–12px type in the
     nav bar. Everywhere there IS room it stays exactly 40px. */
  min-height: 40px;
  padding: 6px 14px 6px 12px;
  margin: 0;
  border: 0;
  border-radius: 8px;
  background: var(--gcid-kv-gold-bright, #cbb585);
  color: var(--gcid-kv-navy-deep, #1b2736);
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: .005em;
  text-align: left;
  cursor: pointer;
  box-shadow: 0 2px 0 rgba(122, 101, 58, .55);
  transition: background-color .25s ease, color .25s ease, transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .25s ease;
}
.kv-launcher-handle:hover {
  background: var(--gcid-kv-gold, #b9a170);
}
.kv-launcher-handle:focus-visible {
  outline: 2px solid var(--gcid-kv-offwhite, #fafaf8);
  outline-offset: 2px;
}
.kv-launcher-handle.is-open {
  background: var(--gcid-kv-navy-deep, #1b2736);
  color: var(--gcid-kv-gold-bright, #cbb585);
  box-shadow: inset 0 0 0 1.5px var(--gcid-kv-gold-bright, #cbb585);
}
.kv-launcher__bird {
  width: 22px;
  height: 22px;
  flex: none;
  transform: scaleX(-1);
}
/* Wraps rather than ellipses. An ellipsis on a four-word label costs the last
   word ("…drei Fla…"), and shrinking the type to make it fit is what put 12px
   in the phone bar; two lines of 14px keeps both the sentence and the size. */
.kv-launcher-handle__label {
  flex: 1 1 auto;
  min-width: 0;
  white-space: normal;
  text-wrap: balance;
}
.kv-launcher-handle__minis {
  display: flex;
  gap: 3px;
  flex: none;
}
.kv-launcher-handle__minis i {
  width: 18px;
  height: 12px;
  border-radius: 2px;
  border: 1px dashed rgba(27, 39, 54, .55);
}
.kv-launcher.is-answered ~ * .kv-launcher-handle__minis i,
.kv-launcher-handle.is-filled .kv-launcher-handle__minis i {
  border-style: solid;
  background: var(--gcid-kv-navy-deep, #1b2736);
  border-color: var(--gcid-kv-navy-deep, #1b2736);
}
.kv-launcher-handle.is-open .kv-launcher-handle__minis i {
  border-color: rgba(203, 181, 133, .6);
}

/* Docked state. The nav bar is position:sticky but its Theme Builder wrapper
   is only as tall as the header itself, so the bar has no room to stick in and
   scrolls off the top of every page on this site. Rather than pretend
   otherwise, the handle detaches the moment the bar's bottom edge passes the
   viewport top and hangs off that edge as a navy tab — same x-position it had
   in the bar (JS measures the slot it leaves behind), 40px tall, flush against
   the top. That is what keeps "reachable at every scroll depth" true; it is
   never a badge floating over the page's own content. */
/* Empty until the handle docks into it; a direct child of <body> so the docked
   handle's position:fixed resolves against the viewport and not against the
   transformed nav bar. Takes no space of its own. */
.kv-launcher-dock {
  height: 0;
}
/* On phone and tablet the docked handle is a small pill floating over whatever
   happens to be under it — at 390 it landed on the top edge of a product photo,
   which breaks the brief's "never blocks content". A pill parked on an image
   blocks content; a bar the page scrolls under is chrome. So below 1025 the dock
   container becomes that bar: same navy as the nav it replaces, sized from the
   handle's own offset so it works whatever a page's own CSS does to `top`. */
@media only screen and (max-width: 1024px) {
  html.kv-launcher-docked .kv-launcher-dock {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: var(--kv-dock-h, 62px);
    z-index: 78;
    background: var(--gcid-kv-navy-deep, #1b2736);
    box-shadow: 0 10px 26px -18px rgba(11, 26, 45, .95);
  }
  .kv-launcher-handle.is-docked {
    box-shadow: none;
  }
}
.kv-launcher-handle.is-docked {
  position: fixed;
  top: 0;
  left: var(--kv-handle-x, 24px);
  width: var(--kv-handle-w, 286px);
  /* --kv-handle-w is frozen while docked (the slot it was measured from is
     empty), so an orientation change mid-page could otherwise leave a tab wider
     than the phone it is now on. */
  max-width: calc(100vw - 28px);
  z-index: 80;
  background: var(--gcid-kv-navy, #223246);
  color: var(--gcid-kv-gold-bright, #cbb585);
  border-radius: 0 0 10px 10px;
  box-shadow: 0 8px 22px rgba(11, 26, 45, .35);
}
.kv-launcher-handle.is-docked .kv-launcher-handle__minis i {
  border-color: rgba(203, 181, 133, .6);
}
.kv-launcher-handle.is-docked.is-open {
  background: var(--gcid-kv-navy-deep, #1b2736);
}

/* One-time hint tag after the hero twin scrolls away. It is a child of the
   handle, so it anchors to the slot while the handle is inline (the slot is the
   nearest positioned ancestor) and to the handle itself once that is fixed —
   either way it hangs directly under the thing it is pointing at. */
.kv-launcher-hint {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 70;
  margin: 0;
  padding: 6px 11px;
  border-radius: 6px;
  background: var(--gcid-kv-offwhite, #fafaf8);
  color: var(--gcid-kv-navy, #223246);
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif);
  font-size: 12.5px;
  line-height: 1.3;
  white-space: nowrap;
  box-shadow: 0 10px 26px -14px rgba(11, 26, 45, .6);
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity .5s ease, transform .5s ease;
  pointer-events: none;
}
.kv-launcher-hint.is-in {
  opacity: 1;
  transform: none;
}

/* ---- Panel shell --------------------------------------------------- */

.kv-launcher[hidden] { display: none; }

.kv-launcher__scrim {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgba(11, 26, 45, .55);
  backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity .28s ease;
}
.kv-launcher.is-open .kv-launcher__scrim { opacity: 1; }

/* The panel is a THREE-BAND object, not a scrolling card:
     .kv-launcher__ask     navy field — the question and the four answers
     .kv-launcher__scroll  the only part that moves
     .kv-launcher__foot    parchment band — browse-all + the shipping promise
   It used to be one 595px box with `overflow-y:auto` over 920px of content, so
   the moment the visitor answered, the price was sliced mid-glyph, the "+" sat
   311px below the edge and the browse-all escape hatch — the whole point of the
   piece — was 500px past it. Pinning the two bands puts the payoff and the exit
   permanently on screen and leaves the shelf as the thing that scrolls. */
.kv-launcher__panel {
  position: fixed;
  z-index: 95;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  background: var(--gcid-kv-offwhite, #fafaf8);
  color: var(--gcid-kv-ink, #3a3d42);
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif);
  box-shadow: 0 30px 70px -30px rgba(11, 26, 45, .6);
  /* NOT `hidden`: the notch hangs 7px above the panel's own top edge, and the
     two bands round their own corners, so there is nothing left to clip. */
  overflow: visible;
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity .28s ease, transform .32s cubic-bezier(.22,.61,.36,1);
}
.kv-launcher.is-open .kv-launcher__panel {
  opacity: 1;
  transform: none;
}

/* The notch. It is the same navy as the ask field above it, so at ≥1025 — where
   the panel is a scrimless dropdown — the panel reads as something the handle
   pushed out, not as an unrelated card that happens to have appeared. JS puts it
   on the handle's centre via --kv-arrow-x. */
.kv-launcher__arrow {
  position: absolute;
  top: -7px;
  right: calc(var(--kv-arrow-x, 60px) - 7px);
  width: 14px;
  height: 14px;
  background: var(--gcid-kv-navy-deep, #1b2736);
  transform: rotate(45deg);
  border-radius: 2px;
  display: none;
}

.kv-launcher__ask {
  flex: none;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--gcid-kv-navy-deep, #1b2736);
  border-bottom: 2px solid var(--gcid-kv-gold, #b9a170);
  color: var(--gcid-kv-offwhite, #fafaf8);
}

.kv-launcher__scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.kv-launcher__close {
  position: absolute;
  top: 0;
  right: 0;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid rgba(203, 181, 133, .5);
  border-radius: 999px;
  background: transparent;
  color: var(--gcid-kv-gold-bright, #cbb585);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  transition: background-color .25s ease, border-color .25s ease;
}
.kv-launcher__close:hover {
  background: rgba(203, 181, 133, .16);
  border-color: var(--gcid-kv-gold-bright, #cbb585);
}
.kv-launcher__close:focus-visible {
  outline: 2px solid var(--gcid-kv-gold-bright, #cbb585);
  outline-offset: 2px;
}

/* Same bird, same gold, same functional caps as the handle — so the field the
   panel opens with is visibly the same object the visitor pressed. */
.kv-launcher__mark {
  margin: 0 0 -6px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding-right: 44px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--gcid-kv-gold-bright, #cbb585);
}
.kv-launcher__mark-bird {
  width: 17px;
  height: 17px;
  flex: none;
  transform: scaleX(-1);
}

.kv-launcher__head {
  margin: 0;
  padding-right: 44px;
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", Georgia, serif);
  font-size: 29px;
  font-weight: 500;
  line-height: 1.05;
  color: var(--gcid-kv-offwhite, #fafaf8);
}
.kv-launcher__sub {
  margin: -4px 0 0;
  font-size: 14.5px;
  line-height: 1.5;
  color: rgba(250, 250, 248, .78);
}
.kv-launcher__n {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--gcid-kv-gold-bright, #cbb585);
}

/* ---- Chips --------------------------------------------------------- */

.kv-launcher__chips {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
}
/* Answers are a control, not prose: they take the functional voice — the same
   uppercase, letter-spaced 700 sans the Fach eyebrows and the site's own
   button system already use — so the serif is left to carry the one emotional
   line at the top and nothing competes with it. */
.kv-launcher__chip {
  min-height: 44px;
  padding: 10px 10px;
  border: 1px solid rgba(203, 181, 133, .42);
  border-radius: 999px;
  background: transparent;
  color: var(--gcid-kv-offwhite, #fafaf8);
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  line-height: 1.2;
  cursor: pointer;
  transition: background-color .3s ease, border-color .3s ease, color .3s ease;
}
.kv-launcher__chip:hover {
  border-color: var(--gcid-kv-gold-bright, #cbb585);
  background: rgba(203, 181, 133, .14);
}
.kv-launcher__chip:focus-visible {
  outline: 2px solid var(--gcid-kv-gold-bright, #cbb585);
  outline-offset: 2px;
}
.kv-launcher__chip[aria-checked="true"] {
  background: var(--gcid-kv-gold-bright, #cbb585);
  border-color: var(--gcid-kv-gold-bright, #cbb585);
  color: var(--gcid-kv-navy-deep, #1b2736);
}

/* ---- Drawer -------------------------------------------------------- */

.kv-launcher__drawer {
  border-bottom: 1px solid var(--gcid-kv-line-soft, #efe9dc);
  padding: 8px 0 12px;
}
.kv-launcher__empty[hidden],
.kv-launcher__set[hidden] { display: none; }

/* The three bottles are on the table BEFORE the question is answered — the page
   opens with its own lead Fach rather than with three dashed rectangles saying
   "drei Plätze frei". This one line is what keeps that honest: it says these are
   the house's suggestion, and it disappears the moment the visitor's own answer
   replaces them. */
.kv-launcher__preview {
  margin: 0 0 10px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--gcid-kv-gold-deep, #9c8456);
}
.kv-launcher.is-answered .kv-launcher__preview { display: none; }

.kv-launcher__empty-eyebrow {
  margin: 0 0 6px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--gcid-kv-gold-deep, #9c8456);
}
.kv-launcher__empty-line {
  margin: 0;
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", Georgia, serif);
  font-size: 19px;
  font-style: italic;
  line-height: 1.35;
  color: var(--gcid-kv-navy, #223246);
}

.kv-launcher__curated {
  margin: 0 0 10px;
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", Georgia, serif);
  font-size: 19px;
  font-style: italic;
  line-height: 1.35;
  color: var(--gcid-kv-navy, #223246);
}
.kv-launcher__bottles {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
.kv-launcher__bottle {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 10px 10px 12px;
  border: 1px solid var(--gcid-kv-line, #e3ddcf);
  border-radius: 3px;
  background: #fff;
}
.kv-launcher__bottle-link {
  display: flex;
  flex-direction: column;
  gap: 2px;
  color: inherit;
  text-decoration: none;
}
/* Fixed height, not 3/4 of whatever the column happens to be: at 720px wide the
   aspect ratio made each shot 261px tall, which alone pushed the price and the
   "+" past the panel's bottom edge. The bottles are `object-fit:contain`, so a
   shorter frame crops nothing. */
.kv-launcher__bottle-shot {
  display: block;
  height: 100px;
  background: var(--gcid-kv-parchment, #f5f2ea);
  margin-bottom: 8px;
  overflow: hidden;
}
.kv-launcher__bottle-shot img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  mix-blend-mode: multiply;
  display: block;
}
.kv-launcher__bottle-line {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--gcid-kv-gold-deep, #9c8456);
}
.kv-launcher__bottle-name {
  font-family: var(--gvid-kv-font-serif, "Cormorant Garamond", Georgia, serif);
  font-size: 18px;
  line-height: 1.15;
  color: var(--gcid-kv-navy, #223246);
}
.kv-launcher__bottle-meta,
.kv-launcher__bottle-grund {
  font-size: 11.5px;
  color: var(--gcid-kv-muted, #7c7e82);
  line-height: 1.4;
}
/* The Germanized fine print is legally required next to every price, so it can
   never be dropped — it is set as small as it stays readable instead, because
   at 11.5px it wrapped to three lines and was the single tallest thing between
   the price and the bottom of the card. */
.kv-launcher__bottle-legal {
  font-size: 10px;
  color: var(--gcid-kv-muted, #7c7e82);
  line-height: 1.35;
}
.kv-launcher__bottle-price {
  font-size: 16px;
  font-weight: 600;
  color: var(--gcid-kv-navy, #223246);
}
.kv-launcher__bottle-price del { opacity: .5; font-weight: 400; }
.kv-launcher__bottle-legal { margin-top: 5px; }

/* The "+" is WooCommerce's own loop add-to-cart anchor (.kv-add), which the
   product-loop CSS only styles inside `.woocommerce ul.products`. Same circle,
   restated for this scope — one button system, not a new one.
   The selector carries `a.button` for one reason: these five pages get the
   `woocommerce woocommerce-page` body classes, and Divi core ships
   `.woocommerce-page a.button{font-size:20px;padding:.3em 1em}` at (0,2,1). A
   plain `.kv-launcher__bottle .kv-add` is (0,2,0) and lost — so the circle kept
   its 20px type and its padding, and "In den Warenkorb" spilled out of a 34px
   button across the legal fine print. `.kv-launcher__bottle a.button.kv-add` is
   (0,3,1) and wins on its own; no !important anywhere.
   (The earlier end-to-end test passed because it ran on a throwaway page that
   had no `woocommerce` body class. Test the "+" on a real guided page.) */
.kv-launcher__bottle a.button.kv-add {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 34px;
  height: 34px;
  min-width: 0;
  padding: 0;
  margin: 0;
  display: grid;
  place-items: center;
  border-radius: 999px;
  border: 1px solid var(--gcid-kv-navy, #223246);
  background: #fff;
  color: transparent;
  font-size: 0;
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
  text-decoration: none;
  transition: background-color .25s ease;
}
/* `display` and `font-family` are not decoration here: Divi's
   `.woocommerce-page a.button::before` sets `display:none; font-family:ETmodules`
   to hide its own icon slot, and a rule that only wins on `content` still
   inherits both — which is why the circle rendered empty. */
.kv-launcher__bottle a.button.kv-add::before {
  content: "+";
  display: block;
  font-family: var(--gvid-kv-font-sans, "Source Sans 3", sans-serif);
  color: var(--gcid-kv-navy, #223246);
  font-size: 20px;
  font-weight: 400;
  line-height: 1;
  opacity: 1;
  margin: 0;
  position: static;
}
.kv-launcher__bottle a.button.kv-add::after { content: none; }
.kv-launcher__bottle a.button.kv-add:hover { background: var(--gcid-kv-parchment, #f5f2ea); }
.kv-launcher__bottle a.button.kv-add:focus-visible {
  outline: 2px solid var(--gcid-kv-navy, #223246);
  outline-offset: 2px;
}
.kv-launcher__bottle a.button.kv-add.loading { opacity: .55; }
.kv-launcher__bottle a.button.kv-add.added {
  background: var(--gcid-kv-navy, #223246);
  border-color: var(--gcid-kv-navy, #223246);
}
.kv-launcher__bottle a.button.kv-add.added::before {
  content: "✓";
  font-size: 15px;
  color: var(--gcid-kv-gold-bright, #cbb585);
}
/* Woo appends a second "Zum Warenkorb" anchor after a successful add — same
   (0,2,1) trap, so it is silenced at (0,3,0), not (0,2,0). */
.kv-launcher__bottle a.added_to_cart { display: none; }

.kv-launcher__archive {
  display: inline-block;
  margin-top: 12px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--gcid-kv-navy, #223246);
  border-bottom: 1px solid var(--gcid-kv-gold, #b9a170);
  text-decoration: none;
}
.kv-launcher__archive:hover { color: var(--gcid-kv-gold-deep, #9c8456); }

/* ---- Disclosure + shelf -------------------------------------------- */

.kv-launcher__disclose {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 44px;
  padding: 8px 0;
  border: 0;
  background: transparent;
  color: var(--gcid-kv-navy, #223246);
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  cursor: pointer;
}
.kv-launcher__disclose-count {
  font-weight: 600;
  letter-spacing: .08em;
  color: var(--gcid-kv-muted, #7c7e82);
  font-variant-numeric: tabular-nums;
}
.kv-launcher__disclose::after {
  content: "";
  order: 3;
  width: 8px;
  height: 8px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .25s ease;
}
.kv-launcher__disclose[aria-expanded="true"]::after {
  transform: rotate(-135deg) translate(-2px, -2px);
}

.kv-launcher__shelf[hidden] { display: none; }
.kv-launcher__tiles {
  list-style: none;
  margin: 0;
  padding: 0 0 4px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
}
.kv-launcher__tile a {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 8px;
  padding: 10px 12px;
  min-height: 44px;
  align-content: center;
  border: 1px solid var(--gcid-kv-line-soft, #efe9dc);
  border-radius: 3px;
  background: #fff;
  color: var(--gcid-kv-navy, #223246);
  text-decoration: none;
  transition: border-color .25s ease, background-color .25s ease;
}
.kv-launcher__tile a:hover {
  border-color: var(--gcid-kv-gold, #b9a170);
  background: var(--gcid-kv-parchment, #f5f2ea);
}
.kv-launcher__tile-title {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .11em;
  text-transform: uppercase;
}
.kv-launcher__tile-count {
  font-size: 12px;
  color: var(--gcid-kv-muted, #7c7e82);
  font-variant-numeric: tabular-nums;
}
.kv-launcher__tile-line {
  grid-column: 1 / -1;
  font-size: 12px;
  line-height: 1.4;
  color: var(--gcid-kv-muted, #7c7e82);
}
/* The wit lines only earn their space once the visitor has answered and is
   deliberately browsing the shelf; before that they are ten paragraphs
   competing with one question. */
.kv-launcher:not(.is-answered) .kv-launcher__tile-line { display: none; }
/* The answered Fach is already on the table above — it does not also sit in
   the shelf below saying the same thing. */
.kv-launcher__tile.is-opened { display: none; }
.kv-launcher__tile.is-folded { display: none; }
.kv-launcher.is-unfolded .kv-launcher__tile.is-folded { display: block; }
.kv-launcher__fold[hidden] { display: none; }
.kv-launcher__fold {
  margin-top: 8px;
  padding: 8px 0;
  min-height: 44px;
  border: 0;
  background: transparent;
  color: var(--gcid-kv-navy, #223246);
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* ---- Foot ---------------------------------------------------------- */

/* Pinned, and on its own parchment field. This is the browse-all escape hatch
   the whole component exists for — it is never allowed to be the thing that
   scrolled away. The ::before is the scroll affordance: the shelf above fades
   under it instead of being cut flat. */
.kv-launcher__foot {
  flex: none;
  position: relative;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 16px;
  background: var(--gcid-kv-parchment, #f5f2ea);
  border-top: 1px solid var(--gcid-kv-line, #e3ddcf);
}
.kv-launcher__foot::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 22px;
  pointer-events: none;
  opacity: 1;
  transition: opacity .2s ease;
  background: linear-gradient(to top, var(--gcid-kv-offwhite, #fafaf8), rgba(250, 250, 248, 0));
}
/* A fade is a promise that something continues below it. Once the shelf is
   scrolled out (or never scrolled at all), there is nothing under the foot to
   fade into and the gradient is just a smear over the last card — JS toggles
   .is-scroll-end whenever the scroll region has nothing left to give. */
.kv-launcher.is-scroll-end .kv-launcher__foot::before { opacity: 0; }
.kv-launcher__exit {
  padding: 8px 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--gcid-kv-navy, #223246);
  border-bottom: 1px solid var(--gcid-kv-gold, #b9a170);
  text-decoration: none;
}
.kv-launcher__exit:hover { color: var(--gcid-kv-gold-deep, #9c8456); }
.kv-launcher__trust {
  font-size: 12.5px;
  color: var(--gcid-kv-muted, #7c7e82);
}
.kv-launcher__cart {
  flex: 1 0 100%;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--gcid-kv-vine, #7a8b55);
  text-decoration: none;
}
.kv-launcher__cart[hidden] { display: none; }

.kv-launcher__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---- Band padding ---------------------------------------------------
   The panel itself has none any more: each of the three bands pays for its own
   inset, because the navy ask field and the parchment foot have to bleed to the
   panel edges to read as fields rather than as boxes drawn inside a card. */
.kv-launcher__panel { padding: 0; }
.kv-launcher__ask {
  padding: var(--kv-pad-t, 22px) var(--kv-pad-x, 26px) 15px;
}
/* The bottom inset is the height of the foot's fade plus a line of air: scrolled
   all the way down, the last line of legal fine print has to sit BELOW the
   gradient on a clean edge. At 10px the fade landed mid-x-height on
   "Lieferzeit: 2–5 Tage" and read as the foot bar sitting on top of the card. */
.kv-launcher__scroll {
  padding: 10px var(--kv-pad-x, 26px) 30px;
  scroll-padding-bottom: 30px;
}
.kv-launcher__foot {
  padding: 12px var(--kv-pad-x, 26px) calc(14px + var(--kv-safe, 0px));
}
.kv-launcher__close {
  top: var(--kv-pad-t, 22px);
  right: var(--kv-pad-x, 26px);
}
.kv-launcher__foot::before { left: 0; right: 0; }

/* ---- Tier 1: ≥1025px — hanging dropdown, page keeps scrolling ------ */

@media only screen and (min-width: 1025px) {
  /* Divi's last menu item carries trailing padding that reaches ~11px past the
     nav's own right edge, so a slot butted straight against it clips the word
     "Kontakt". Clear it properly instead of shaving the handle. */
  .kv-launcher-handle-slot { margin-left: 26px; }
  .kv-launcher__arrow { display: block; }
  /* A light one — enough to say the page is waiting on this panel, not enough
     to turn a dropdown into a modal. The handle is lifted above it so the
     visitor can still see the control the panel came out of. */
  .kv-launcher__scrim {
    background: rgba(11, 26, 45, .3);
    backdrop-filter: none;
  }
  html.kv-launcher-is-open .kv-launcher-handle.is-docked { z-index: 96; }
}
/* Between the desktop menu appearing (1025) and there being room for it, the
   menu + full-width handle + cart total more than the bar is wide and the flex
   row wraps — which drops the cart icon onto a second line. Narrower handle
   through that band, and the label takes a second line rather than dropping to
   13px: the type size is the thing that is not allowed to move. */
@media only screen and (min-width: 1025px) and (max-width: 1279px) {
  .kv-launcher-handle-slot {
    width: 232px;
    margin-left: 16px;
    margin-right: 14px;
  }
  .kv-launcher-handle {
    gap: 8px;
    padding: 6px 10px 6px 10px;
  }
  .kv-launcher-handle__minis i { width: 15px; height: 11px; }
}
@media only screen and (min-width: 1025px) {
  /* --kv-panel-* are written by JS from the HANDLE's own rect, so the panel
     hangs off the button that was pressed — including once the handle has
     docked to the top-right corner, where it used to open 600px away from it.
     The fallbacks keep it sane for the one frame before JS measures. */
  .kv-launcher__panel {
    top: var(--kv-panel-top, calc(var(--kv-nav-h, 96px) + 10px));
    right: var(--kv-panel-right, max(24px, calc((100vw - var(--gvid-kv-content-max, 1180px)) / 2)));
    width: 720px;
    max-width: calc(100vw - 48px);
    max-height: var(--kv-panel-maxh, calc(100dvh - var(--kv-nav-h, 96px) - 44px));
    border-radius: 18px;
  }
  .kv-launcher__ask { border-radius: 18px 18px 0 0; }
  .kv-launcher__foot { border-radius: 0 0 18px 18px; }
}

/* ---- Tier 2: 601–1024px — modal sheet under the bar ---------------- */

@media only screen and (max-width: 1024px) {
  /* The bar reads as [handle ............ cart burger] instead of one gold slab
     floating left of centre with two small icons trailing it. Scoped to the
     wrap JS actually put a handle in — the header itself is global. */
  .kv-launcher-host { width: 100%; }
  .kv-launcher-handle-slot { margin-left: 0; margin-right: auto; }

  .kv-launcher__panel {
    --kv-pad-x: 22px;
    left: 24px;
    right: 24px;
    top: calc(var(--kv-nav-h, 88px) + 10px);
    max-height: calc(100dvh - var(--kv-nav-h, 88px) - 40px);
    border-radius: 20px;
  }
  .kv-launcher__ask { border-radius: 20px 20px 0 0; }
  .kv-launcher__foot { border-radius: 0 0 20px 20px; }
}
@media only screen and (max-width: 760px) {
  .kv-launcher__chips { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---- Tier 3: ≤600px — bottom sheet, reel drawer -------------------- */

@media only screen and (max-width: 600px) {
  /* Auto width, capped at whatever the cart icon and the burger leave over
     (measured: 83px of chrome plus a 13px gap). The label then takes two lines
     at 14px instead of one at 12px — legibility first, and the tab still ends
     clear of the two icons at 320px. */
  .kv-launcher-handle-slot {
    width: auto;
    min-width: min(255px, calc(100% - 96px));
    max-width: calc(100% - 96px);
    margin-right: auto;
  }
  .kv-launcher-handle {
    min-height: 44px;
    padding: 7px 12px 7px 10px;
    gap: 8px;
  }
  .kv-launcher__bird { width: 20px; height: 20px; }
  .kv-launcher-handle__minis i { width: 16px; height: 11px; }
  .kv-launcher-hint { display: none; }

  .kv-launcher__panel {
    --kv-pad-x: 18px;
    --kv-pad-t: 18px;
    --kv-safe: env(safe-area-inset-bottom);
    left: 0;
    right: 0;
    bottom: 0;
    top: auto;
    max-height: 90dvh;
    border-radius: 22px 22px 0 0;
    transform: translateY(14px);
  }
  .kv-launcher__ask { border-radius: 22px 22px 0 0; }
  .kv-launcher__foot { border-radius: 0; }
  .kv-launcher__head { font-size: 26px; }
  .kv-launcher__bottle-shot { height: 140px; }

  /* Three cards do not fit side by side at 390px and stacking them buries
     the third. A snapping reel shows 1.6 — enough to prove there is more. */
  .kv-launcher__bottles {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 62%;
    grid-template-columns: none;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    margin-right: calc(var(--kv-pad-x, 18px) * -1);
    padding-right: var(--kv-pad-x, 18px);
  }
  .kv-launcher__bottles::-webkit-scrollbar { display: none; }
  .kv-launcher__bottle { scroll-snap-align: start; }
  .kv-launcher__tiles { grid-template-columns: minmax(0, 1fr); }
}

/* The narrowest tier tightens the bird and the insets — never the type. 11px in
   a nav bar was unreadable and it was the one place the component broke its own
   rule; the four words wrap instead. */
@media only screen and (max-width: 360px) {
  .kv-launcher-handle {
    padding: 7px 10px 7px 8px;
    gap: 6px;
  }
  .kv-launcher__bird { width: 18px; height: 18px; }
  .kv-launcher-handle__minis i { width: 14px; height: 10px; }
}

/* Body scroll lock for the modal tiers. position:fixed is the only lock iOS
   Safari actually honours; JS restores the offset on close. */
body.kv-launcher-lock {
  position: fixed;
  left: 0;
  right: 0;
  width: 100%;
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .kv-launcher__panel,
  .kv-launcher__scrim,
  .kv-launcher-handle,
  .kv-launcher-hint {
    transition-duration: .24s !important;
  }
  .kv-launcher__panel { transform: none !important; }
}
