/**
 * KB Bundle Builder styles — v3 mockup-exact port (measured from the live
 * design draft: emerald-600 pills/CTA, 14px radius family, single white
 * rounded-2xl surface, 320px review panel, dashed empty slots).
 */

/* ---- v3 tokens ---- */
:root {
  --kb-space-1: 4px; --kb-space-2: 8px; --kb-space-3: 12px; --kb-space-4: 16px; --kb-space-5: 20px; --kb-space-6: 24px;
  --kb-radius-sm: 12px; --kb-radius-md: 16px; --kb-radius-lg: 20px;
  --kb-green: #688D72;          /* sage — sliders, accents, active elements */
  --kb-green-deep: #55745E;     /* deep sage — CTA, active pills, labels */
  --kb-green-ink: #22352B;      /* near-black green — text on light pills */
  --kb-sage-bg: #E4EBE6;        /* owner palette: module background */
  --kb-pill-bg: #F0F5F1;        /* owner palette: inactive pill */
  --kb-pill-on: #9DBEA5;        /* owner palette: active pill */
  --kb-add-bg: #2C4932;         /* owner palette: + add-to-bundle */
  --kb-var-bg: #EFF5F0;         /* owner palette: "N options" chip */
  --kb-card-bg: #CBD9CF;        /* owner palette: product card background */
  --kb-amber: #f59e0b;          /* star + toast accent */
  --kb-red: #b23b31;
  --kb-red-pale-bg: #fdeceb; --kb-red-pale-border: #f0c6c0;
  --kb-ink: #171717;            /* neutral-900 */
  --kb-muted: #525252;          /* neutral-700 */
  --kb-soft: #737373;           /* neutral-500 */
  --kb-faint: #a3a3a3;          /* neutral-400 — pill labels */
  --kb-line: #c3d2c8;           /* sage-tinted hairline — borders on #E4EBE6 */
  --kb-line-strong: #9db5a5;    /* stronger sage hairline — dashed slots */
  --kb-bg: #E4EBE6;             /* neutral surface = module sage (thumbs, chips) */
  --kb-shadow: 0 20px 25px -5px rgba(0,0,0,.1), 0 8px 10px -6px rgba(0,0,0,.1);
  --kb-font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

.kb-builder, .kb-builder * { box-sizing: border-box; }
.kb-builder { font-family: var(--kb-font); color: var(--kb-ink); font-size: 14px; line-height: 1.45; }
.kb-no-scroll { overflow: hidden; }

/* ---- placement: the builder replaces the default product top (v0.2.3) ---- */
body.kb-bundle-page .product-main { display: none; }
/* Flatsome's category-filter row ("Filter" button) leaks onto bundle pages
   below the module — theme element, but it has no business on a bundle. */
body.kb-bundle-page .category-filtering { display: none !important; }

/* ---- §9.1/1 THE button ruleset — text can never cut off ---- */
.kb-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 38px; max-width: 100%;
  padding: 8px 14px;
  border: none; border-radius: var(--kb-radius-md);
  font: inherit; font-weight: 700; font-size: 14px; line-height: 1.25;
  text-align: center; cursor: pointer; overflow-wrap: break-word; word-break: break-word;
}
.kb-btn:disabled { background: var(--kb-line-strong); color: var(--kb-soft); cursor: not-allowed; }
.kb-btn.green { background: var(--kb-green-deep); color: #fff; }
.kb-btn.green:hover:not(:disabled) { background: #445C4B; }
.kb-btn.ghost { background: #fff; border: 1px solid var(--kb-line); color: var(--kb-muted); }
.kb-btn.cancel { background: var(--kb-red-pale-bg); border: 1px solid var(--kb-red-pale-border); color: var(--kb-red); }
.kb-btn-lg { width: 100%; padding: 12px 16px; min-height: 44px; border-radius: var(--kb-radius-md); font-size: 14px; }

/* ---- v3 surface: ONE white rounded-2xl card, finder | 320px panel inside ---- */
.kb-wrap { max-width: 1152px; margin: 0 auto; padding: var(--kb-space-4); position: relative; }
.kb-wrap.kb-desktop {
  background: var(--kb-sage-bg); border: 1px solid var(--kb-line); border-radius: var(--kb-radius-lg);
  box-shadow: var(--kb-shadow); overflow: hidden; padding: 0;
  margin: 24px auto 32px; /* air between the site header/footer and the module */
}
.kb-main { display: grid; gap: var(--kb-space-6); margin-top: var(--kb-space-4); align-items: stretch; }
.kb-desktop .kb-main { grid-template-columns: minmax(0, 1fr) 320px; gap: 0; margin-top: 0; align-items: start; }
.kb-desktop .kb-finder {
  padding: var(--kb-space-5); border-right: 1px solid var(--kb-line);
}
/* No fixed height / inner scroll — the page scrolls, not a box inside a box
   (owner: "why do I need to scroll inside the module?"). NOT sticky: sticky
   top:96px left a growing white hole inside the card as the page scrolled
   (owner Sep 29: "weird empty white space" above the bundle name). */
.kb-desktop .kb-builder-panel {
  background: var(--kb-sage-bg); border: none; border-radius: 0;
  padding: var(--kb-space-5);
}
.kb-mobile .kb-main { grid-template-columns: 1fr; gap: 0; margin-top: 0; }
.kb-wrap.kb-mobile { padding: 20px 0 24px; }
@media (max-width: 849px) { .kb-title { font-size: 22px; } }
/* Drawer: tight pill stack — the filter rows ate half the panel (owner Sep 29).
   Sep 30 mobile polish: pills compacted so 3+ fit per row at 390px (uppercase
   names wrap one-per-line otherwise), theme letter-spacing zeroed. */
.kb-mobile .kb-pill-row { margin-bottom: 12px; column-gap: 8px; }
.kb-mobile .kb-pill-opts { gap: 4px; row-gap: 4px; }
.kb-mobile .kb-pill { padding: 6px 13px; font-size: 11px; line-height: 20px; letter-spacing: 0; margin: 0; }
.kb-mobile .kb-pill-label { padding-top: 8px; font-size: 10.5px; }
.kb-mobile .kb-pills { margin-top: 8px; }
.kb-mobile .kb-range { margin: 12px 0; }
/* Card foot: let the options chip drop to its own line instead of hard-
   clipping mid-glyph at 2-col mobile widths (owner Sep 29: "4 options cut off") */
.kb-mobile .kb-card-foot { flex-wrap: wrap; row-gap: 4px; }
.kb-mobile .kb-chip-var { letter-spacing: 0; min-height: 26px; }
/* Add button stays one line on narrow cards; 38px thumb-friendly target
   (owner Sep 30) — heights stay in flow so nothing overlays */
/* Mobile: "+" pill (owner Sep 30) — full-width like the old text button,
   40px tap target. The glyph is a clip-path cross, NOT font text: "+" side
   bearings differ across fonts (owner: "not dead center" in Safari) and
   Flatsome leaks 0.78px letter-spacing. A drawn plus is metric-perfect on
   every device. The real "+" text stays at font-size:0 for accessibility. */
.kb-mobile .kb-add { font-size: 0; line-height: 0; letter-spacing: 0; padding: 4px 10px; min-height: 40px; width: 100%; }
.kb-mobile .kb-add::before {
  content: ''; display: block; width: 16px; height: 16px; background: currentColor;
  clip-path: polygon(35% 0, 65% 0, 65% 35%, 100% 35%, 100% 65%, 65% 65%, 65% 100%, 35% 100%, 35% 65%, 0 65%, 0 35%, 35% 35%);
}
/* breathing room between the options chip and the Add button (owner Sep 30) —
   foot-level margin keeps equal card heights via the hidden placeholder chip */
.kb-mobile .kb-card-foot { margin-bottom: 10px; }

.kb-finder-btn { margin: var(--kb-space-3) 0 0; gap: var(--kb-space-2); border-radius: 999px; min-height: 48px; font-size: 15px; }
/* Mobile summary: air between the slot grid and the finder/CTA pills, and
   between the math rows and the CTA (owner Sep 30) */
.kb-mobile .kb-finder-btn { margin-top: 20px; }
.kb-mobile .kb-slots { margin: 14px 0 4px; }
.kb-mobile .kb-math .kb-btn-lg { margin-top: var(--kb-space-4); }
.kb-badge { background: #BE7E73; color: #fff; border-radius: 999px; padding: 2px 10px; font-size: 12px; font-weight: 700; white-space: nowrap; }
.kb-badge.ok { background: #7CB187; }

/* ---- panel (mockup: compact 320px review) ---- */
.kb-builder-panel { background: #fff; border: 1px solid var(--kb-line); border-radius: var(--kb-radius-lg); padding: var(--kb-space-4); }
/* Mobile summary panel: sage background like desktop (owner Sep 30: "main page
   card of the bundle background is still white") */
.kb-mobile .kb-builder-panel { border: none; border-radius: 0; padding: var(--kb-space-4); background: var(--kb-sage-bg); }
.kb-panel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--kb-space-2); }
/* theme h1 margins (Flatsome .entry-content h1) outrank .kb-title and blew a
   ~80px white hole above the bundle name — kill it with a stronger selector */
.kb-builder-panel h1.kb-title { margin: 0; }
.kb-title { margin: 0; font-size: 26px; font-weight: 800; line-height: 1.2; letter-spacing: -0.01em; }
.kb-panel-meta { font-size: 12px; color: var(--kb-soft); margin: 4px 0 var(--kb-space-3); }

/* Short description (owner: pull in with theme HTML formatting) */
.kb-desc { margin: var(--kb-space-2) 0 0; font-size: 14px; line-height: 1.65; color: var(--kb-muted); }
.kb-desc p { margin: 0 0 8px; }
.kb-desc p:last-child { margin-bottom: 0; }
.kb-desc strong, .kb-desc b { color: #1a1a1a; }
.kb-desc ul, .kb-desc ol { margin: 0 0 8px; padding-left: 20px; }

/* Rules + deal block (owner Sep 28: make constraints & discounts prominent) */
.kb-info { margin: var(--kb-space-3) 0 0; }
/* Selector strengthened (.kb-wrap .kb-rules > li): Flatsome's
   `.entry-content ul li` (0,1,2) outranks a plain `.kb-rules li` (0,1,1) and
   forces each chip onto its own block line — owner: "fit into 1 line". */
.kb-wrap .kb-rules { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 5px; }
.kb-wrap .kb-rules > li { display: inline-flex; align-items: center; gap: 4px; margin: 0; padding: 4px 9px; background: rgba(153,180,160,.4); color: var(--kb-green-ink); border-radius: 999px; font-size: 11.5px; font-weight: 700; white-space: nowrap; }
.kb-deal { margin-top: var(--kb-space-2); background: var(--kb-green-deep); color: #fff; border-radius: var(--kb-radius-md); padding: 10px 14px; font-size: 13.5px; font-weight: 700; line-height: 1.5; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.kb-deal-tag { background: rgba(255,255,255,.22); border-radius: 999px; padding: 2px 10px; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; }
.kb-deal-sep { opacity: .55; }

.kb-slots { display: grid; grid-template-columns: 1fr 1fr; gap: var(--kb-space-2); margin: 0 0 var(--kb-space-3); }
.kb-desktop .kb-builder-panel .kb-slots { grid-template-columns: 1fr; }
/* empty slot — mockup: 62px dashed neutral-300 capsule, 12px muted label.
   Tappable: whole slot opens the finder (v0.2.4) */
.kb-slot { border: 1px dashed var(--kb-line-strong); border-radius: var(--kb-radius-md); min-height: 62px; display: flex; align-items: center; justify-content: center; color: var(--kb-soft); font-size: 12px; padding: var(--kb-space-2); }
.kb-slot.empty { cursor: pointer; background: transparent; font: inherit; transition: border-color .15s, color .15s, background .15s; }
.kb-slot.empty:hover, .kb-slot.empty:focus-visible { border-color: var(--kb-green); color: var(--kb-green); background: rgba(5,150,105,.05); outline: none; }
.kb-slot.filled { border-style: solid; border-color: var(--kb-line); background: var(--kb-card-bg); display: block; cursor: pointer; }
.kb-slot.filled:hover { border-color: var(--kb-green); }
.kb-slot-head { display: flex; justify-content: space-between; gap: var(--kb-space-1); font-size: 14px; font-weight: 600; min-width: 0; }
.kb-slot-name { overflow-wrap: anywhere; min-width: 0; font-weight: 700; font-size: 14.5px; }
.kb-slot-x { border: none; background: none; color: #BE7E73; cursor: pointer; font-size: 20px; font-weight: 700; line-height: 1; padding: 2px 6px; margin: -8px -6px 0 0; border-radius: 999px; }
/* Under-title rating link (owner Sep 29) */
.kb-rating-link { display: inline-flex; align-items: center; gap: 5px; border: none; background: none; padding: 0; margin: 4px 0 0; font: inherit; font-size: 13.5px; font-weight: 600; color: var(--kb-muted); cursor: pointer; }
.kb-rating-link:hover .kb-rev-count { text-decoration: underline; }
.kb-rating-link .kb-stars { color: var(--kb-amber); letter-spacing: 1px; font-size: 14px; }
.kb-rating-link .kb-rev-count { color: var(--kb-soft); font-weight: 500; }
.kb-slot-x:hover { color: var(--kb-red); background: var(--kb-red-pale-bg); }
.kb-slot-row { display: flex; justify-content: space-between; align-items: center; margin-top: var(--kb-space-2); font-size: 13px; font-weight: 700; }
.kb-slot-price { font-weight: 800; font-size: 15.5px; }
/* Mobile filled slot: price and qty selector on separate lines, everything
   left-aligned (owner Sep 30: "more space between price and quantity").
   Alignment pass (owner Sep 30: "aligned better, looks sloppy"): the ×
   pins to the first name line (flex-start, not stretch), the card becomes
   a flex column, and margin-top:auto pushes the price/qty block to the
   card bottom — every card in a row ends evenly no matter how many lines
   the name wraps to. */
.kb-mobile .kb-slot-head { align-items: flex-start; }
.kb-mobile .kb-slot.filled { display: flex; flex-direction: column; }
.kb-mobile .kb-slot-row { flex-direction: column; align-items: center; gap: 6px; margin-top: auto; }
.kb-mobile .kb-slot.filled { padding-bottom: var(--kb-space-3); }
/* Variant pill compaction (owner Sep 30: "make the pill smaller, text smaller,
   reduce padding — where it says Eighth") */
.kb-mobile .kb-var { padding: 7px 10px; font-size: 11.5px; min-height: 32px; }
/* Compact qty pill (owner Sep 29: too big; −/+ too far apart).
   .kb-wrap-prefixed + explicit sizing: Flatsome's button rules match
   `.kb-qty button` on equal specificity and load later — same fight as the
   search input. */
.kb-wrap .kb-qty { display: inline-flex; align-items: center; gap: 4px; border: 1px solid rgba(85,116,94,.3); border-radius: 999px; padding: 1px 6px; background: #99B4A0; font-size: 12px; min-height: 24px; height: 24px; }
.kb-wrap .kb-qty button { border: none; background: none; cursor: pointer; font-size: 13px; line-height: 1; padding: 0 4px; margin: 0; min-height: 0; height: auto; color: #fff; }
.kb-qty b { font-weight: 700; min-width: 14px; text-align: center; color: #fff; }
.kb-var { display: block; width: 100%; max-width: 100%; margin-top: var(--kb-space-2); padding: 11px 12px; border: 1px solid transparent; border-radius: 999px; background: #688D72; color: #fff; font: inherit; font-size: 13px; font-weight: 700; line-height: 1.35; min-height: 40px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---- math block (mockup desktop: plain rows on the panel bg; savings emerald) ---- */
.kb-math { padding-top: var(--kb-space-2); margin-top: var(--kb-space-2); }
.kb-math-row { display: flex; justify-content: space-between; font-size: 13px; color: var(--kb-soft); padding: 3px 0; gap: var(--kb-space-2); }
.kb-math-save { color: var(--kb-green); font-weight: 700; }
.kb-save-chip {
  display: inline-block; background: var(--kb-green); color: #fff;
  border-radius: 999px; padding: 1px 8px; font-size: 11px; font-weight: 800;
  margin-left: 4px; vertical-align: 1px;
}
.kb-math-total { border-top: 1px solid var(--kb-line); margin-top: var(--kb-space-2); padding-top: var(--kb-space-2); color: var(--kb-ink); font-weight: 700; font-size: 16px; }
.kb-math .kb-btn-lg { margin-top: var(--kb-space-3); }
/* CTA state colors (owner Sep 29): muted red "Add N more" while incomplete,
   deep sage once the bundle qualifies. Overrides .kb-btn:disabled defaults. */
#kb-cta { background: #BE7E73; color: #fff; }
/* Ready state (owner Sep 29): muted lilac fill + lilac border. Light fill →
   dark plum text for contrast (white on #D9BFD4 would wash out). */
#kb-cta.kb-ready { background: #D9BFD4; border: 1px solid #C7A1C1; color: #432C3D; cursor: pointer; }
#kb-cta.kb-ready:hover { background: #CBA9C4; border-color: #C7A1C1; color: #432C3D; }
/* Mobile summary block: same light sage treatment as desktop (owner Sep 29 —
   the dark bar read as a foreign plugin element, not part of the site). */
.kb-mobile .kb-math { background: var(--kb-sage-bg); border: 1px solid var(--kb-line); border-radius: var(--kb-radius-md); padding: var(--kb-space-4); margin: 20px 0 0; }
.kb-mobile .kb-math-row { color: var(--kb-muted); }
.kb-mobile .kb-math-save { color: var(--kb-green); }
.kb-mobile .kb-math-total { color: var(--kb-ink); border-top-color: var(--kb-line); }
.kb-nudge { background: #fffbeb; color: #92400e; border-radius: var(--kb-radius-sm); padding: var(--kb-space-2) var(--kb-space-3); font-size: 12px; font-weight: 600; margin: var(--kb-space-2) 0; }
.kb-note { text-align: center; font-size: 11px; color: var(--kb-soft); margin: var(--kb-space-2) 0 0; }
.kb-mobile .kb-note { color: var(--kb-soft); }

/* ---- finder ---- */
.kb-search { position: relative; }
/* Prominent pill search (owner Sep 29): no icon — it fought the layout for
   three rounds and added nothing. Thick light-green ring, white fill. */
/* Selector strengthened with .kb-wrap + input[type="search"] on purpose:
   Flatsome (flatsome.css) ships `input[type=search]{...border:1px solid #ddd;
   border-radius:0...}` loaded AFTER this file with equal specificity, which
   kept winning and flattened the pill. (0,2,1) beats the theme's (0,1,1). */
.kb-wrap .kb-search input[type="search"] {
  width: 100%; height: 46px; padding: 10px 20px;
  border: 2px solid rgba(85,116,94,.5); border-radius: 999px;
  background: #fff; font: inherit; font-size: 14.5px; color: var(--kb-ink);
  box-shadow: none; -webkit-appearance: none; appearance: none;
}
.kb-wrap .kb-search input[type="search"]::placeholder { color: var(--kb-muted); }
.kb-wrap .kb-search input[type="search"]:focus {
  outline: none; border-color: var(--kb-green);
  box-shadow: 0 0 0 3px rgba(104,141,114,.18); background: #fff;
}

/* ---- filter collapse (owner Sep 29: filters too intrusive in the drawer) ----
   Mobile: hidden behind an obvious "Filters" button with an active count.
   Desktop: button hidden, filters always visible. */
.kb-filter-toggle {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: var(--kb-space-2); padding: 9px 14px; min-height: 42px;
  border: 1px solid var(--kb-line); border-radius: 999px; background: #fff;
  font: inherit; font-size: 13px; font-weight: 700; color: var(--kb-muted); cursor: pointer;
}
.kb-filter-toggle .kb-chev { transition: transform .2s; }
.kb-filter-toggle.open .kb-chev { transform: rotate(180deg); }
.kb-filter-toggle.open { border-color: var(--kb-green); color: var(--kb-green-deep); }
.kb-filter-count { background: var(--kb-green); color: #fff; border-radius: 999px; min-width: 18px; height: 18px; line-height: 18px; text-align: center; font-size: 11px; font-weight: 800; padding: 0 4px; }
.kb-desktop .kb-filter-toggle { display: none; }
.kb-desktop #kb-filters { display: block; }
.kb-mobile #kb-filters { display: none; }
.kb-mobile #kb-filters.open { display: block; }

/* ---- pills (mockup: full-radius, 13px/500, emerald active) ----
   Label column + wrapping pill container — rows stay aligned on narrow
   screens instead of ragged wraps under the label (owner v0.2.5). */
.kb-pills { margin-top: var(--kb-space-3); }
.kb-sort-row { margin: var(--kb-space-2) 0 0; }
.kb-pill-row { display: grid; grid-template-columns: 48px minmax(0, 1fr); column-gap: 8px; align-items: start; margin-bottom: 5px; }
.kb-pill-row-full { grid-template-columns: minmax(0, 1fr); }
.kb-pill-label { font-size: 10.5px; font-weight: 800; text-transform: uppercase; color: var(--kb-green-deep); letter-spacing: .04em; padding-top: 6px; }
.kb-pill-opts { display: flex; flex-wrap: wrap; gap: 5px; min-width: 0; }
.kb-pill {
  border: 1px solid rgba(85,116,94,.28); border-radius: 999px; background: var(--kb-pill-bg);
  padding: 4px 9px; font: inherit; font-size: 11.5px; font-weight: 700; color: var(--kb-green-ink);
  cursor: pointer; white-space: nowrap; line-height: 18px;
}
.kb-pill:hover { border-color: var(--kb-green-deep); color: var(--kb-green-ink); }
.kb-pill.on { background: var(--kb-pill-on); border-color: var(--kb-pill-on); color: var(--kb-green-ink); }

/* ---- price range: slider inline with its label (owner Sep 29) ----
   min-height reserves room for the 22px handles so they never spill onto the
   SORT row below ("circle cuts into Random"). */
.kb-range { display: flex; align-items: center; gap: 16px; min-height: 22px; margin: 14px 0; }
.kb-range-label { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--kb-green-deep); white-space: nowrap; }
.kb-range-val { font-size: 12px; font-weight: 600; color: var(--kb-ink); white-space: nowrap; min-width: 86px; text-align: right; }
/* Track margins: ~10% shorter AND the end handles overhang padding instead of
   the label/value text (owner: "price range and the slider too close together") */
.kb-range-track { position: relative; flex: 1; min-width: 60px; height: 6px; margin: 0 12px; border-radius: 999px; background: rgba(85,116,94,.22); }
.kb-range-fill { position: absolute; top: 0; bottom: 0; background: var(--kb-green); border-radius: 999px; }
.kb-range-handle {
  position: absolute; top: 50%; transform: translate(-50%, -50%);
  width: 22px; height: 22px; min-width: 22px; min-height: 22px;
  aspect-ratio: 1/1; flex: none; padding: 0; border-radius: 50%;
  background: #fff; border: 3px solid var(--kb-green);
  cursor: grab; touch-action: none;
  box-shadow: 0 1px 4px rgba(0,0,0,.2);
  box-sizing: border-box; /* theme button padding can't inflate it into an oval */
}
.kb-range-handle:active { cursor: grabbing; border-color: var(--kb-green-deep); }

.kb-count { font-size: 11px; color: var(--kb-soft); margin: var(--kb-space-3) 0 var(--kb-space-2); }

/* ---- product grid ----
   Desktop: auto-fill ≥180px → 3–4 smaller thumbnails per row (owner Sep 29:
   "smaller thumbnails"). Mobile: explicit 2-col — auto-fill + minmax let
   cards overflow the drawer panel on WebKit (v0.2.4). */
.kb-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--kb-space-3); }
.kb-desktop .kb-grid { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: var(--kb-space-3); }
.kb-mobile .kb-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.kb-card { min-width: 0; border: 1px solid rgba(85,116,94,.25); border-radius: var(--kb-radius-md); padding: var(--kb-space-3); background: var(--kb-card-bg); display: flex; flex-direction: column; }
/* Button pinned to the card bottom: grid rows stretch every card to the same
   height, so margin-top:auto aligns ALL Add-to-bundle buttons across a row
   regardless of name length, rating, or options chip (owner: "still not same
   height" — fixing the residual case-by-case gaps structurally). */
.kb-card .kb-add { margin-top: auto; }
.kb-card.in-bundle { border-color: var(--kb-green-deep); box-shadow: 0 0 0 2px rgba(85,116,94,.18); }
.kb-thumb { position: relative; aspect-ratio: 1; border-radius: var(--kb-radius-md); background: var(--kb-bg); overflow: hidden; }
.kb-thumb img { width: 100%; height: 100%; object-fit: cover; object-position: center; }
/* Mobile: shorter photo band, but 2:1 cropped product shots badly (owner Sep 29) */
.kb-mobile .kb-thumb { aspect-ratio: 4/3; }
.kb-sale-badge {
  position: absolute; top: var(--kb-space-2); left: var(--kb-space-2); z-index: 1;
  background: var(--kb-red); color: #fff; border-radius: var(--kb-radius-sm);
  font-size: 10px; font-weight: 800; text-transform: uppercase; padding: 2px 6px;
}
.kb-name { font-size: 12px; font-weight: 600; line-height: 1.35; margin: var(--kb-space-2) 0 2px; min-height: 2.7em; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.kb-rating { font-size: 11px; color: var(--kb-muted); margin: 0 0 2px; }
.kb-rating .kb-star { color: var(--kb-amber); }
.kb-rating .kb-reviews { color: #47604F; }
.kb-card-foot { display: flex; justify-content: flex-start; align-items: center; gap: 6px; flex-wrap: nowrap; overflow: hidden; line-height: 1.15; }
.kb-card .kb-price { font-weight: 700; font-size: 14px; line-height: 1.15; color: var(--kb-ink); white-space: nowrap; flex: 0 0 auto; display: inline-flex; align-items: center; }
.kb-card .kb-price .kb-from { font-weight: 500; font-size: 11px; color: var(--kb-soft); }
.kb-card .kb-sale-price { color: var(--kb-soft); text-decoration: line-through; font-weight: 500; font-size: 11.5px; margin-right: 4px; }
.kb-chip { background: var(--kb-bg); border: 1px solid var(--kb-line); border-radius: 999px; padding: 1px 8px; font-size: 10.5px; font-weight: 600; color: var(--kb-muted); white-space: nowrap; flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* "N options" chip: it's a HINT BUTTON, not a label (owner Sep 29).
   inline-flex + fixed line-height keeps it optically centered next to the
   price text (owner: "4 options not properly valigned center to the price"). */
.kb-chip-var { cursor: pointer; font: inherit; font-size: 10.5px; font-weight: 700; line-height: 1.1; min-height: 22px; padding: 2px 8px; display: inline-flex; align-items: center; border-style: dashed; background: var(--kb-var-bg); border-color: rgba(85,116,94,.35); color: var(--kb-green-ink); }
.kb-chip { display: inline-flex; align-items: center; line-height: 1.1; }
.kb-chip-placeholder { visibility: hidden; min-height: 22px; padding: 2px 8px; }
.kb-chip-var:hover { border-color: var(--kb-green-deep); color: var(--kb-green-ink); }
.kb-name a { color: inherit; text-decoration: none; }
.kb-name a:hover { color: var(--kb-green-deep); text-decoration: underline; }
.kb-thumb a { display: block; width: 100%; height: 100%; }
/* mockup: subtle emerald ghost. INLINE in the card foot — absolute placement
   kept colliding with the options chip (owner Sep 29: "+ is weirdly placed"). */
/* Text pill (owner Sep 29: replaces the + circle) — full card width, below
   the price row. */
.kb-add {
  width: 100%; min-height: 34px; margin-top: var(--kb-space-2);
  border: 1px solid var(--kb-add-bg); border-radius: 999px;
  background: var(--kb-add-bg); color: #fff; font: inherit; font-size: 12.5px; font-weight: 700; line-height: 1.2; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  transition: background .15s, color .15s;
}
.kb-add:hover:not(:disabled) { background: #1E3626; border-color: #1E3626; color: #fff; }
.kb-add:disabled { background: var(--kb-line); color: var(--kb-soft); border-color: var(--kb-line); cursor: not-allowed; }
.kb-empty { grid-column: 1/-1; text-align: center; color: var(--kb-soft); padding: 40px 0; border: 1px dashed var(--kb-line-strong); border-radius: var(--kb-radius-md); }
.kb-more { grid-column: 1/-1; justify-self: center; margin-top: var(--kb-space-2); border-radius: 999px; padding: 10px 22px; }

/* ---- mobile drawer (§9.2/6 — fixed panel, no gestures, explicit close) ----
   Scrim must paint BELOW the panel: DOM order (bg first) + explicit z-index.
   Drawer z sits above theme floaters (WPLoyalty JOIN pill, back-to-top). */
.kb-drawer { position: fixed; inset: 0; z-index: 999900; visibility: hidden; }
.kb-drawer.open { visibility: visible; }
.kb-drawer-bg { position: absolute; inset: 0; z-index: 0; background: rgba(0,0,0,.4); opacity: 0; transition: opacity .2s; }
.kb-drawer.open .kb-drawer-bg { opacity: 1; }
.kb-drawer-panel {
  position: absolute; top: 0; left: 0; bottom: 0; width: 88%; max-width: 420px;
  z-index: 1;
  background: #E4EBE6; /* owner-specified modal tint */
  box-shadow: var(--kb-shadow);
  transform: translateX(-100%); transition: transform .25s ease;
  display: flex; flex-direction: column; padding: var(--kb-space-4) var(--kb-space-6);
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  /* Classic scrollbars (iPadOS with mouse, desktop Safari narrow window) sit
     INSIDE the right padding and made it read ~40px vs 24px left — the
     "padding looks worse" report (owner Sep 30). Hide the track: touch and
     wheel scrolling are unaffected, padding stays symmetric. */
  scrollbar-width: none;
}
.kb-drawer-panel::-webkit-scrollbar { width: 0; height: 0; }
.kb-drawer.open .kb-drawer-panel { transform: none; }
.kb-drawer-head { display: flex; align-items: center; justify-content: space-between; gap: var(--kb-space-2); margin-bottom: var(--kb-space-3); font-size: 12px; color: var(--kb-soft); flex-wrap: nowrap; }
.kb-drawer-head .kb-btn { white-space: nowrap; padding: 6px 10px; min-height: 34px; font-size: 12.5px; flex: 0 0 auto; }
.kb-drawer-title { flex: 1; min-width: 0; text-align: center; font-size: 17px; font-weight: 800; color: var(--kb-ink); letter-spacing: -0.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; align-self: center; }
/* 24px side padding (0.3.6) squeezes the header — smaller title keeps
   "Pick your products" on one line instead of truncating */
.kb-mobile .kb-drawer-title { font-size: 14px; }
/* Mobile header: strict vertical centering; × larger, muted red (owner Sep 30).
   gap 6px (0.3.9): measured title needs 120px, had 116 — tighter gaps buy it */
.kb-mobile .kb-drawer-head { align-items: center; gap: 6px; }
/* Flatsome leaks margins onto header buttons (measured Sep 30: ghost btn
   mr 12.5px, drawer-x mr 26px) — they shrink the title box by ~38px and
   starve "Pick your products" into ellipsis at 375px. Zero them here. */
.kb-mobile .kb-drawer-head .kb-btn { align-self: center; margin: 0; }
.kb-mobile .kb-drawer-x {
  flex: 0 0 auto; align-self: center; margin: 0;
  border: none; background: none; cursor: pointer; font-size: 26px; line-height: 1;
  color: #BE7E73; padding: 2px 10px; border-radius: 999px;
}
.kb-mobile .kb-drawer-x:hover { color: var(--kb-red); background: var(--kb-red-pale-bg); }
.kb-drawer-x {
  flex: 0 0 auto;
  border: none; background: none; cursor: pointer; font-size: 20px; line-height: 1;
  color: var(--kb-soft); padding: 2px 8px; border-radius: 999px;
}
.kb-drawer-x:hover { color: var(--kb-ink); background: rgba(0,0,0,.06); }

/* desktop slot-tap feedback: pulsing ring around the finder — visible even
   when the finder is already in the viewport (owner: "pressing it does nothing") */
@keyframes kb-pulse { 0% { box-shadow: 0 0 0 0 rgba(5,150,105,.45); } 100% { box-shadow: 0 0 0 16px rgba(5,150,105,0); } }
.kb-finder.kb-flash { animation: kb-pulse .55s ease-out 2; border-radius: var(--kb-radius-lg); }

/* ---- toast (§10.4: non-blocking, green/amber, wrap-safe) ---- */
.kb-toast {
  position: fixed; top: 16px; left: 50%; transform: translateX(-50%) translateY(-8px);
  z-index: 999950; pointer-events: none; /* never blocks taps */
  max-width: min(88%, 460px); overflow-wrap: break-word; word-break: break-word;
  background: var(--kb-green); border: 2px solid var(--kb-amber);
  color: #fff; font-weight: 700; font-size: 12.5px; line-height: 1.4; text-align: center;
  padding: 10px 16px; border-radius: var(--kb-radius-md); box-shadow: var(--kb-shadow);
  opacity: 0; transition: opacity .15s, transform .15s;
}
.kb-toast.on { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---- busy lock (§9.2/7) ---- */
.kb-busy { position: absolute; inset: 0; z-index: 99994; display: none; align-items: center; justify-content: center; background: rgba(255,255,255,.72); border-radius: var(--kb-radius-lg); }
.kb-busy.on { display: flex; }
.kb-busy-box { text-align: center; font-weight: 700; color: var(--kb-green); font-size: 13px; }
.kb-spin { display: inline-block; width: 34px; height: 34px; border: 4px solid #cde8d2; border-top-color: var(--kb-green); border-radius: 50%; animation: kb-rot 0.8s linear infinite; margin-bottom: var(--kb-space-2); }
.kb-spin-sm { width: 22px; height: 22px; border-width: 3px; margin-bottom: var(--kb-space-1); }
.kb-boot { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding: var(--kb-space-4) var(--kb-space-2); color: var(--kb-soft); font-size: 13px; font-weight: 600; text-align: center; }
.kb-grid > .kb-boot { grid-column: 1 / -1; }
@keyframes kb-rot { to { transform: rotate(360deg); } }

/* ---- errors & promo (in-context only, §9.3/9) ---- */
.kb-error { background: var(--kb-red-pale-bg); border: 1px solid var(--kb-red-pale-border); color: var(--kb-red); border-radius: var(--kb-radius-sm); padding: var(--kb-space-3); font-size: 13px; font-weight: 600; margin: var(--kb-space-3) 0; }
.kb-promo { background: #fffbeb; border: 1px solid var(--kb-amber); color: #92400e; border-radius: var(--kb-radius-md); padding: var(--kb-space-3); font-weight: 700; font-size: 13.5px; margin: 0 0 var(--kb-space-3); }
.kb-noscript { padding: var(--kb-space-4); background: var(--kb-red-pale-bg); border-radius: var(--kb-radius-md); }

/* ---- safe area (§9 lessons) ---- */
@supports (padding: max(0px)) {
  .kb-wrap { padding-bottom: max(var(--kb-space-4), env(safe-area-inset-bottom)); }
  .kb-wrap.kb-mobile { padding-bottom: 0; }
}

/* 2.1.0: native modal containment, explicit options and keyboard parity. */
dialog.kb-drawer { margin: 0; padding: 0; border: 0; width: 100%; height: 100%; max-width: none; max-height: none; background: transparent; color: inherit; }
dialog.kb-drawer::backdrop { background: transparent; }
.kb-card-options { margin: 8px 0; }
.kb-card-options[hidden] { display: none; }
.kb-card-options label { display: block; font-size: 12px; font-weight: 700; }
.kb-card-options select { width: 100%; min-width: 0; margin: 4px 0 0; font-size: 12px; }
.kb-range-handle:focus-visible, .kb-wrap button:focus-visible, .kb-wrap select:focus-visible { outline: 2px solid var(--kb-green-deep); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
  .kb-wrap *, .kb-wrap *::before, .kb-wrap *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
}
