@lime-bundles/widget 4.4.0 → 4.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -3574,6 +3574,8 @@ function mergeCartLines(selections) {
3574
3574
  var ALL_TYPES2 = "__all__";
3575
3575
  var CLOSE_TRANSITION_MS2 = 300;
3576
3576
  var SEARCH_DEBOUNCE_MS2 = 200;
3577
+ var STEP_CASCADE_MS = 500;
3578
+ var AUTO_ADVANCE_HOLD_MS = 160;
3577
3579
  function createWizard(deps) {
3578
3580
  const { container, steps, selections, t } = deps;
3579
3581
  const overlay = container.querySelector("[data-modal-overlay]");
@@ -3598,6 +3600,8 @@ function createWizard(deps) {
3598
3600
  let modalOpen = false;
3599
3601
  let stepIndex = 0;
3600
3602
  let rows = [];
3603
+ let cascadeTimer = null;
3604
+ let autoAdvanceTimer = null;
3601
3605
  const productsFor = (i) => steps[i].eligibleProducts || [];
3602
3606
  const rowCapacity = {
3603
3607
  remainingSpots: () => stepHeadroom(selections, steps, stepIndex),
@@ -3694,6 +3698,18 @@ function createWizard(deps) {
3694
3698
  for (const r of rows) r.refresh();
3695
3699
  updateModalMeta();
3696
3700
  }
3701
+ function maybeAutoAdvance() {
3702
+ if (!deps.autoAdvance) return;
3703
+ if (stepIndex >= steps.length - 1) return;
3704
+ if (stepHeadroom(selections, steps, stepIndex) !== 0) return;
3705
+ const from = stepIndex;
3706
+ if (autoAdvanceTimer !== null) clearTimeout(autoAdvanceTimer);
3707
+ autoAdvanceTimer = setTimeout(() => {
3708
+ autoAdvanceTimer = null;
3709
+ if (!modalOpen) return;
3710
+ goToStep(from + 1);
3711
+ }, AUTO_ADVANCE_HOLD_MS);
3712
+ }
3697
3713
  function buildProductList(forStep) {
3698
3714
  if (!modalList) return;
3699
3715
  deps.dropdown?.unbindAll(modalList);
@@ -3710,6 +3726,7 @@ function createWizard(deps) {
3710
3726
  onCommittedQtyChanged: () => {
3711
3727
  deps.onSelectionChanged();
3712
3728
  refresh();
3729
+ maybeAutoAdvance();
3713
3730
  }
3714
3731
  });
3715
3732
  rows.push(row);
@@ -3789,6 +3806,7 @@ function createWizard(deps) {
3789
3806
  selections[stepIndex].push(newItem);
3790
3807
  deps.onSelectionChanged();
3791
3808
  refresh();
3809
+ maybeAutoAdvance();
3792
3810
  }
3793
3811
  if (modalList) modalList.addEventListener("click", onListClick);
3794
3812
  function buildFilters(forStep) {
@@ -3878,7 +3896,29 @@ function createWizard(deps) {
3878
3896
  });
3879
3897
  }
3880
3898
  function goToStep(i, opts = {}) {
3881
- stepIndex = Math.max(0, Math.min(steps.length - 1, i));
3899
+ const target = Math.max(0, Math.min(steps.length - 1, i));
3900
+ if (autoAdvanceTimer !== null) {
3901
+ clearTimeout(autoAdvanceTimer);
3902
+ autoAdvanceTimer = null;
3903
+ }
3904
+ if (modalDialog) {
3905
+ if (cascadeTimer !== null) clearTimeout(cascadeTimer);
3906
+ cascadeTimer = null;
3907
+ modalDialog.removeAttribute("data-step-transition");
3908
+ if (opts.animate !== false && target !== stepIndex) {
3909
+ void modalDialog.offsetHeight;
3910
+ modalDialog.setAttribute(
3911
+ "data-step-transition",
3912
+ target > stepIndex ? "forward" : "back"
3913
+ );
3914
+ const dialog = modalDialog;
3915
+ cascadeTimer = setTimeout(() => {
3916
+ cascadeTimer = null;
3917
+ dialog.removeAttribute("data-step-transition");
3918
+ }, STEP_CASCADE_MS);
3919
+ }
3920
+ }
3921
+ stepIndex = target;
3882
3922
  buildProductList(stepIndex);
3883
3923
  buildFilters(stepIndex);
3884
3924
  activeType = ALL_TYPES2;
@@ -3903,7 +3943,10 @@ function createWizard(deps) {
3903
3943
  function open(atStep) {
3904
3944
  if (!overlay || modalOpen) return;
3905
3945
  modalOpen = true;
3906
- goToStep(typeof atStep === "number" ? atStep : 0, { skipFocus: true });
3946
+ goToStep(typeof atStep === "number" ? atStep : 0, {
3947
+ skipFocus: true,
3948
+ animate: false
3949
+ });
3907
3950
  overlay.style.display = "";
3908
3951
  void overlay.offsetHeight;
3909
3952
  overlay.classList.add("lb-mix-match__modal-overlay--open");
@@ -3916,6 +3959,14 @@ function createWizard(deps) {
3916
3959
  function close() {
3917
3960
  if (!overlay || !modalOpen) return;
3918
3961
  modalOpen = false;
3962
+ if (autoAdvanceTimer !== null) {
3963
+ clearTimeout(autoAdvanceTimer);
3964
+ autoAdvanceTimer = null;
3965
+ }
3966
+ if (cascadeTimer !== null) {
3967
+ clearTimeout(cascadeTimer);
3968
+ cascadeTimer = null;
3969
+ }
3919
3970
  overlay.classList.remove("lb-mix-match__modal-overlay--open");
3920
3971
  unlock();
3921
3972
  setTimeout(() => {
@@ -4172,6 +4223,8 @@ function renderMultiStepBundle(container, bundle, onAddToCart, onCleanup) {
4172
4223
  rulesMap,
4173
4224
  showQtySelector: wc.mixMatchShowQuantitySelector !== false,
4174
4225
  showTypeFilters: wc.mixMatchShowTypeFilters !== false,
4226
+ // Off by default: a stored config predating the key must not advance.
4227
+ autoAdvance: wc.multiStepAutoAdvance === true,
4175
4228
  formatMoney,
4176
4229
  dropdown: void 0,
4177
4230
  portalTarget: null,
@@ -4301,11 +4354,18 @@ var BUNDLE_BASE_CSS = `/* Lime Bundles \u2014 shared base styles for all bundle
4301
4354
  --lb-list-max-height: 360px;
4302
4355
  /* Depth of the soft fade at a scroll list's clipped edge. */
4303
4356
  --lb-edge-fade-size: 20px;
4304
- /* Derived "small" corner radius for inner controls (thumbnails, variant
4305
- selects, the qty chip). One step tighter than the global --lb-radius so
4306
- small elements stay proportionate. Both come from the global radius
4307
- preset; nothing else sets a radius. */
4308
- --lb-radius-sm: max(0px, calc(var(--lb-radius) - 4px));
4357
+ /* Derived "small" corner radius for chips and badges \u2014 the low-stock badge,
4358
+ the volume tier badge, the multi-step count chip. Controls and media
4359
+ (thumbnails, selects, steppers, buttons) take the full --lb-radius: they
4360
+ are the elements the merchant is looking at when they pick a preset, and
4361
+ the picker's own help text already promises they follow it.
4362
+
4363
+ Proportional rather than a fixed subtraction. At "subtle" (6px) minus-4px
4364
+ left 2px, which reads as square \u2014 the merchant saw a picker set to Subtle
4365
+ render with sharp corners (issue #363). Two thirds holds the proportion at
4366
+ every preset: none 0, subtle 4px, rounded 8px, round 12px. No max() needed,
4367
+ since 0 \xD7 \u2154 is 0. */
4368
+ --lb-radius-sm: calc(var(--lb-radius) * 2 / 3);
4309
4369
 
4310
4370
  font-family: inherit;
4311
4371
  font-size: 16px;
@@ -4469,7 +4529,7 @@ var BUNDLE_BASE_CSS = `/* Lime Bundles \u2014 shared base styles for all bundle
4469
4529
  ratio. Default keeps the historical 1:1 behaviour. */
4470
4530
  aspect-ratio: var(--lb-thumbnail-aspect-ratio, 1 / 1);
4471
4531
  background: var(--lb-thumbnail-bg);
4472
- border-radius: var(--lb-radius-sm);
4532
+ border-radius: var(--lb-radius);
4473
4533
  overflow: hidden;
4474
4534
  display: flex;
4475
4535
  align-items: center;
@@ -5019,12 +5079,12 @@ var BUNDLE_FIXED_CSS = `/* Lime Bundles \u2014 Fixed bundle styles */
5019
5079
  .lb-fixed .lb-bundle-thumbnail {
5020
5080
  width: 60px;
5021
5081
  min-width: 60px;
5022
- border-radius: var(--lb-radius-sm);
5082
+ border-radius: var(--lb-radius);
5023
5083
  box-sizing: border-box;
5024
5084
  }
5025
5085
 
5026
5086
  .lb-fixed .lb-bundle-thumbnail img {
5027
- border-radius: var(--lb-radius-sm);
5087
+ border-radius: var(--lb-radius);
5028
5088
  border: none;
5029
5089
  }
5030
5090
 
@@ -5041,7 +5101,7 @@ var BUNDLE_FIXED_CSS = `/* Lime Bundles \u2014 Fixed bundle styles */
5041
5101
  display: var(--lb-product-qty-chip-display, inline-flex);
5042
5102
  align-items: center;
5043
5103
  justify-content: center;
5044
- border-radius: var(--lb-radius-sm);
5104
+ border-radius: var(--lb-radius);
5045
5105
  background: color-mix(in srgb, var(--lb-text) 7%, transparent);
5046
5106
  color: color-mix(in srgb, var(--lb-text) 75%, transparent);
5047
5107
  font-size: 13px;
@@ -5057,7 +5117,7 @@ var BUNDLE_FIXED_CSS = `/* Lime Bundles \u2014 Fixed bundle styles */
5057
5117
  .lb-bundle-variant-select {
5058
5118
  display: inline-block;
5059
5119
  border: var(--lb-border-width) solid var(--lb-border);
5060
- border-radius: var(--lb-radius-sm);
5120
+ border-radius: var(--lb-radius);
5061
5121
  padding: 8px 32px 8px 12px;
5062
5122
  font-size: 12px;
5063
5123
  line-height: 16px;
@@ -5205,12 +5265,12 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5205
5265
  position: relative;
5206
5266
  width: 60px;
5207
5267
  min-width: 60px;
5208
- border-radius: var(--lb-radius-sm);
5268
+ border-radius: var(--lb-radius);
5209
5269
  box-sizing: border-box;
5210
5270
  }
5211
5271
 
5212
5272
  .lb-mix-match .lb-bundle-thumbnail img {
5213
- border-radius: var(--lb-radius-sm);
5273
+ border-radius: var(--lb-radius);
5214
5274
  border: none;
5215
5275
  }
5216
5276
 
@@ -5376,14 +5436,26 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5376
5436
  color: inherit;
5377
5437
  }
5378
5438
 
5379
- /* Derived "small" radius for the picker's inner controls (search, thumbnails,
5380
- variant select, qty stepper, Add/Done buttons), one step tighter than the
5381
- modal's --lb-picker-radius \u2014 the picker-scoped mirror of --lb-radius-sm in the
5382
- main widget. Defined on the overlay so the modal AND the variant listbox
5383
- (which portals up to [data-modal-overlay]) both inherit it. The modal shell
5384
- and product tiles keep the full --lb-picker-radius. */
5439
+ /* Derived "small" radius for the picker's chips and badges \u2014 the progress
5440
+ segments, the "Added" badge, the close button, the filter pills. The
5441
+ picker-scoped mirror of --lb-radius-sm, and proportional for the same reason
5442
+ (see bundle-base.css).
5443
+
5444
+ Everything the merchant would call a control or an image \u2014 the modal, search,
5445
+ product tiles, thumbnails, variant dropdown, quantity stepper and the
5446
+ buttons \u2014 takes the full --lb-picker-radius instead. That is what the
5447
+ editor's own Borders copy promises them, and the reduced tier had it
5448
+ rendering square at the Subtle preset (issue #363).
5449
+
5450
+ Declared on BOTH hosts the modal can live under. On the storefront it portals
5451
+ to [data-modal-overlay], which the variant listbox portals up to as well. In
5452
+ the admin widget editor there is no overlay at all \u2014 the preview renders the
5453
+ modal directly under .lb-bundle-widget \u2014 so scoping this to the overlay alone
5454
+ left the variable undefined there and every control using it fell back to
5455
+ square corners while the modal and tiles rounded correctly (issue #363). */
5456
+ .lb-bundle-widget,
5385
5457
  [data-modal-overlay] {
5386
- --lb-picker-radius-sm: max(0px, calc(var(--lb-picker-radius) - 4px));
5458
+ --lb-picker-radius-sm: calc(var(--lb-picker-radius) * 2 / 3);
5387
5459
  }
5388
5460
 
5389
5461
  /* === Modal Overlay === */
@@ -5480,7 +5552,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5480
5552
  border: none;
5481
5553
  cursor: pointer;
5482
5554
  color: var(--lb-picker-text);
5483
- border-radius: 8px;
5555
+ border-radius: var(--lb-picker-radius-sm);
5484
5556
  padding: 0;
5485
5557
  margin: -12px -12px 0 0;
5486
5558
  transition: background 0.25s ease;
@@ -5510,7 +5582,9 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5510
5582
  .lb-mix-match__filter {
5511
5583
  padding: 6px 14px;
5512
5584
  border: var(--lb-picker-border-width) solid var(--lb-picker-border-color);
5513
- border-radius: 999px;
5585
+ /* Pills followed the merchant's picker radius as of #363 \u2014 a fixed 999px
5586
+ read as a stray rounded shape in a picker set to None or Subtle. */
5587
+ border-radius: var(--lb-picker-radius-sm);
5514
5588
  background: transparent;
5515
5589
  color: var(--lb-picker-text);
5516
5590
  font-family: inherit;
@@ -5564,7 +5638,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5564
5638
  width: 100%;
5565
5639
  padding: 12px 40px 12px 44px;
5566
5640
  border: var(--lb-picker-border-width) solid var(--lb-picker-border-color);
5567
- border-radius: var(--lb-picker-radius-sm);
5641
+ border-radius: var(--lb-picker-radius);
5568
5642
  font-size: 16px;
5569
5643
  line-height: 20px;
5570
5644
  color: var(--lb-picker-text);
@@ -5664,7 +5738,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5664
5738
  independent from the main widget's thumbnailRatio so a merchant can
5665
5739
  e.g. show tall picker thumbs with square main thumbs. */
5666
5740
  aspect-ratio: var(--lb-picker-thumbnail-aspect-ratio, 1 / 1);
5667
- border-radius: var(--lb-picker-radius-sm);
5741
+ border-radius: var(--lb-picker-radius);
5668
5742
  box-sizing: border-box;
5669
5743
  overflow: hidden;
5670
5744
  background: var(--lb-thumbnail-bg);
@@ -5677,7 +5751,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5677
5751
  to auto/contain so the image renders uncropped at intrinsic ratio. */
5678
5752
  height: var(--lb-picker-thumbnail-img-height, 100%);
5679
5753
  object-fit: var(--lb-picker-thumbnail-img-fit, cover);
5680
- border-radius: var(--lb-picker-radius-sm);
5754
+ border-radius: var(--lb-picker-radius);
5681
5755
  }
5682
5756
 
5683
5757
  .lb-mix-match__modal-product-info {
@@ -5752,7 +5826,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5752
5826
  font-size: 12px;
5753
5827
  padding: 4px 24px 4px 8px;
5754
5828
  border: var(--lb-picker-border-width) solid var(--lb-picker-border-color);
5755
- border-radius: var(--lb-picker-radius-sm);
5829
+ border-radius: var(--lb-picker-radius);
5756
5830
  background-color: var(--lb-picker-bg);
5757
5831
  background-image: var(--lb-picker-variant-chevron);
5758
5832
  background-repeat: no-repeat;
@@ -5803,7 +5877,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5803
5877
  width: 100%;
5804
5878
  flex-shrink: 0;
5805
5879
  border: var(--lb-picker-border-width) solid var(--lb-picker-border-color);
5806
- border-radius: var(--lb-picker-radius-sm);
5880
+ border-radius: var(--lb-picker-radius);
5807
5881
  background-color: var(--lb-picker-bg);
5808
5882
  overflow: hidden;
5809
5883
  box-sizing: border-box;
@@ -5880,7 +5954,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5880
5954
  background: var(--lb-picker-add-bg);
5881
5955
  color: var(--lb-picker-add-label);
5882
5956
  border: var(--lb-picker-add-border-width) solid var(--lb-picker-add-border-color);
5883
- border-radius: var(--lb-picker-radius-sm);
5957
+ border-radius: var(--lb-picker-radius);
5884
5958
  box-sizing: border-box;
5885
5959
  font-size: 12px;
5886
5960
  font-weight: 600;
@@ -6021,7 +6095,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
6021
6095
  background: var(--lb-picker-add-bg);
6022
6096
  color: var(--lb-picker-add-label);
6023
6097
  border: var(--lb-picker-add-border-width) solid var(--lb-picker-add-border-color);
6024
- border-radius: var(--lb-picker-radius-sm);
6098
+ border-radius: var(--lb-picker-radius);
6025
6099
  box-sizing: border-box;
6026
6100
  font-family: inherit;
6027
6101
  font-size: 14px;
@@ -6070,7 +6144,9 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
6070
6144
  .lb-mix-match__modal {
6071
6145
  max-width: 100%;
6072
6146
  max-height: 90vh;
6073
- border-radius: 16px 16px 0 0;
6147
+ /* Bottom sheet: only the top corners round, but they round to whatever the
6148
+ merchant picked rather than a fixed 16px (issue #363). */
6149
+ border-radius: var(--lb-picker-radius) var(--lb-picker-radius) 0 0;
6074
6150
  transform: translateY(100%);
6075
6151
  }
6076
6152
 
@@ -6337,12 +6413,12 @@ var BUNDLE_BOGO_CSS = `/* Lime Bundles \u2014 BOGO (Buy X Get Y) bundle styles *
6337
6413
  .lb-bogo .lb-bundle-thumbnail {
6338
6414
  width: 60px;
6339
6415
  min-width: 60px;
6340
- border-radius: var(--lb-radius-sm);
6416
+ border-radius: var(--lb-radius);
6341
6417
  box-sizing: border-box;
6342
6418
  }
6343
6419
 
6344
6420
  .lb-bogo .lb-bundle-thumbnail img {
6345
- border-radius: var(--lb-radius-sm);
6421
+ border-radius: var(--lb-radius);
6346
6422
  border: none;
6347
6423
  }
6348
6424
 
@@ -6463,6 +6539,13 @@ var BUNDLE_MULTI_STEP_CSS = `/**
6463
6539
  cursor: pointer;
6464
6540
  box-sizing: border-box;
6465
6541
  transition: background-color 0.25s ease;
6542
+ /* Deliberately no border-radius. This row paints the checklist hairline as
6543
+ its own border-top (see the run rule above), and a radius tapers that
6544
+ border into the corner arcs \u2014 the dividers came out visibly curved at the
6545
+ "round" preset (issue #363). A full-bleed list row is meant to be square
6546
+ anyway; the hover tint below spans the card width, so it has no corner to
6547
+ round against. The :focus-visible radius is fine: an outline is a
6548
+ separate paint and never touches the border. */
6466
6549
  }
6467
6550
 
6468
6551
  .lb-multi-step__step-row:hover {
@@ -6610,7 +6693,7 @@ var BUNDLE_MULTI_STEP_CSS = `/**
6610
6693
  padding: 10px 24px;
6611
6694
  background: none;
6612
6695
  border: var(--lb-picker-border-width) solid var(--lb-picker-border-color);
6613
- border-radius: var(--lb-picker-radius-sm);
6696
+ border-radius: var(--lb-picker-radius);
6614
6697
  box-sizing: border-box;
6615
6698
  color: var(--lb-picker-text);
6616
6699
  font-family: inherit;
@@ -6628,6 +6711,108 @@ var BUNDLE_MULTI_STEP_CSS = `/**
6628
6711
  outline: 2px solid var(--lb-primary-color);
6629
6712
  outline-offset: 2px;
6630
6713
  }
6714
+
6715
+ /* \u2500\u2500 Step-change transition \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
6716
+ Moving between steps swaps the whole step-scoped region in a single
6717
+ paint, which reads as nothing happening (or as a glitch) rather than
6718
+ as arriving somewhere new \u2014 and worst of all under auto-advance,
6719
+ where the shopper never clicked anything. So the step assembles
6720
+ instead of arriving whole: the step label leads, the filter pills
6721
+ follow, then the product cards one after another. Staging is what
6722
+ makes the change legible; a uniform slide of everything at once only
6723
+ wobbles the card.
6724
+
6725
+ The wizard stamps data-step-transition="forward" | "back" on the
6726
+ dialog on every step change (manual Next/Back and auto-advance
6727
+ alike, never on open, where the modal entrance already carries the
6728
+ motion), and clears it again once the cascade has played \u2014 see
6729
+ STEP_CASCADE_MS in multi-step/wizard.ts. That clear is load-bearing,
6730
+ not tidiness: search and filter hide cards with .lb-hidden
6731
+ (display: none), and restoring display restarts a card's animation,
6732
+ so a live attribute would replay the whole cascade on every
6733
+ keystroke that reveals a card.
6734
+
6735
+ Two elements deliberately hold still. The footer, because Back/Next
6736
+ are the shopper's anchor while everything above them moves. And the
6737
+ progress rail, because it is the one thing that answers "where am I
6738
+ now" \u2014 animating the shopper's only orientation cue is what made the
6739
+ previous version hard to read. Its segment fill carries its own
6740
+ state change already. */
6741
+ @keyframes lb-multi-step-cascade-fwd {
6742
+ from {
6743
+ opacity: 0;
6744
+ transform: translateY(10px);
6745
+ }
6746
+ }
6747
+
6748
+ @keyframes lb-multi-step-cascade-back {
6749
+ from {
6750
+ opacity: 0;
6751
+ transform: translateY(-10px);
6752
+ }
6753
+ }
6754
+
6755
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-subtitle {
6756
+ animation: lb-multi-step-cascade-fwd 0.2s ease-out both;
6757
+ }
6758
+
6759
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__filters {
6760
+ animation: lb-multi-step-cascade-fwd 0.2s ease-out 0.05s both;
6761
+ }
6762
+
6763
+ /* Cards stagger 30ms apart, but only the first four: a step can hold
6764
+ dozens of products and the two-column grid shows about four at a
6765
+ time, so past that the stagger is below the fold and would only add
6766
+ lag. Everything from the fifth on shares the fourth's landing. */
6767
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-list > * {
6768
+ animation: lb-multi-step-cascade-fwd 0.22s ease-out 0.2s both;
6769
+ }
6770
+
6771
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-list > :nth-child(1) {
6772
+ animation-delay: 0.09s;
6773
+ }
6774
+
6775
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-list > :nth-child(2) {
6776
+ animation-delay: 0.12s;
6777
+ }
6778
+
6779
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-list > :nth-child(3) {
6780
+ animation-delay: 0.15s;
6781
+ }
6782
+
6783
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-list > :nth-child(4) {
6784
+ animation-delay: 0.18s;
6785
+ }
6786
+
6787
+ /* Going back runs the same cascade in the same order \u2014 only the offset
6788
+ flips, so the shopper still reads which way they moved. Overrides
6789
+ the name alone; the staggered delays above must survive. */
6790
+ .lb-mix-match__modal[data-step-transition="back"] .lb-mix-match__modal-subtitle,
6791
+ .lb-mix-match__modal[data-step-transition="back"] .lb-mix-match__filters,
6792
+ .lb-mix-match__modal[data-step-transition="back"] .lb-mix-match__modal-list > * {
6793
+ animation-name: lb-multi-step-cascade-back;
6794
+ }
6795
+
6796
+ @keyframes lb-multi-step-cascade-fade {
6797
+ from {
6798
+ opacity: 0;
6799
+ }
6800
+ }
6801
+
6802
+ /* Reduced motion keeps the fade and drops the travel and the stagger:
6803
+ the step change still has to be perceptible, which is the whole
6804
+ point of this block. The card selector is :nth-child(n) rather than
6805
+ * on purpose \u2014 a plain * loses to the :nth-child(1..4) delays above
6806
+ on specificity, which would leave the stagger running with nothing
6807
+ moving. :nth-child(n) matches every child at equal specificity and
6808
+ wins on order. */
6809
+ @media (prefers-reduced-motion: reduce) {
6810
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-subtitle,
6811
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__filters,
6812
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-list > :nth-child(n) {
6813
+ animation: lb-multi-step-cascade-fade 0.15s ease-out both;
6814
+ }
6815
+ }
6631
6816
  `;
6632
6817
  var BUNDLE_DROPDOWN_CSS = `/**
6633
6818
  * Lime Bundles \u2014 Custom variant-picker dropdown styling.
@@ -6675,7 +6860,7 @@ var BUNDLE_DROPDOWN_CSS = `/**
6675
6860
  gap: 8px;
6676
6861
  width: 100%;
6677
6862
  border: var(--lb-border-width) solid var(--lb-border);
6678
- border-radius: var(--lb-radius-sm);
6863
+ border-radius: var(--lb-radius);
6679
6864
  padding: 8px 12px;
6680
6865
  font-size: 12px;
6681
6866
  line-height: 16px;
@@ -6738,7 +6923,7 @@ var BUNDLE_DROPDOWN_CSS = `/**
6738
6923
  background: var(--lb-bg);
6739
6924
  color: var(--lb-text);
6740
6925
  border: var(--lb-border-width) solid var(--lb-border);
6741
- border-radius: var(--lb-radius-sm);
6926
+ border-radius: var(--lb-radius);
6742
6927
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
6743
6928
  overflow-y: auto;
6744
6929
  overflow-x: hidden;
@@ -6799,6 +6984,10 @@ var BUNDLE_DROPDOWN_CSS = `/**
6799
6984
  overflow: hidden;
6800
6985
  text-overflow: ellipsis;
6801
6986
  color: var(--lb-text);
6987
+ /* The active/hover tint below fills the option, so it rounds with the rest
6988
+ of the widget rather than squaring off against the listbox corner it sits
6989
+ in (issue #363). */
6990
+ border-radius: var(--lb-radius-sm);
6802
6991
  }
6803
6992
 
6804
6993
  .lb-dropdown-option[aria-selected="true"] {
@@ -6857,7 +7046,7 @@ var BUNDLE_DROPDOWN_CSS = `/**
6857
7046
  .lb-mix-match__modal .lb-dropdown-trigger {
6858
7047
  border-color: var(--lb-picker-border-color);
6859
7048
  border-width: var(--lb-picker-border-width);
6860
- border-radius: var(--lb-picker-radius-sm);
7049
+ border-radius: var(--lb-picker-radius);
6861
7050
  background: var(--lb-picker-bg);
6862
7051
  color: var(--lb-picker-text);
6863
7052
  /* Match the picker qty stepper + Add button height (border-box so 32px is
@@ -6878,13 +7067,17 @@ var BUNDLE_DROPDOWN_CSS = `/**
6878
7067
  [data-modal-overlay] > .lb-dropdown-listbox {
6879
7068
  border-color: var(--lb-picker-border-color);
6880
7069
  border-width: var(--lb-picker-border-width);
6881
- border-radius: var(--lb-picker-radius-sm);
7070
+ border-radius: var(--lb-picker-radius);
6882
7071
  background: var(--lb-picker-bg);
6883
7072
  color: var(--lb-picker-text);
6884
7073
  scrollbar-color: color-mix(in srgb, var(--lb-picker-text) 15%, transparent)
6885
7074
  color-mix(in srgb, var(--lb-picker-text) 2%, transparent);
6886
7075
  }
6887
7076
 
7077
+ [data-modal-overlay] > .lb-dropdown-listbox .lb-dropdown-option {
7078
+ border-radius: var(--lb-picker-radius-sm);
7079
+ }
7080
+
6888
7081
  [data-modal-overlay] > .lb-dropdown-listbox::-webkit-scrollbar-track {
6889
7082
  background: color-mix(in srgb, var(--lb-picker-text) 2%, transparent);
6890
7083
  border-radius: 2px;