@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.js CHANGED
@@ -3582,6 +3582,8 @@ function mergeCartLines(selections) {
3582
3582
  var ALL_TYPES2 = "__all__";
3583
3583
  var CLOSE_TRANSITION_MS2 = 300;
3584
3584
  var SEARCH_DEBOUNCE_MS2 = 200;
3585
+ var STEP_CASCADE_MS = 500;
3586
+ var AUTO_ADVANCE_HOLD_MS = 160;
3585
3587
  function createWizard(deps) {
3586
3588
  const { container, steps, selections, t } = deps;
3587
3589
  const overlay = container.querySelector("[data-modal-overlay]");
@@ -3606,6 +3608,8 @@ function createWizard(deps) {
3606
3608
  let modalOpen = false;
3607
3609
  let stepIndex = 0;
3608
3610
  let rows = [];
3611
+ let cascadeTimer = null;
3612
+ let autoAdvanceTimer = null;
3609
3613
  const productsFor = (i) => steps[i].eligibleProducts || [];
3610
3614
  const rowCapacity = {
3611
3615
  remainingSpots: () => stepHeadroom(selections, steps, stepIndex),
@@ -3702,6 +3706,18 @@ function createWizard(deps) {
3702
3706
  for (const r of rows) r.refresh();
3703
3707
  updateModalMeta();
3704
3708
  }
3709
+ function maybeAutoAdvance() {
3710
+ if (!deps.autoAdvance) return;
3711
+ if (stepIndex >= steps.length - 1) return;
3712
+ if (stepHeadroom(selections, steps, stepIndex) !== 0) return;
3713
+ const from = stepIndex;
3714
+ if (autoAdvanceTimer !== null) clearTimeout(autoAdvanceTimer);
3715
+ autoAdvanceTimer = setTimeout(() => {
3716
+ autoAdvanceTimer = null;
3717
+ if (!modalOpen) return;
3718
+ goToStep(from + 1);
3719
+ }, AUTO_ADVANCE_HOLD_MS);
3720
+ }
3705
3721
  function buildProductList(forStep) {
3706
3722
  if (!modalList) return;
3707
3723
  deps.dropdown?.unbindAll(modalList);
@@ -3718,6 +3734,7 @@ function createWizard(deps) {
3718
3734
  onCommittedQtyChanged: () => {
3719
3735
  deps.onSelectionChanged();
3720
3736
  refresh();
3737
+ maybeAutoAdvance();
3721
3738
  }
3722
3739
  });
3723
3740
  rows.push(row);
@@ -3797,6 +3814,7 @@ function createWizard(deps) {
3797
3814
  selections[stepIndex].push(newItem);
3798
3815
  deps.onSelectionChanged();
3799
3816
  refresh();
3817
+ maybeAutoAdvance();
3800
3818
  }
3801
3819
  if (modalList) modalList.addEventListener("click", onListClick);
3802
3820
  function buildFilters(forStep) {
@@ -3886,7 +3904,29 @@ function createWizard(deps) {
3886
3904
  });
3887
3905
  }
3888
3906
  function goToStep(i, opts = {}) {
3889
- stepIndex = Math.max(0, Math.min(steps.length - 1, i));
3907
+ const target = Math.max(0, Math.min(steps.length - 1, i));
3908
+ if (autoAdvanceTimer !== null) {
3909
+ clearTimeout(autoAdvanceTimer);
3910
+ autoAdvanceTimer = null;
3911
+ }
3912
+ if (modalDialog) {
3913
+ if (cascadeTimer !== null) clearTimeout(cascadeTimer);
3914
+ cascadeTimer = null;
3915
+ modalDialog.removeAttribute("data-step-transition");
3916
+ if (opts.animate !== false && target !== stepIndex) {
3917
+ void modalDialog.offsetHeight;
3918
+ modalDialog.setAttribute(
3919
+ "data-step-transition",
3920
+ target > stepIndex ? "forward" : "back"
3921
+ );
3922
+ const dialog = modalDialog;
3923
+ cascadeTimer = setTimeout(() => {
3924
+ cascadeTimer = null;
3925
+ dialog.removeAttribute("data-step-transition");
3926
+ }, STEP_CASCADE_MS);
3927
+ }
3928
+ }
3929
+ stepIndex = target;
3890
3930
  buildProductList(stepIndex);
3891
3931
  buildFilters(stepIndex);
3892
3932
  activeType = ALL_TYPES2;
@@ -3911,7 +3951,10 @@ function createWizard(deps) {
3911
3951
  function open(atStep) {
3912
3952
  if (!overlay || modalOpen) return;
3913
3953
  modalOpen = true;
3914
- goToStep(typeof atStep === "number" ? atStep : 0, { skipFocus: true });
3954
+ goToStep(typeof atStep === "number" ? atStep : 0, {
3955
+ skipFocus: true,
3956
+ animate: false
3957
+ });
3915
3958
  overlay.style.display = "";
3916
3959
  void overlay.offsetHeight;
3917
3960
  overlay.classList.add("lb-mix-match__modal-overlay--open");
@@ -3924,6 +3967,14 @@ function createWizard(deps) {
3924
3967
  function close() {
3925
3968
  if (!overlay || !modalOpen) return;
3926
3969
  modalOpen = false;
3970
+ if (autoAdvanceTimer !== null) {
3971
+ clearTimeout(autoAdvanceTimer);
3972
+ autoAdvanceTimer = null;
3973
+ }
3974
+ if (cascadeTimer !== null) {
3975
+ clearTimeout(cascadeTimer);
3976
+ cascadeTimer = null;
3977
+ }
3927
3978
  overlay.classList.remove("lb-mix-match__modal-overlay--open");
3928
3979
  unlock();
3929
3980
  setTimeout(() => {
@@ -4180,6 +4231,8 @@ function renderMultiStepBundle(container, bundle, onAddToCart, onCleanup) {
4180
4231
  rulesMap,
4181
4232
  showQtySelector: wc.mixMatchShowQuantitySelector !== false,
4182
4233
  showTypeFilters: wc.mixMatchShowTypeFilters !== false,
4234
+ // Off by default: a stored config predating the key must not advance.
4235
+ autoAdvance: wc.multiStepAutoAdvance === true,
4183
4236
  formatMoney,
4184
4237
  dropdown: void 0,
4185
4238
  portalTarget: null,
@@ -4309,11 +4362,18 @@ var BUNDLE_BASE_CSS = `/* Lime Bundles \u2014 shared base styles for all bundle
4309
4362
  --lb-list-max-height: 360px;
4310
4363
  /* Depth of the soft fade at a scroll list's clipped edge. */
4311
4364
  --lb-edge-fade-size: 20px;
4312
- /* Derived "small" corner radius for inner controls (thumbnails, variant
4313
- selects, the qty chip). One step tighter than the global --lb-radius so
4314
- small elements stay proportionate. Both come from the global radius
4315
- preset; nothing else sets a radius. */
4316
- --lb-radius-sm: max(0px, calc(var(--lb-radius) - 4px));
4365
+ /* Derived "small" corner radius for chips and badges \u2014 the low-stock badge,
4366
+ the volume tier badge, the multi-step count chip. Controls and media
4367
+ (thumbnails, selects, steppers, buttons) take the full --lb-radius: they
4368
+ are the elements the merchant is looking at when they pick a preset, and
4369
+ the picker's own help text already promises they follow it.
4370
+
4371
+ Proportional rather than a fixed subtraction. At "subtle" (6px) minus-4px
4372
+ left 2px, which reads as square \u2014 the merchant saw a picker set to Subtle
4373
+ render with sharp corners (issue #363). Two thirds holds the proportion at
4374
+ every preset: none 0, subtle 4px, rounded 8px, round 12px. No max() needed,
4375
+ since 0 \xD7 \u2154 is 0. */
4376
+ --lb-radius-sm: calc(var(--lb-radius) * 2 / 3);
4317
4377
 
4318
4378
  font-family: inherit;
4319
4379
  font-size: 16px;
@@ -4477,7 +4537,7 @@ var BUNDLE_BASE_CSS = `/* Lime Bundles \u2014 shared base styles for all bundle
4477
4537
  ratio. Default keeps the historical 1:1 behaviour. */
4478
4538
  aspect-ratio: var(--lb-thumbnail-aspect-ratio, 1 / 1);
4479
4539
  background: var(--lb-thumbnail-bg);
4480
- border-radius: var(--lb-radius-sm);
4540
+ border-radius: var(--lb-radius);
4481
4541
  overflow: hidden;
4482
4542
  display: flex;
4483
4543
  align-items: center;
@@ -5027,12 +5087,12 @@ var BUNDLE_FIXED_CSS = `/* Lime Bundles \u2014 Fixed bundle styles */
5027
5087
  .lb-fixed .lb-bundle-thumbnail {
5028
5088
  width: 60px;
5029
5089
  min-width: 60px;
5030
- border-radius: var(--lb-radius-sm);
5090
+ border-radius: var(--lb-radius);
5031
5091
  box-sizing: border-box;
5032
5092
  }
5033
5093
 
5034
5094
  .lb-fixed .lb-bundle-thumbnail img {
5035
- border-radius: var(--lb-radius-sm);
5095
+ border-radius: var(--lb-radius);
5036
5096
  border: none;
5037
5097
  }
5038
5098
 
@@ -5049,7 +5109,7 @@ var BUNDLE_FIXED_CSS = `/* Lime Bundles \u2014 Fixed bundle styles */
5049
5109
  display: var(--lb-product-qty-chip-display, inline-flex);
5050
5110
  align-items: center;
5051
5111
  justify-content: center;
5052
- border-radius: var(--lb-radius-sm);
5112
+ border-radius: var(--lb-radius);
5053
5113
  background: color-mix(in srgb, var(--lb-text) 7%, transparent);
5054
5114
  color: color-mix(in srgb, var(--lb-text) 75%, transparent);
5055
5115
  font-size: 13px;
@@ -5065,7 +5125,7 @@ var BUNDLE_FIXED_CSS = `/* Lime Bundles \u2014 Fixed bundle styles */
5065
5125
  .lb-bundle-variant-select {
5066
5126
  display: inline-block;
5067
5127
  border: var(--lb-border-width) solid var(--lb-border);
5068
- border-radius: var(--lb-radius-sm);
5128
+ border-radius: var(--lb-radius);
5069
5129
  padding: 8px 32px 8px 12px;
5070
5130
  font-size: 12px;
5071
5131
  line-height: 16px;
@@ -5213,12 +5273,12 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5213
5273
  position: relative;
5214
5274
  width: 60px;
5215
5275
  min-width: 60px;
5216
- border-radius: var(--lb-radius-sm);
5276
+ border-radius: var(--lb-radius);
5217
5277
  box-sizing: border-box;
5218
5278
  }
5219
5279
 
5220
5280
  .lb-mix-match .lb-bundle-thumbnail img {
5221
- border-radius: var(--lb-radius-sm);
5281
+ border-radius: var(--lb-radius);
5222
5282
  border: none;
5223
5283
  }
5224
5284
 
@@ -5384,14 +5444,26 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5384
5444
  color: inherit;
5385
5445
  }
5386
5446
 
5387
- /* Derived "small" radius for the picker's inner controls (search, thumbnails,
5388
- variant select, qty stepper, Add/Done buttons), one step tighter than the
5389
- modal's --lb-picker-radius \u2014 the picker-scoped mirror of --lb-radius-sm in the
5390
- main widget. Defined on the overlay so the modal AND the variant listbox
5391
- (which portals up to [data-modal-overlay]) both inherit it. The modal shell
5392
- and product tiles keep the full --lb-picker-radius. */
5447
+ /* Derived "small" radius for the picker's chips and badges \u2014 the progress
5448
+ segments, the "Added" badge, the close button, the filter pills. The
5449
+ picker-scoped mirror of --lb-radius-sm, and proportional for the same reason
5450
+ (see bundle-base.css).
5451
+
5452
+ Everything the merchant would call a control or an image \u2014 the modal, search,
5453
+ product tiles, thumbnails, variant dropdown, quantity stepper and the
5454
+ buttons \u2014 takes the full --lb-picker-radius instead. That is what the
5455
+ editor's own Borders copy promises them, and the reduced tier had it
5456
+ rendering square at the Subtle preset (issue #363).
5457
+
5458
+ Declared on BOTH hosts the modal can live under. On the storefront it portals
5459
+ to [data-modal-overlay], which the variant listbox portals up to as well. In
5460
+ the admin widget editor there is no overlay at all \u2014 the preview renders the
5461
+ modal directly under .lb-bundle-widget \u2014 so scoping this to the overlay alone
5462
+ left the variable undefined there and every control using it fell back to
5463
+ square corners while the modal and tiles rounded correctly (issue #363). */
5464
+ .lb-bundle-widget,
5393
5465
  [data-modal-overlay] {
5394
- --lb-picker-radius-sm: max(0px, calc(var(--lb-picker-radius) - 4px));
5466
+ --lb-picker-radius-sm: calc(var(--lb-picker-radius) * 2 / 3);
5395
5467
  }
5396
5468
 
5397
5469
  /* === Modal Overlay === */
@@ -5488,7 +5560,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5488
5560
  border: none;
5489
5561
  cursor: pointer;
5490
5562
  color: var(--lb-picker-text);
5491
- border-radius: 8px;
5563
+ border-radius: var(--lb-picker-radius-sm);
5492
5564
  padding: 0;
5493
5565
  margin: -12px -12px 0 0;
5494
5566
  transition: background 0.25s ease;
@@ -5518,7 +5590,9 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5518
5590
  .lb-mix-match__filter {
5519
5591
  padding: 6px 14px;
5520
5592
  border: var(--lb-picker-border-width) solid var(--lb-picker-border-color);
5521
- border-radius: 999px;
5593
+ /* Pills followed the merchant's picker radius as of #363 \u2014 a fixed 999px
5594
+ read as a stray rounded shape in a picker set to None or Subtle. */
5595
+ border-radius: var(--lb-picker-radius-sm);
5522
5596
  background: transparent;
5523
5597
  color: var(--lb-picker-text);
5524
5598
  font-family: inherit;
@@ -5572,7 +5646,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5572
5646
  width: 100%;
5573
5647
  padding: 12px 40px 12px 44px;
5574
5648
  border: var(--lb-picker-border-width) solid var(--lb-picker-border-color);
5575
- border-radius: var(--lb-picker-radius-sm);
5649
+ border-radius: var(--lb-picker-radius);
5576
5650
  font-size: 16px;
5577
5651
  line-height: 20px;
5578
5652
  color: var(--lb-picker-text);
@@ -5672,7 +5746,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5672
5746
  independent from the main widget's thumbnailRatio so a merchant can
5673
5747
  e.g. show tall picker thumbs with square main thumbs. */
5674
5748
  aspect-ratio: var(--lb-picker-thumbnail-aspect-ratio, 1 / 1);
5675
- border-radius: var(--lb-picker-radius-sm);
5749
+ border-radius: var(--lb-picker-radius);
5676
5750
  box-sizing: border-box;
5677
5751
  overflow: hidden;
5678
5752
  background: var(--lb-thumbnail-bg);
@@ -5685,7 +5759,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5685
5759
  to auto/contain so the image renders uncropped at intrinsic ratio. */
5686
5760
  height: var(--lb-picker-thumbnail-img-height, 100%);
5687
5761
  object-fit: var(--lb-picker-thumbnail-img-fit, cover);
5688
- border-radius: var(--lb-picker-radius-sm);
5762
+ border-radius: var(--lb-picker-radius);
5689
5763
  }
5690
5764
 
5691
5765
  .lb-mix-match__modal-product-info {
@@ -5760,7 +5834,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5760
5834
  font-size: 12px;
5761
5835
  padding: 4px 24px 4px 8px;
5762
5836
  border: var(--lb-picker-border-width) solid var(--lb-picker-border-color);
5763
- border-radius: var(--lb-picker-radius-sm);
5837
+ border-radius: var(--lb-picker-radius);
5764
5838
  background-color: var(--lb-picker-bg);
5765
5839
  background-image: var(--lb-picker-variant-chevron);
5766
5840
  background-repeat: no-repeat;
@@ -5811,7 +5885,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5811
5885
  width: 100%;
5812
5886
  flex-shrink: 0;
5813
5887
  border: var(--lb-picker-border-width) solid var(--lb-picker-border-color);
5814
- border-radius: var(--lb-picker-radius-sm);
5888
+ border-radius: var(--lb-picker-radius);
5815
5889
  background-color: var(--lb-picker-bg);
5816
5890
  overflow: hidden;
5817
5891
  box-sizing: border-box;
@@ -5888,7 +5962,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
5888
5962
  background: var(--lb-picker-add-bg);
5889
5963
  color: var(--lb-picker-add-label);
5890
5964
  border: var(--lb-picker-add-border-width) solid var(--lb-picker-add-border-color);
5891
- border-radius: var(--lb-picker-radius-sm);
5965
+ border-radius: var(--lb-picker-radius);
5892
5966
  box-sizing: border-box;
5893
5967
  font-size: 12px;
5894
5968
  font-weight: 600;
@@ -6029,7 +6103,7 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
6029
6103
  background: var(--lb-picker-add-bg);
6030
6104
  color: var(--lb-picker-add-label);
6031
6105
  border: var(--lb-picker-add-border-width) solid var(--lb-picker-add-border-color);
6032
- border-radius: var(--lb-picker-radius-sm);
6106
+ border-radius: var(--lb-picker-radius);
6033
6107
  box-sizing: border-box;
6034
6108
  font-family: inherit;
6035
6109
  font-size: 14px;
@@ -6078,7 +6152,9 @@ var BUNDLE_MIX_MATCH_CSS = `/* Lime Bundles \u2014 Mix & Match styles */
6078
6152
  .lb-mix-match__modal {
6079
6153
  max-width: 100%;
6080
6154
  max-height: 90vh;
6081
- border-radius: 16px 16px 0 0;
6155
+ /* Bottom sheet: only the top corners round, but they round to whatever the
6156
+ merchant picked rather than a fixed 16px (issue #363). */
6157
+ border-radius: var(--lb-picker-radius) var(--lb-picker-radius) 0 0;
6082
6158
  transform: translateY(100%);
6083
6159
  }
6084
6160
 
@@ -6345,12 +6421,12 @@ var BUNDLE_BOGO_CSS = `/* Lime Bundles \u2014 BOGO (Buy X Get Y) bundle styles *
6345
6421
  .lb-bogo .lb-bundle-thumbnail {
6346
6422
  width: 60px;
6347
6423
  min-width: 60px;
6348
- border-radius: var(--lb-radius-sm);
6424
+ border-radius: var(--lb-radius);
6349
6425
  box-sizing: border-box;
6350
6426
  }
6351
6427
 
6352
6428
  .lb-bogo .lb-bundle-thumbnail img {
6353
- border-radius: var(--lb-radius-sm);
6429
+ border-radius: var(--lb-radius);
6354
6430
  border: none;
6355
6431
  }
6356
6432
 
@@ -6471,6 +6547,13 @@ var BUNDLE_MULTI_STEP_CSS = `/**
6471
6547
  cursor: pointer;
6472
6548
  box-sizing: border-box;
6473
6549
  transition: background-color 0.25s ease;
6550
+ /* Deliberately no border-radius. This row paints the checklist hairline as
6551
+ its own border-top (see the run rule above), and a radius tapers that
6552
+ border into the corner arcs \u2014 the dividers came out visibly curved at the
6553
+ "round" preset (issue #363). A full-bleed list row is meant to be square
6554
+ anyway; the hover tint below spans the card width, so it has no corner to
6555
+ round against. The :focus-visible radius is fine: an outline is a
6556
+ separate paint and never touches the border. */
6474
6557
  }
6475
6558
 
6476
6559
  .lb-multi-step__step-row:hover {
@@ -6618,7 +6701,7 @@ var BUNDLE_MULTI_STEP_CSS = `/**
6618
6701
  padding: 10px 24px;
6619
6702
  background: none;
6620
6703
  border: var(--lb-picker-border-width) solid var(--lb-picker-border-color);
6621
- border-radius: var(--lb-picker-radius-sm);
6704
+ border-radius: var(--lb-picker-radius);
6622
6705
  box-sizing: border-box;
6623
6706
  color: var(--lb-picker-text);
6624
6707
  font-family: inherit;
@@ -6636,6 +6719,108 @@ var BUNDLE_MULTI_STEP_CSS = `/**
6636
6719
  outline: 2px solid var(--lb-primary-color);
6637
6720
  outline-offset: 2px;
6638
6721
  }
6722
+
6723
+ /* \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
6724
+ Moving between steps swaps the whole step-scoped region in a single
6725
+ paint, which reads as nothing happening (or as a glitch) rather than
6726
+ as arriving somewhere new \u2014 and worst of all under auto-advance,
6727
+ where the shopper never clicked anything. So the step assembles
6728
+ instead of arriving whole: the step label leads, the filter pills
6729
+ follow, then the product cards one after another. Staging is what
6730
+ makes the change legible; a uniform slide of everything at once only
6731
+ wobbles the card.
6732
+
6733
+ The wizard stamps data-step-transition="forward" | "back" on the
6734
+ dialog on every step change (manual Next/Back and auto-advance
6735
+ alike, never on open, where the modal entrance already carries the
6736
+ motion), and clears it again once the cascade has played \u2014 see
6737
+ STEP_CASCADE_MS in multi-step/wizard.ts. That clear is load-bearing,
6738
+ not tidiness: search and filter hide cards with .lb-hidden
6739
+ (display: none), and restoring display restarts a card's animation,
6740
+ so a live attribute would replay the whole cascade on every
6741
+ keystroke that reveals a card.
6742
+
6743
+ Two elements deliberately hold still. The footer, because Back/Next
6744
+ are the shopper's anchor while everything above them moves. And the
6745
+ progress rail, because it is the one thing that answers "where am I
6746
+ now" \u2014 animating the shopper's only orientation cue is what made the
6747
+ previous version hard to read. Its segment fill carries its own
6748
+ state change already. */
6749
+ @keyframes lb-multi-step-cascade-fwd {
6750
+ from {
6751
+ opacity: 0;
6752
+ transform: translateY(10px);
6753
+ }
6754
+ }
6755
+
6756
+ @keyframes lb-multi-step-cascade-back {
6757
+ from {
6758
+ opacity: 0;
6759
+ transform: translateY(-10px);
6760
+ }
6761
+ }
6762
+
6763
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-subtitle {
6764
+ animation: lb-multi-step-cascade-fwd 0.2s ease-out both;
6765
+ }
6766
+
6767
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__filters {
6768
+ animation: lb-multi-step-cascade-fwd 0.2s ease-out 0.05s both;
6769
+ }
6770
+
6771
+ /* Cards stagger 30ms apart, but only the first four: a step can hold
6772
+ dozens of products and the two-column grid shows about four at a
6773
+ time, so past that the stagger is below the fold and would only add
6774
+ lag. Everything from the fifth on shares the fourth's landing. */
6775
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-list > * {
6776
+ animation: lb-multi-step-cascade-fwd 0.22s ease-out 0.2s both;
6777
+ }
6778
+
6779
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-list > :nth-child(1) {
6780
+ animation-delay: 0.09s;
6781
+ }
6782
+
6783
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-list > :nth-child(2) {
6784
+ animation-delay: 0.12s;
6785
+ }
6786
+
6787
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-list > :nth-child(3) {
6788
+ animation-delay: 0.15s;
6789
+ }
6790
+
6791
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-list > :nth-child(4) {
6792
+ animation-delay: 0.18s;
6793
+ }
6794
+
6795
+ /* Going back runs the same cascade in the same order \u2014 only the offset
6796
+ flips, so the shopper still reads which way they moved. Overrides
6797
+ the name alone; the staggered delays above must survive. */
6798
+ .lb-mix-match__modal[data-step-transition="back"] .lb-mix-match__modal-subtitle,
6799
+ .lb-mix-match__modal[data-step-transition="back"] .lb-mix-match__filters,
6800
+ .lb-mix-match__modal[data-step-transition="back"] .lb-mix-match__modal-list > * {
6801
+ animation-name: lb-multi-step-cascade-back;
6802
+ }
6803
+
6804
+ @keyframes lb-multi-step-cascade-fade {
6805
+ from {
6806
+ opacity: 0;
6807
+ }
6808
+ }
6809
+
6810
+ /* Reduced motion keeps the fade and drops the travel and the stagger:
6811
+ the step change still has to be perceptible, which is the whole
6812
+ point of this block. The card selector is :nth-child(n) rather than
6813
+ * on purpose \u2014 a plain * loses to the :nth-child(1..4) delays above
6814
+ on specificity, which would leave the stagger running with nothing
6815
+ moving. :nth-child(n) matches every child at equal specificity and
6816
+ wins on order. */
6817
+ @media (prefers-reduced-motion: reduce) {
6818
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-subtitle,
6819
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__filters,
6820
+ .lb-mix-match__modal[data-step-transition] .lb-mix-match__modal-list > :nth-child(n) {
6821
+ animation: lb-multi-step-cascade-fade 0.15s ease-out both;
6822
+ }
6823
+ }
6639
6824
  `;
6640
6825
  var BUNDLE_DROPDOWN_CSS = `/**
6641
6826
  * Lime Bundles \u2014 Custom variant-picker dropdown styling.
@@ -6683,7 +6868,7 @@ var BUNDLE_DROPDOWN_CSS = `/**
6683
6868
  gap: 8px;
6684
6869
  width: 100%;
6685
6870
  border: var(--lb-border-width) solid var(--lb-border);
6686
- border-radius: var(--lb-radius-sm);
6871
+ border-radius: var(--lb-radius);
6687
6872
  padding: 8px 12px;
6688
6873
  font-size: 12px;
6689
6874
  line-height: 16px;
@@ -6746,7 +6931,7 @@ var BUNDLE_DROPDOWN_CSS = `/**
6746
6931
  background: var(--lb-bg);
6747
6932
  color: var(--lb-text);
6748
6933
  border: var(--lb-border-width) solid var(--lb-border);
6749
- border-radius: var(--lb-radius-sm);
6934
+ border-radius: var(--lb-radius);
6750
6935
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
6751
6936
  overflow-y: auto;
6752
6937
  overflow-x: hidden;
@@ -6807,6 +6992,10 @@ var BUNDLE_DROPDOWN_CSS = `/**
6807
6992
  overflow: hidden;
6808
6993
  text-overflow: ellipsis;
6809
6994
  color: var(--lb-text);
6995
+ /* The active/hover tint below fills the option, so it rounds with the rest
6996
+ of the widget rather than squaring off against the listbox corner it sits
6997
+ in (issue #363). */
6998
+ border-radius: var(--lb-radius-sm);
6810
6999
  }
6811
7000
 
6812
7001
  .lb-dropdown-option[aria-selected="true"] {
@@ -6865,7 +7054,7 @@ var BUNDLE_DROPDOWN_CSS = `/**
6865
7054
  .lb-mix-match__modal .lb-dropdown-trigger {
6866
7055
  border-color: var(--lb-picker-border-color);
6867
7056
  border-width: var(--lb-picker-border-width);
6868
- border-radius: var(--lb-picker-radius-sm);
7057
+ border-radius: var(--lb-picker-radius);
6869
7058
  background: var(--lb-picker-bg);
6870
7059
  color: var(--lb-picker-text);
6871
7060
  /* Match the picker qty stepper + Add button height (border-box so 32px is
@@ -6886,13 +7075,17 @@ var BUNDLE_DROPDOWN_CSS = `/**
6886
7075
  [data-modal-overlay] > .lb-dropdown-listbox {
6887
7076
  border-color: var(--lb-picker-border-color);
6888
7077
  border-width: var(--lb-picker-border-width);
6889
- border-radius: var(--lb-picker-radius-sm);
7078
+ border-radius: var(--lb-picker-radius);
6890
7079
  background: var(--lb-picker-bg);
6891
7080
  color: var(--lb-picker-text);
6892
7081
  scrollbar-color: color-mix(in srgb, var(--lb-picker-text) 15%, transparent)
6893
7082
  color-mix(in srgb, var(--lb-picker-text) 2%, transparent);
6894
7083
  }
6895
7084
 
7085
+ [data-modal-overlay] > .lb-dropdown-listbox .lb-dropdown-option {
7086
+ border-radius: var(--lb-picker-radius-sm);
7087
+ }
7088
+
6896
7089
  [data-modal-overlay] > .lb-dropdown-listbox::-webkit-scrollbar-track {
6897
7090
  background: color-mix(in srgb, var(--lb-picker-text) 2%, transparent);
6898
7091
  border-radius: 2px;