/* ==========================================================================
   bundle-builder.css — presentation for the theme-owned `bundle_builder`
   section. Token-only: every colour, radius, space and font resolves through
   layered var() fallbacks so the same file works on a --clr-* theme, a
   --color-* theme, or a theme with neither.

   Nothing in here knows about a specific bundle, product, group or vendor.
   ========================================================================== */

.bb {
  --bb-text:        var(--clr-body,    var(--color-body,    #1f2937));
  --bb-heading:     var(--clr-primary, var(--color-primary, #111827));
  --bb-muted:       var(--clr-muted,   var(--color-muted,   #6b7280));
  --bb-surface:     var(--clr-white,   var(--color-white,   #ffffff));
  --bb-surface-alt: var(--clr-light,   var(--color-light,   #fafafa));
  --bb-line:        var(--clr-gray,    var(--color-gray,    #e5e7eb));
  --bb-accent:      var(--clr-accent,  var(--color-accent,  var(--clr-primary, #111827)));
  --bb-on-accent:   var(--clr-white,   var(--color-white,   #ffffff));
  --bb-success:     var(--clr-success, var(--color-success, #10b981));
  --bb-warning:     var(--clr-warning, var(--color-warning, #b45309));
  --bb-radius:      var(--rounded-lg,  var(--radius-lg, 12px));
  --bb-radius-sm:   var(--rounded-sm,  var(--radius-sm, 8px));
  --bb-gap:         var(--space-md, 16px);

  /* Media sizing tokens.
     `--bb-option-min` is the option grid's column floor; an option card pads
     itself by `--bb-option-pad` on each side, so the option THUMBNAIL is
     (column - 2 * pad) wide. The included item is the anchor of the bundle, so
     its thumbnail is one spacing step LARGER than a whole option column —
     never smaller than the option thumbnail it sits above. */
  --bb-option-min:      116px;
  --bb-option-pad:      8px;
  --bb-included-size:   calc(var(--bb-option-min) + var(--space-md, 16px));

  color: var(--bb-text);
  font-family: var(--ff-body, inherit);
}

/* --------------------------------------------------------------------------
   Scoped compat layer.
   Host themes commonly (a) hijack `button, .btn` into a black flex box,
   (b) set -webkit-appearance:none on inputs, which makes native radios and
   checkboxes invisible, and (c) declare `ul, li { list-style: none }`, which
   kills bullets in rich text. Everything below is scoped to `.bb` and only
   undoes those three collisions inside this section.
   -------------------------------------------------------------------------- */
.bb button.bb__control,
.bb .btn.bb__control {
  -webkit-appearance: none;
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  min-width: 0;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  color: inherit;
  font: inherit;
  line-height: inherit;
  letter-spacing: normal;
  text-transform: none;
  text-align: left;
  cursor: pointer;
}

/* Native controls: keep them real (and reachable) rather than relying on the
   host theme not having nulled their appearance. They are visually replaced by
   .bb__mark but remain focusable, announced and keyboard-operable. */
.bb input[type="radio"].bb__input,
.bb input[type="checkbox"].bb__input {
  -webkit-appearance: none;
  appearance: none;
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

.bb .bb__prose ul { list-style: disc outside; padding-left: 1.25em; }
.bb .bb__prose ol { list-style: decimal outside; padding-left: 1.25em; }
.bb .bb__prose li { list-style: inherit; display: list-item; }

/* --------------------------------------------------------------------------
   Layout
   -------------------------------------------------------------------------- */
.bb__head { display: grid; gap: 6px; margin-bottom: var(--bb-gap); }

.bb__title {
  margin: 0;
  font-family: var(--ff-heading, inherit);
  font-size: var(--fs-h3, 1.5rem);
  line-height: 1.15;
  color: var(--bb-heading);
}

.bb__subtitle { margin: 0; color: var(--bb-muted); font-size: var(--fs-caption, 0.875rem); }

/* ── Two-column shell ──────────────────────────────────────────────────────
   The product shot used to sit in the vertical flow above the groups, costing
   a full screen of scroll before the first option. It now occupies a sticky
   left column while the groups scroll past it in the right rail.

   The media column is deliberately capped narrow: every pixel it takes is a
   pixel the option grid can't use for another column, and fitting more of the
   bundle on one screen is the whole point of this layout. */
.bb__layout {
  display: grid;
  grid-template-columns: minmax(240px, 320px) minmax(0, 1fr);
  gap: var(--space-xl, 32px);
  align-items: start;
}

.bb__media {
  position: sticky;
  /* Clears the sticky site header; falls back to a safe value if unset. */
  top: var(--bb-sticky-top, 96px);
}

/* min-width:0 lets the rail's option grid shrink inside the grid track —
   without it the 43-card drink grid forces the column wider and overflows. */
.bb__rail { min-width: 0; }

.bb__hero {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  border-radius: var(--bb-radius);
  background: var(--bb-surface-alt);
}

/* Price + running total + CTA pin to the bottom of the viewport so the cost
   of a configuration stays visible while the shopper scrolls the options. */
.bb .bb__footer {
  position: sticky;
  bottom: 0;
  z-index: 2;
  padding-bottom: var(--bb-gap);
  background: var(--clr-white, #ffffff);
  box-shadow: 0 -10px 18px -14px rgba(0, 0, 0, 0.35);
}

@media (max-width: 900px) {
  .bb__layout {
    grid-template-columns: 1fr;
    gap: var(--space-md, 16px);
  }

  .bb__media {
    position: static;
    width: 100%;
    max-width: 300px;
    margin-inline: auto;
  }
}

.bb__groups { display: grid; gap: var(--space-lg, 24px); }

.bb__branches {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 6px;
  background: var(--bb-surface-alt);
  border-radius: var(--bb-radius);
}

.bb__branch {
  padding: 8px 14px;
  border-radius: var(--bb-radius-sm);
  font-size: var(--fs-caption, 0.875rem);
  font-weight: 600;
  color: var(--bb-heading);
  background: transparent;
}

.bb__branch[aria-pressed="true"] { background: var(--bb-surface); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12); }

.bb__group { display: grid; gap: 12px; }
.bb__group[hidden] { display: none; }

.bb__group-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }

.bb__group-title {
  margin: 0;
  font-family: var(--ff-heading, inherit);
  font-size: var(--fs-h5, 1.125rem);
  color: var(--bb-heading);
}

.bb__group-desc { margin: 0; color: var(--bb-muted); font-size: var(--fs-caption, 0.875rem); }

.bb__count {
  flex: 0 0 auto;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--bb-surface-alt);
  color: var(--bb-muted);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.bb__count.is-complete { background: var(--bb-success); color: var(--bb-on-accent); }
.bb__count.is-over { background: var(--bb-warning); color: var(--bb-on-accent); }

/* Included (auto-added) groups */
.bb__included {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border: 1px solid var(--bb-line);
  border-radius: var(--bb-radius);
  background: var(--bb-surface-alt);
}

/* The included item is the hero of the bundle, so its thumbnail is a step
   LARGER than an option thumbnail rather than smaller. Size comes from the
   shared media tokens above, so it can never drift out of step with the
   option grid. */
.bb__included-media {
  width: var(--bb-included-size);
  height: var(--bb-included-size);
  object-fit: contain;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--bb-surface);
}
.bb__included img { flex: 0 0 auto; }

/* Keeps the "Included: <item>" label on the row next to a large thumbnail:
   it may wrap, but it must never be pushed out or force a horizontal scroll. */
.bb__included-text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.bb__included-label { font-weight: 700; }

/* Options */
.bb__options {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--bb-option-min), 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
}

.bb__option {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: var(--bb-option-pad);
  border: 1px solid var(--bb-line);
  border-radius: var(--bb-radius);
  background: var(--bb-surface);
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

.bb__option:hover { border-color: var(--bb-accent); }
.bb__option.is-selected { border-color: var(--bb-accent); box-shadow: inset 0 0 0 1px var(--bb-accent); }
.bb__option.is-disabled { opacity: 0.45; cursor: not-allowed; }
.bb__option:focus-within { outline: 2px solid var(--bb-accent); outline-offset: 2px; }

.bb__mark {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: 2px solid var(--bb-line);
  border-radius: 50%;
  background: var(--bb-surface);
  color: transparent;
}

.bb__mark svg { width: 12px; height: 12px; display: block; }

.bb__option--multi .bb__mark { border-radius: 6px; }

.bb__option.is-selected .bb__mark {
  border-color: var(--bb-accent);
  background: var(--bb-accent);
  color: var(--bb-on-accent);
}

.bb__option-media {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  background: var(--bb-surface-alt);
  border-radius: 50%;
}

.bb__option-media--empty { background: var(--bb-surface-alt); }

/* Clamped to two lines: a grid row is as tall as its tallest card, so one
   long product name would otherwise add a line of height to every card in
   that row. The full name stays in the DOM (announced, and shown on hover
   via the card's title attribute) — only the painted lines are capped. */
.bb__option-name {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  width: 100%;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  overflow-wrap: anywhere;
}

.bb__option-price { font-size: 11px; color: var(--bb-muted); text-align: center; }
.bb__option-price[hidden] { display: none; }

/* --------------------------------------------------------------------------
   Size sub-picker — rendered ONLY for a product that contributes more than one
   variant to its group. Labels and price deltas are supplied by the section
   from the variant's own option data; nothing here knows a size name.
   -------------------------------------------------------------------------- */
/* Progressive disclosure: the pills only exist for the card the shopper has
   actually chosen. Three labelled pills stack on a ~116px card and were ~80px
   of every one of the 40 cards that carry them — by far the largest remaining
   block of scroll. A size can only be set on a selection anyway, so an
   unselected card showing a size picker was offering a control that does
   nothing yet.

   display:none (not visibility/opacity) so the hidden pills also leave the
   tab order and the a11y tree — a keyboard user reaches them the moment the
   card becomes selected, and never tabs through 40 dead pickers to get to the
   next option. Deliberately NOT revealed on :hover: that would reflow the
   whole grid under the cursor. */
.bb__sizes {
  display: none;
  gap: 0;
  width: 100%;
  margin-top: auto;
  padding-top: 6px;
  border-top: 1px dashed var(--bb-line);
}

/* 0-3-0, comfortably over the 0-1-0 base above. :focus-within keeps the picker
   open while a pill inside it holds focus. */
.bb__option.is-selected .bb__sizes,
.bb__option:focus-within .bb__sizes {
  display: grid;
}

/* The visible "Size" caption is redundant next to self-describing pills and
   cost a line of height on nearly every card in the grid. The group keeps its
   aria-label, so assistive tech still announces what the pills are. */
.bb__sizes-label { display: none; }

.bb__sizes-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 3px;
}

/* NOTE: the scoped compat reset is `.bb button.bb__control` (0-2-1). These
   rules are 0-3-1 so they win. */
.bb button.bb__size.bb__control,
.bb .btn.bb__size.bb__control {
  display: inline-flex;
  align-items: baseline;
  gap: 3px;
  padding: 3px 8px;
  border: 1px solid var(--bb-line);
  border-radius: 999px;
  background: var(--bb-surface);
  color: var(--bb-heading);
  font-size: 11px;
  font-weight: 700;
  line-height: 1.15;
  white-space: nowrap;
}

.bb button.bb__size.bb__control:hover,
.bb .btn.bb__size.bb__control:hover { border-color: var(--bb-accent); }

.bb button.bb__size.bb__control.is-active,
.bb .btn.bb__size.bb__control.is-active {
  border-color: var(--bb-accent);
  background: var(--bb-accent);
  color: var(--bb-on-accent);
}

.bb__size-delta { font-size: 10px; font-weight: 600; opacity: 0.85; }

.bb__stepper { display: inline-flex; align-items: center; gap: 8px; margin-top: 2px; }

.bb button.bb__step.bb__control,
.bb .btn.bb__step.bb__control {
  width: 26px;
  height: 26px;
  border: 1px solid var(--bb-line);
  border-radius: 50%;
  font-size: 15px;
  font-weight: 700;
  color: var(--bb-heading);
  background: var(--bb-surface);
  justify-content: center;
}

.bb button.bb__step.bb__control[disabled],
.bb .btn.bb__step.bb__control[disabled] { opacity: 0.35; cursor: not-allowed; }
.bb__step-value { min-width: 1.5em; text-align: center; font-weight: 700; }

/* Summary + CTA */
.bb__footer {
  display: grid;
  gap: 12px;
  margin-top: var(--space-lg, 24px);
  padding-top: var(--bb-gap);
  border-top: 1px solid var(--bb-line);
}

.bb__summary { display: grid; gap: 4px; font-size: var(--fs-caption, 0.875rem); }
.bb__summary-row { display: flex; justify-content: space-between; gap: 12px; }
.bb__summary-row--total { font-weight: 700; color: var(--bb-heading); }

.bb__price-row { display: flex; align-items: baseline; gap: 10px; }
.bb__price { font-size: var(--fs-h4, 1.25rem); font-weight: 700; color: var(--bb-heading); }
/* A min–max range is about twice as long as a single total, so it steps down one
   size rather than pushing the Add-to-cart control out of the footer row. */
.bb__price--range { font-size: var(--fs-body, 1rem); }

/* NOTE: the scoped compat reset above is `.bb button.bb__control` (0-2-1).
   Any rule that re-dresses a control must MATCH OR EXCEED that specificity or
   the reset silently wins and the control renders as bare inline text. */
.bb button.bb__cta.bb__control,
.bb .btn.bb__cta.bb__control {
  width: 100%;
  min-height: 52px;
  padding: 14px 24px;
  border-radius: var(--bb-radius);
  background: var(--bb-accent);
  color: var(--bb-on-accent);
  font-family: var(--ff-heading, inherit);
  font-size: var(--fs-body, 1rem);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-align: center;
  justify-content: center;
}

.bb button.bb__cta.bb__control[disabled],
.bb .btn.bb__cta.bb__control[disabled] { opacity: 0.5; cursor: not-allowed; }

.bb__notice {
  margin: 0;
  font-size: var(--fs-caption, 0.875rem);
  color: var(--bb-warning);
}

.bb__notice[hidden] { display: none; }

@media (max-width: 640px) {
  /* Narrow the option column; the included thumbnail follows it automatically
     through --bb-included-size and stays a step larger than an option thumb.
     The step widens to --space-lg here because a narrow grid stretches each
     option column well past its floor, so the small step would nearly tie. */
  .bb {
    --bb-option-min:    104px;
    --bb-included-size: calc(var(--bb-option-min) + var(--space-lg, 24px));
  }
}

/* MOBILE LEGIBILITY FLOOR.
   The theme's global type scale steps down hard below 768px
   (--fs-h5 → 10px, --fs-h4 → 13px, --fs-caption → 8px in assets/config.css),
   which rendered the group titles, helper copy and the running TOTAL at
   8–10px on a 390px viewport — unreadable for the one control a shopper has
   to read in order to spend money. The builder pins its own floor here rather
   than changing the global tokens, so nothing outside this component moves. */
@media (max-width: 767px) {
  .bb__title { font-size: 22px; }
  .bb__group-title { font-size: 16px; }
  .bb__subtitle,
  .bb__group-desc,
  .bb__notice { font-size: 13px; }
  .bb__price { font-size: 22px; }
  .bb__price--range { font-size: 16px; }
  .bb button.bb__cta.bb__control,
  .bb .btn.bb__cta.bb__control { font-size: 15px; }
  .bb__sizes-label { font-size: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  .bb__option { transition: none; }
}
