PageSourceSearch

https://www.bostonproper.com/products/boston-proper-printed-scarf-with-love-bp

html bostonproper.com collected 2026-10-03 21:31:11 UTC 1,317,922 bytes, 24,586 lines download raw bytes

1<!doctype html>
2<html
3  
4  lang="en"
5>
6  <head><link rel="preconnect" href="https://media.bostonproper.com">
7      <link rel="dns-prefetch" href="https://media.bostonproper.com"><link
8        rel="icon"
9        type="image/png"
10        href="//www.bostonproper.com/cdn/shop/files/bp-favicon_2026.jpg?crop=center&height=32&v=1785357425&width=32"
11      >
12    
13
14
15<meta charset="utf-8">
16<meta
17  http-equiv="X-UA-Compatible"
18  content="IE=edge"
19>
20<meta
21  name="viewport"
22  content="width=device-width,initial-scale=1"
23>
24<meta
25  name="view-transition"
26  content="same-origin"
27>
28<meta
29  name="theme-color"
30  content=""
31>
32
33<meta
34  property="og:site_name"
35  content="Boston Proper"
36>
37<meta
38  property="og:url"
39  content="https://www.bostonproper.com/products/boston-proper-printed-scarf-with-love-bp"
40>
41<meta
42  property="og:title"
43  content="Boston Proper Printed Scarf With Love BP"
44>
45<meta
46  property="og:type"
47  content="product"
48>
49<meta
50  property="og:description"
51  content="Shop women&#39;s dresses, statement tops, polished pants, shoes, accessories, and travel-ready styles designed to fit beautifully and own every room. "
52><meta
53    property="og:image"
54    content="http://www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198"
55  >
56  <meta
57    property="og:image:secure_url"
58    content="https://www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198"
59  >
60  <meta
61    property="og:image:width"
62    content="1639"
63  >
64  <meta
65    property="og:image:height"
66    content="2048"
67  ><meta
68    property="og:price:amount"
69    content="50.00"
70  >
71  <meta
72    property="og:price:currency"
73    content="USD"
74  ><meta
75  name="twitter:card"
76  content="summary_large_image"
77>
78<meta
79  name="twitter:title"
80  content="Boston Proper Printed Scarf With Love BP"
81>
82<meta
83  name="twitter:description"
84  content="Shop women&#39;s dresses, statement tops, polished pants, shoes, accessories, and travel-ready styles designed to fit beautifully and own every room. "
85>
86
87<title>
88  Boston Proper Printed Scarf With Love BP
89</title>
90
91<link
92  rel="canonical"
93  href="https://www.bostonproper.com/products/boston-proper-printed-scarf-with-love-bp"
94>
95
96
97<link href="//www.bostonproper.com/cdn/shop/t/1521/assets/overflow-list.css?v=16727044177065489451790713714" as="style" rel="preload">
98<link href="//www.bostonproper.com/cdn/shop/t/1521/assets/base.css?v=80415010869825589501790713714" rel="stylesheet" type="text/css" media="all" />
99
100<link
101    rel="preload"
102    as="font"
103    href="//www.bostonproper.com/cdn/fonts/inter/inter_n4.b2a3f24c19b4de56e8871f609e73ca7f6d2e2bb9.woff2"
104    type="font/woff2"
105    crossorigin
106    fetchpriority="low"
107  ><link
108    rel="preload"
109    as="font"
110    href="//www.bostonproper.com/cdn/fonts/inter/inter_n5.d7101d5e168594dd06f56f290dd759fba5431d97.woff2"
111    type="font/woff2"
112    crossorigin
113    fetchpriority="low"
114  ><link
115    rel="preload"
116    as="font"
117    href="//www.bostonproper.com/cdn/fonts/inter/inter_n7.02711e6b374660cfc7915d1afc1c204e633421e4.woff2"
118    type="font/woff2"
119    crossorigin
120    fetchpriority="low"
121  ><link
122    rel="preload"
123    as="font"
124    href="//www.bostonproper.com/cdn/fonts/inter/inter_n7.02711e6b374660cfc7915d1afc1c204e633421e4.woff2"
125    type="font/woff2"
126    crossorigin
127    fetchpriority="low"
128  >
129
130
131<script async crossorigin fetchpriority="high" src="/cdn/shopifycloud/importmap-polyfill/es-modules-shim.2.4.0.js"></script>
vendor: 1 bytes, line 131
131
132<script type="importmap">
133  {
134    "imports": {
135      "@theme/overflow-list": "//www.bostonproper.com/cdn/shop/t/1521/assets/overflow-list.js?v=46858356770684902511790713714",
136      "@theme/product-title": "//www.bostonproper.com/cdn/shop/t/1521/assets/product-title-truncation.js?v=81744426891537421781790713714",
137      "@theme/component": "//www.bostonproper.com/cdn/shop/t/1521/assets/component.js?v=184240237101443119871790713714",
138      "@theme/dialog": "//www.bostonproper.com/cdn/shop/t/1521/assets/dialog.js?v=150888536568694194021790713714",
139      "@theme/events": "//www.bostonproper.com/cdn/shop/t/1521/assets/events.js?v=1118589085892804011790713714",
140      "@theme/focus": "//www.bostonproper.com/cdn/shop/t/1521/assets/focus.js?v=60436577539430446401790713714",
141      "@theme/morph": "//www.bostonproper.com/cdn/shop/t/1521/assets/morph.js?v=104045809772310330131790713714",
142      "@theme/paginated-list": "//www.bostonproper.com/cdn/shop/t/1521/assets/paginated-list.js?v=95298315036233333871790713714",
143      "@theme/performance": "//www.bostonproper.com/cdn/shop/t/1521/assets/performance.js?v=171015751390534793081790713714",
144      "@theme/product-form": "//www.bostonproper.com/cdn/shop/t/1521/assets/product-form.js?v=138228271698465017521790713714",
145      "@theme/recently-viewed-products": "//www.bostonproper.com/cdn/shop/t/1521/assets/recently-viewed-products.js?v=94729125001750262651790713714",
146      "@theme/scrolling": "//www.bostonproper.com/cdn/shop/t/1521/assets/scrolling.js?v=162288454571026455011790713714",
147      "@theme/section-renderer": "//www.bostonproper.com/cdn/shop/t/1521/assets/section-renderer.js?v=170547751348887101551790713714",
148      "@theme/section-hydration": "//www.bostonproper.com/cdn/shop/t/1521/assets/section-hydration.js?v=108434990705342316311790713714",
149      "@theme/money-formatting": "//www.bostonproper.com/cdn/shop/t/1521/assets/money-formatting.js?v=182191346160333327151790713714",
150      "@theme/utilities": "//www.bostonproper.com/cdn/shop/t/1521/assets/utilities.js?v=28506172887375975941790713714",
151      "@theme/variant-picker": "//www.bostonproper.com/cdn/shop/t/1521/assets/variant-picker.js?v=137587803232570873901790713714",
152      "@theme/media-gallery": "//www.bostonproper.com/cdn/shop/t/1521/assets/media-gallery.js?v=14624021005636302161790713714",
153      "@theme/quick-add": "//www.bostonproper.com/cdn/shop/t/1521/assets/quick-add.js?v=141968020560480616261790713714",
154      "@theme/paginated-list-aspect-ratio": "//www.bostonproper.com/cdn/shop/t/1521/assets/paginated-list-aspect-ratio.js?v=25254270272143792451790713714",
155      "@theme/popover-polyfill": "//www.bostonproper.com/cdn/shop/t/1521/assets/popover-polyfill.js?v=119029313658895111201790713714",
156      "@theme/component-quantity-selector": "//www.bostonproper.com/cdn/shop/t/1521/assets/component-quantity-selector.js?v=67906657287482036641790713714",
157      "@theme/comparison-slider": "//www.bostonproper.com/cdn/shop/t/1521/assets/comparison-slider.js?v=106705562947035711941790713714",
158      "@theme/sticky-add-to-cart": "//www.bostonproper.com/cdn/shop/t/1521/assets/sticky-add-to-cart.js?v=48956925339276737091790713714",
159      "@theme/fly-to-cart": "//www.bostonproper.com/cdn/shop/t/1521/assets/fly-to-cart.js?v=48483246440248933081790713714"
160    }
161  }
162</script>
162
163
164<script
165  src="//www.bostonproper.com/cdn/shop/t/1521/assets/view-transitions.js?v=41230751666534493481790713714"
166  async
167  
168></script>
168
169
170<link
171  rel="modulepreload"
172  href="//www.bostonproper.com/cdn/shop/t/1521/assets/utilities.js?v=28506172887375975941790713714"
173  fetchpriority="low"
174>
175<link
176  rel="modulepreload"
177  href="//www.bostonproper.com/cdn/shop/t/1521/assets/component.js?v=184240237101443119871790713714"
178  fetchpriority="low"
179>
180<link
181  rel="modulepreload"
182  href="//www.bostonproper.com/cdn/shop/t/1521/assets/section-renderer.js?v=170547751348887101551790713714"
183  fetchpriority="low"
184>
185<link
186  rel="modulepreload"
187  href="//www.bostonproper.com/cdn/shop/t/1521/assets/section-hydration.js?v=108434990705342316311790713714"
188  fetchpriority="low"
189>
190<link
191  rel="modulepreload"
192  href="//www.bostonproper.com/cdn/shop/t/1521/assets/morph.js?v=104045809772310330131790713714"
193  fetchpriority="low"
194>
195
196
197
198<link
199  rel="modulepreload"
200  href="//www.bostonproper.com/cdn/shop/t/1521/assets/focus.js?v=60436577539430446401790713714"
201  fetchpriority="low"
202>
203<link
204  rel="modulepreload"
205  href="//www.bostonproper.com/cdn/shop/t/1521/assets/recently-viewed-products.js?v=94729125001750262651790713714"
206  fetchpriority="low"
207>
208<link
209  rel="modulepreload"
210  href="//www.bostonproper.com/cdn/shop/t/1521/assets/scrolling.js?v=162288454571026455011790713714"
211  fetchpriority="low"
212>
213<link
214  rel="modulepreload"
215  href="//www.bostonproper.com/cdn/shop/t/1521/assets/events.js?v=1118589085892804011790713714"
216  fetchpriority="low"
217>
218<script
219  src="//www.bostonproper.com/cdn/shop/t/1521/assets/popover-polyfill.js?v=119029313658895111201790713714"
220  type="module"
221  fetchpriority="low"
222></script>
vendor: 1 bytes, line 222
222
223<script
224  src="//www.bostonproper.com/cdn/shop/t/1521/assets/overflow-list.js?v=46858356770684902511790713714"
225  type="module"
226  fetchpriority="low"
227></script>
vendor: 1 bytes, line 227
227
228<script
229  src="//www.bostonproper.com/cdn/shop/t/1521/assets/quick-add.js?v=141968020560480616261790713714"
230  type="module"
231  fetchpriority="low"
232></script>
232
233
234  
234<script
235    src="//www.bostonproper.com/cdn/shop/t/1521/assets/cart-discount.js?v=107077853990124422021790713714"
236    type="module"
237    fetchpriority="low"
238  ></script>
238
239
240
241<script
242  src="//www.bostonproper.com/cdn/shop/t/1521/assets/dialog.js?v=150888536568694194021790713714"
243  type="module"
244  fetchpriority="low"
245></script>
vendor: 1 bytes, line 245
245
246<script
247  src="//www.bostonproper.com/cdn/shop/t/1521/assets/variant-picker.js?v=137587803232570873901790713714"
248  type="module"
249  fetchpriority="low"
250></script>
vendor: 1 bytes, line 250
250
251<script
252  src="//www.bostonproper.com/cdn/shop/t/1521/assets/product-card.js?v=28695665944407642501790713714"
253  type="module"
254  fetchpriority="low"
255></script>
vendor: 1 bytes, line 255
255
256<script
257  src="//www.bostonproper.com/cdn/shop/t/1521/assets/product-form.js?v=138228271698465017521790713714"
258  type="module"
259  fetchpriority="low"
260></script>
vendor: 1 bytes, line 260
260
261<script
262  src="//www.bostonproper.com/cdn/shop/t/1521/assets/fly-to-cart.js?v=48483246440248933081790713714"
263  type="module"
264  fetchpriority="low"
265></script>
vendor: 1 bytes, line 265
265
266<script
267  src="//www.bostonproper.com/cdn/shop/t/1521/assets/accordion-custom.js?v=97588419883090888471790713714"
268  type="module"
269  fetchpriority="low"
270></script>
vendor: 1 bytes, line 270
270
271<script
272  src="//www.bostonproper.com/cdn/shop/t/1521/assets/media.js?v=37825095869491791421790713714"
273  type="module"
274  fetchpriority="low"
275></script>
vendor: 1 bytes, line 275
275
276<script
277  src="//www.bostonproper.com/cdn/shop/t/1521/assets/product-price.js?v=83480980452100801711790713714"
278  type="module"
279  fetchpriority="low"
280></script>
vendor: 1 bytes, line 280
280
281<script
282  src="//www.bostonproper.com/cdn/shop/t/1521/assets/product-sku.js?v=121804655373531320511790713714"
283  type="module"
284  fetchpriority="low"
285></script>
vendor: 1 bytes, line 285
285
286<script
287  src="//www.bostonproper.com/cdn/shop/t/1521/assets/product-title-truncation.js?v=81744426891537421781790713714"
288  type="module"
289  fetchpriority="low"
290></script>
vendor: 1 bytes, line 290
290
291<script
292  src="//www.bostonproper.com/cdn/shop/t/1521/assets/product-inventory.js?v=81520546963552472391790713714"
293  type="module"
294  fetchpriority="low"
295></script>
vendor: 1 bytes, line 295
295
296<script
297  src="//www.bostonproper.com/cdn/shop/t/1521/assets/show-more.js?v=94563802205717136101790713714"
298  type="module"
299  fetchpriority="low"
300></script>
vendor: 1 bytes, line 300
300
301<script
302  src="//www.bostonproper.com/cdn/shop/t/1521/assets/slideshow.js?v=168726587398279102001790713714"
303  type="module"
304  fetchpriority="low"
305></script>
vendor: 1 bytes, line 305
305
306<script
307  src="//www.bostonproper.com/cdn/shop/t/1521/assets/layered-slideshow.js?v=30135417790894624731790713714"
308  type="module"
309  fetchpriority="low"
310></script>
vendor: 1 bytes, line 310
310
311<script
312  src="//www.bostonproper.com/cdn/shop/t/1521/assets/anchored-popover.js?v=95953304814728754461790713714"
313  type="module"
314  fetchpriority="low"
315></script>
vendor: 1 bytes, line 315
315
316<script
317  src="//www.bostonproper.com/cdn/shop/t/1521/assets/floating-panel.js?v=151277338116891310371790713714"
318  type="module"
319  fetchpriority="low"
320></script>
vendor: 1 bytes, line 320
320
321<script
322  src="//www.bostonproper.com/cdn/shop/t/1521/assets/video-background.js?v=25237992823806706551790713714"
323  type="module"
324  fetchpriority="low"
325></script>
vendor: 1 bytes, line 325
325
326<script
327  src="//www.bostonproper.com/cdn/shop/t/1521/assets/component-quantity-selector.js?v=67906657287482036641790713714"
328  type="module"
329  fetchpriority="low"
330></script>
vendor: 1 bytes, line 330
330
331<script
332  src="//www.bostonproper.com/cdn/shop/t/1521/assets/media-gallery.js?v=14624021005636302161790713714"
333  type="module"
334  fetchpriority="low"
335></script>
vendor: 1 bytes, line 335
335
336<script
337  src="//www.bostonproper.com/cdn/shop/t/1521/assets/rte-formatter.js?v=40306132146590816021790713714"
338  type="module"
339  fetchpriority="low"
340></script>
vendor: 1 bytes, line 340
340
341<script
342  src="//www.bostonproper.com/cdn/shop/t/1521/assets/volume-pricing.js?v=15442793518842484731790713714"
343  type="module"
344  fetchpriority="low"
345></script>
vendor: 1 bytes, line 345
345
346<script
347  src="//www.bostonproper.com/cdn/shop/t/1521/assets/price-per-item.js?v=144512917617120124431790713714"
348  type="module"
349  fetchpriority="low"
350></script>
vendor: 1 bytes, line 350
350
351<script
352  src="//www.bostonproper.com/cdn/shop/t/1521/assets/volume-pricing-info.js?v=94479640769665442661790713714"
353  type="module"
354  fetchpriority="low"
355></script>
355
356
357
358  
358<script
359    src="//www.bostonproper.com/cdn/shop/t/1521/assets/localization.js?v=15585934801240115691790713714"
360    type="module"
361    fetchpriority="low"
362  ></script>
362
363
364
365
366  
366<script
367    src="//www.bostonproper.com/cdn/shop/t/1521/assets/fly-to-cart.js?v=48483246440248933081790713714"
368    type="module"
369    fetchpriority="low"
370  ></script>
370
371  
371<script
372    src="//www.bostonproper.com/cdn/shop/t/1521/assets/sticky-add-to-cart.js?v=48956925339276737091790713714"
373    type="module"
374    fetchpriority="low"
375  ></script>
375
376  
376<script type="module">
377    import { RecentlyViewed } from '@theme/recently-viewed-products';
378    RecentlyViewed.addProduct('15286962618534');
379  </script>
379
380
381
382<script
383  src="//www.bostonproper.com/cdn/shop/t/1521/assets/auto-close-details.js?v=58350291535404441581790713714"
384  defer="defer"
385></script>
385
386
387<script>
388  const Theme = {
389    translations: {
390      placeholder_image: `Placeholder image`,
391      added: `Added`,
392      recipient_form_fields_visible: `Recipient form fields are now visible`,
393      recipient_form_fields_hidden: `Recipient form fields are now hidden`,
394      recipient_form_error: `There was an error with the form submission`,
395      items_added_to_cart_one: `1 item added to cart`,
396      items_added_to_cart_other: `{{ count }} items added to cart`,
397      cart_count: `Total items in cart`,
398    },
399    routes: {
400      cart_add_url: '/cart/add.js',
401      cart_change_url: '/cart/change',
402      cart_update_url: '/cart/update',
403      cart_url: '/cart',
404      predictive_search_url: '/search/suggest',
405      search_url: '/search',
406    },
407    template: {
408      name: 'product',
409    },
410  };
411</script>
411
412<style data-shopify>
413@font-face {
414  font-family: Inter;
415  font-weight: 400;
416  font-style: normal;
417  font-display: swap;
418  src: url("//www.bostonproper.com/cdn/fonts/inter/inter_n4.b2a3f24c19b4de56e8871f609e73ca7f6d2e2bb9.woff2") format("woff2"),
419       url("//www.bostonproper.com/cdn/fonts/inter/inter_n4.af8052d517e0c9ffac7b814872cecc27ae1fa132.woff") format("woff");
420}
421@font-face {
422  font-family: Inter;
423  font-weight: 700;
424  font-style: normal;
425  font-display: swap;
426  src: url("//www.bostonproper.com/cdn/fonts/inter/inter_n7.02711e6b374660cfc7915d1afc1c204e633421e4.woff2") format("woff2"),
427       url("//www.bostonproper.com/cdn/fonts/inter/inter_n7.6dab87426f6b8813070abd79972ceaf2f8d3b012.woff") format("woff");
428}
429@font-face {
430  font-family: Inter;
431  font-weight: 400;
432  font-style: italic;
433  font-display: swap;
434  src: url("//www.bostonproper.com/cdn/fonts/inter/inter_i4.feae1981dda792ab80d117249d9c7e0f1017e5b3.woff2") format("woff2"),
435       url("//www.bostonproper.com/cdn/fonts/inter/inter_i4.62773b7113d5e5f02c71486623cf828884c85c6e.woff") format("woff");
436}
437@font-face {
438  font-family: Inter;
439  font-weight: 700;
440  font-style: italic;
441  font-display: swap;
442  src: url("//www.bostonproper.com/cdn/fonts/inter/inter_i7.b377bcd4cc0f160622a22d638ae7e2cd9b86ea4c.woff2") format("woff2"),
443       url("//www.bostonproper.com/cdn/fonts/inter/inter_i7.7c69a6a34e3bb44fcf6f975857e13b9a9b25beb4.woff") format("woff");
444}
445@font-face {
446  font-family: Inter;
447  font-weight: 500;
448  font-style: normal;
449  font-display: swap;
450  src: url("//www.bostonproper.com/cdn/fonts/inter/inter_n5.d7101d5e168594dd06f56f290dd759fba5431d97.woff2") format("woff2"),
451       url("//www.bostonproper.com/cdn/fonts/inter/inter_n5.5332a76bbd27da00474c136abb1ca3cbbf259068.woff") format("woff");
452}
453@font-face {
454  font-family: Inter;
455  font-weight: 500;
456  font-style: italic;
457  font-display: swap;
458  src: url("//www.bostonproper.com/cdn/fonts/inter/inter_i5.4474f48e6ab2b1e01aa2b6d942dd27fa24f2d99f.woff2") format("woff2"),
459       url("//www.bostonproper.com/cdn/fonts/inter/inter_i5.493dbd6ee8e49f4ad722ebb68d92f201af2c2f56.woff") format("woff");
460}
461
462
463  :root {
464    /* Page Layout */
465    --sidebar-width: 25rem;
466    --narrow-content-width: 36rem;
467    --normal-content-width: 42rem;
468    --wide-content-width: 46rem;
469    --narrow-page-width: 90rem;
470    --normal-page-width: 120rem;
471    --wide-page-width: 150rem;
472
473    /* Section Heights */
474    --section-height-small: 15rem;
475    --section-height-medium: 25rem;
476    --section-height-large: 35rem;
477
478    @media screen and (min-width: 40em) {
479      --section-height-small: 40svh;
480      --section-height-medium: 55svh;
481      --section-height-large: 70svh;
482    }
483
484    @media screen and (min-width: 60em) {
485      --section-height-small: 50svh;
486      --section-height-medium: 65svh;
487      --section-height-large: 80svh;
488    }
489
490    /* Letter spacing */
491    --letter-spacing-sm: 0.06em;
492    --letter-spacing-md: 0.13em;
493
494    /* Font families */
495    --font-body--family: Inter, sans-serif;
496    --font-body--style: normal;
497    --font-body--weight: 400;
498    --font-subheading--family: Inter, sans-serif;
499    --font-subheading--style: normal;
500    --font-subheading--weight: 500;
501    --font-heading--family: Inter, sans-serif;
502    --font-heading--style: normal;
503    --font-heading--weight: 700;
504    --font-accent--family: Inter, sans-serif;
505    --font-accent--style: normal;
506    --font-accent--weight: 700;
507
508    /* Margin sizes */
509    --font-heading--spacing: 0.25em;
510    --font-h1--spacing: var(--font-heading--spacing);
511    --font-h2--spacing: var(--font-heading--spacing);
512    --font-h3--spacing: var(--font-heading--spacing);
513    --font-h4--spacing: var(--font-heading--spacing);
514    --font-h5--spacing: var(--font-heading--spacing);
515    --font-h6--spacing: var(--font-heading--spacing);
516    --font-paragraph--spacing: 0.5em;
517
518    /* Heading colors */
519    --font-h1--color: var(--color-foreground-heading);
520    --font-h2--color: var(--color-foreground-heading);
521    --font-h3--color: var(--color-foreground-heading);
522    --font-h4--color: var(--color-foreground-heading);
523    --font-h5--color: var(--color-foreground-heading);
524    --font-h6--color: var(--color-foreground-heading);
525
526    /** Z-Index / Layering */
527    --layer-section-background: -2;
528    --layer-lowest: -1;
529    --layer-base: 0;
530    --layer-flat: 1;
531    --layer-raised: 2;
532    --layer-heightened: 4;
533    --layer-sticky: 8;
534    --layer-window-overlay: 10;
535    --layer-header-menu: 12;
536    --layer-overlay: 16;
537    --layer-menu-drawer: 18;
538    --layer-temporary: 20;
539
540    /* Max-width / Measure */
541    --max-width--body-normal: 32.5em;
542    --max-width--body-narrow: 22.75em;
543
544    --max-width--heading-normal: 32.5em;
545    --max-width--heading-narrow: 19.5em;
546
547    --max-width--display-normal: 13em;
548    --max-width--display-narrow: 9.75em;
549    --max-width--display-tight: 3.25em;
550
551    /* Letter-spacing / Tracking */
552    --letter-spacing--display-tight: -0.03em;
553    --letter-spacing--display-normal: 0em;
554    --letter-spacing--display-loose: 0.03em;
555
556    --letter-spacing--heading-tight: -0.03em;
557    --letter-spacing--heading-normal: 0em;
558    --letter-spacing--heading-loose: 0.03em;
559
560    --letter-spacing--body-tight: -0.03em;
561    --letter-spacing--body-normal: 0em;
562    --letter-spacing--body-loose: 0.03em;
563
564    /* Line height / Leading */
565    --line-height: 1;
566
567    --line-height--display-tight: 1;
568    --line-height--display-normal: 1.1;
569    --line-height--display-loose: 1.2;
570
571    --line-height--heading-tight: 1.15;
572    --line-height--heading-normal: 1.25;
573    --line-height--heading-loose: 1.35;
574
575    --line-height--body-tight: 1.2;
576    --line-height--body-normal: 1.4;
577    --line-height--body-loose: 1.6;
578
579    /* Typography presets */
580    --font-size--paragraph: 0.875rem;--font-size--h1: clamp(3.0rem, 5.6vw, 3.5rem);--font-size--h2: clamp(2.25rem, 4.8vw, 3.0rem);--font-size--h3: 2.0rem;--font-size--h4: 1.5rem;--font-size--h5: 0.875rem;--font-size--h6: 0.75rem;--font-paragraph--weight: 400;--font-paragraph--letter-spacing: var(--letter-spacing--body-normal);--font-paragraph--size: var(--font-size--paragraph);--font-paragraph--family: var(--font-body--family);--font-paragraph--style: var(--font-body--style);--font-paragraph--case: ;--font-paragraph--line-height: var(--line-height--body-loose);--font-h1--weight: var(--font-heading--weight);--font-h1--letter-spacing: var(--letter-spacing--heading-normal);--font-h1--size: var(--font-size--h1);--font-h1--family: var(--font-heading--family);--font-h1--style: var(--font-heading--style);--font-h1--case: none;--font-h1--line-height: var(--line-height--display-tight);--font-h2--weight: var(--font-heading--weight);--font-h2--letter-spacing: var(--letter-spacing--heading-normal);--font-h2--size: var(--font-size--h2);--font-h2--family: var(--font-heading--family);--font-h2--style: var(--font-heading--style);--font-h2--case: none;--font-h2--line-height: var(--line-height--display-tight);--font-h3--weight: var(--font-heading--weight);--font-h3--letter-spacing: var(--letter-spacing--heading-normal);--font-h3--size: var(--font-size--h3);--font-h3--family: var(--font-heading--family);--font-h3--style: var(--font-heading--style);--font-h3--case: none;--font-h3--line-height: var(--line-height--display-normal);--font-h4--weight: var(--font-heading--weight);--font-h4--letter-spacing: var(--letter-spacing--heading-normal);--font-h4--size: var(--font-size--h4);--font-h4--family: var(--font-heading--family);--font-h4--style: var(--font-heading--style);--font-h4--case: none;--font-h4--line-height: var(--line-height--display-tight);--font-h5--weight: var(--font-subheading--weight);--font-h5--letter-spacing: var(--letter-spacing--heading-normal);--font-h5--size: var(--font-size--h5);--font-h5--family: var(--font-subheading--family);--font-h5--style: var(--font-subheading--style);--font-h5--case: none;--font-h5--line-height: var(--line-height--display-loose);--font-h6--weight: var(--font-subheading--weight);--font-h6--letter-spacing: var(--letter-spacing--heading-normal);--font-h6--size: var(--font-size--h6);--font-h6--family: var(--font-subheading--family);--font-h6--style: var(--font-subheading--style);--font-h6--case: none;--font-h6--line-height: var(--line-height--display-loose);
581
582    /* Hardcoded font sizes */
583    --font-size--3xs: 0.625rem;
584    --font-size--2xs: 0.75rem;
585    --font-size--xs: 0.8125rem;
586    --font-size--sm: 0.875rem;
587    --font-size--md: 1rem;
588    --font-size--lg: 1.125rem;
589    --font-size--xl: 1.25rem;
590    --font-size--2xl: 1.5rem;
591    --font-size--3xl: 2rem;
592    --font-size--4xl: 2.5rem;
593    --font-size--5xl: 3rem;
594    --font-size--6xl: 3.5rem;
595
596    /* Menu font sizes */
597    --menu-font-sm--size: 0.875rem;
598    --menu-font-sm--line-height: calc(1.1 + 0.5 * min(16 / 14));
599    --menu-font-md--size: 1rem;
600    --menu-font-md--line-height: calc(1.1 + 0.5 * min(16 / 16));
601    --menu-font-lg--size: 1.125rem;
602    --menu-font-lg--line-height: calc(1.1 + 0.5 * min(16 / 18));
603    --menu-font-xl--size: 1.25rem;
604    --menu-font-xl--line-height: calc(1.1 + 0.5 * min(16 / 20));
605    --menu-font-2xl--size: 1.75rem;
606    --menu-font-2xl--line-height: calc(1.1 + 0.5 * min(16 / 28));
607
608    /* Colors */
609    --color-error: #8B0000;
610    --color-success: #006400;
611    --color-white: #FFFFFF;
612    --color-white-rgb: 255 255 255;
613    --color-black: #000000;
614    --color-instock: #3ED660;
615    --color-lowstock: #EE9441;
616    --color-outofstock: #C8C8C8;
617
618    /* Opacity */
619    --opacity-5: 0.05;
620    --opacity-8: 0.08;
621    --opacity-10: 0.1;
622    --opacity-15: 0.15;
623    --opacity-20: 0.2;
624    --opacity-25: 0.25;
625    --opacity-30: 0.3;
626    --opacity-40: 0.4;
627    --opacity-50: 0.5;
628    --opacity-60: 0.6;
629    --opacity-70: 0.7;
630    --opacity-80: 0.8;
631    --opacity-85: 0.85;
632    --opacity-90: 0.9;
633    --opacity-subdued-text: var(--opacity-70);
634
635    --shadow-button: 0 2px 3px rgb(0 0 0 / 20%);
636    --gradient-image-overlay: linear-gradient(to top, rgb(0 0 0 / 0.5), transparent);
637
638    /* Spacing */
639    --margin-3xs: 0.125rem;
640    --margin-2xs: 0.3rem;
641    --margin-xs: 0.5rem;
642    --margin-sm: 0.7rem;
643    --margin-md: 0.8rem;
644    --margin-lg: 1rem;
645    --margin-xl: 1.25rem;
646    --margin-2xl: 1.5rem;
647    --margin-3xl: 1.75rem;
648    --margin-4xl: 2rem;
649    --margin-5xl: 3rem;
650    --margin-6xl: 5rem;
651
652    --scroll-margin: 50px;
653
654    --padding-3xs: 0.125rem;
655    --padding-2xs: 0.25rem;
656    --padding-xs: 0.5rem;
657    --padding-sm: 0.7rem;
658    --padding-md: 0.8rem;
659    --padding-lg: 1rem;
660    --padding-xl: 1.25rem;
661    --padding-2xl: 1.5rem;
662    --padding-3xl: 1.75rem;
663    --padding-4xl: 2rem;
664    --padding-5xl: 3rem;
665    --padding-6xl: 4rem;
666
667    --gap-3xs: 0.125rem;
668    --gap-2xs: 0.3rem;
669    --gap-xs: 0.5rem;
670    --gap-sm: 0.7rem;
671    --gap-md: 0.9rem;
672    --gap-lg: 1rem;
673    --gap-xl: 1.25rem;
674    --gap-2xl: 2rem;
675    --gap-3xl: 3rem;
676
677    --spacing-scale-sm: 0.6;
678    --spacing-scale-md: 0.7;
679    --spacing-scale-default: 1.0;
680
681    /* Checkout buttons gap */
682    --checkout-button-gap: 10px;
683
684    /* Borders */
685    --style-border-width: 1px;
686    --style-border-radius-xs: 0.2rem;
687    --style-border-radius-sm: 0.6rem;
688    --style-border-radius-md: 0.8rem;
689    --style-border-radius-50: 50%;
690    --style-border-radius-lg: 1rem;
691    --style-border-radius-pills: 40px;
692    --style-border-radius-inputs: 4px;
693    --style-border-radius-buttons-primary: 14px;
694    --style-border-radius-buttons-secondary: 14px;
695    --style-border-width-primary: 0px;
696    --style-border-width-secondary: 1px;
697    --style-border-width-inputs: 1px;
698    --style-border-radius-popover: 14px;
699    --style-border-popover: 1px none rgb(var(--color-border-rgb) / 50%);
700    --style-border-drawer: 1px none rgb(var(--color-border-rgb) / 50%);
701    --style-border-swatch-opacity: 10%;
702    --style-border-swatch-width: 1px;
703    --style-border-swatch-style: solid;
704
705    /* Animation */
706    --ease-out-cubic: cubic-bezier(0.33, 1, 0.68, 1);
707    --ease-out-quad: cubic-bezier(0.32, 0.72, 0, 1);
708    --ease-in-out-quad: cubic-bezier(0.455, 0.03, 0.515, 0.955);
709    --animation-speed-fast: 0.0625s;
710    --animation-speed: 0.125s;
711    --animation-speed-slow: 0.2s;
712    --animation-speed-medium: 0.15s;
713    --animation-easing: ease-in-out;
714    --animation-slideshow-easing: cubic-bezier(0.4, 0, 0.2, 1);
715    --drawer-animation-speed: 0.2s;
716    --animation-values-slow: var(--animation-speed-slow) var(--animation-easing);
717    --animation-values: var(--animation-speed) var(--animation-easing);
718    --animation-values-fast: var(--animation-speed-fast) var(--animation-easing);
719    --animation-values-allow-discrete: var(--animation-speed) var(--animation-easing) allow-discrete;
720    --animation-timing-hover: cubic-bezier(0.25, 0.46, 0.45, 0.94);
721    --animation-timing-active: cubic-bezier(0.5, 0, 0.75, 0);
722    --animation-timing-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
723    --animation-timing-default: cubic-bezier(0, 0, 0.2, 1);
724    --animation-timing-fade-in: cubic-bezier(0.16, 1, 0.3, 1);
725    --animation-timing-fade-out: cubic-bezier(0.4, 0, 0.2, 1);
726    /* Spring definitions suffixed with perceptual duration (d<ms>) and bounce (b<%>)*/
727    --spring-d300-b0-easing: linear(0, 0.0033 0.81%, 0.027 2.42%, 0.0916 4.84%, 0.4745 15.32%, 0.6422 20.97%, 0.7175, 0.7789, 0.8283 30.64%, 0.876, 0.9111 38.71%, 0.941, 0.9611 48.39%, 0.9707, 0.978 54.84%, 0.9885 62.1%, 0.9949 70.97%, 0.9982 82.26%, 0.9997 100%);
728    --spring-d300-b0-duration: 0.4980s;
729    --spring-d280-b0-easing: linear(0, 0.0044, 0.0164 1.85%, 0.085 4.63%, 0.4571 14.81%, 0.575 18.52%, 0.6505, 0.7148 24.07%, 0.7849, 0.8393, 0.8809 35.18%, 0.9189, 0.9453 44.44%, 0.9662, 0.9793 55.55%, 0.9894 62.95%, 0.995 71.28%, 0.9982 82.39%, 0.9997 99.98%);
730    --spring-d280-b0-duration: 0.4648s;
731    --spring-d260-b0-easing: linear(0, 0.0058, 0.0216 2.15%, 0.0748 4.29%, 0.4646 15.03%, 0.5673, 0.655, 0.7279, 0.7872, 0.8349, 0.8727 34.36%, 0.9107, 0.9379 42.95%, 0.9609 48.31%, 0.9778 54.76%, 0.9887 62.27%, 0.9948 70.86%, 0.9983 82.67%, 0.9997 99.85%);
732    --spring-d260-b0-duration: 0.4316s;
733    --spring-d220-b0-easing: linear(
734      0,
735      0.0093 1.37%,
736      0.0696 4.12%,
737      0.4667 15.09%,
738      0.6322 20.58%,
739      0.6986 23.32%,
740      0.7793 27.44%,
741      0.8219 30.18%,
742      0.8721,
743      0.9089 38.42%,
744      0.9427,
745      0.9644,
746      0.978 54.88%,
747      0.9881 61.74%,
748      0.9944 69.97%,
749      0.998 80.95%,
750      0.9996 98.78%
751    );
752    --spring-d220-b0-duration: 0.3818s;
753    --spring-d180-b0-easing: linear(0, 0.0234, 0.0805 4.48%, 0.4865 15.68%, 0.6211 20.16%, 0.7696 26.88%, 0.8064 29.12%, 0.8646, 0.9063, 0.9358, 0.9563 47.04%, 0.9757, 0.9867 60.48%, 0.9941 69.44%, 0.9979 80.64%, 0.9996 98.56%);
754    --spring-d180-b0-duration: 0.2988s;
755
756    /* View transitions */
757    /* View transition old */
758    --view-transition-old-main-content: var(--animation-speed) var(--animation-easing) both fadeOut;
759
760    /* View transition new */
761    --view-transition-new-main-content: var(--animation-speed) var(--animation-easing) both fadeIn, var(--animation-speed) var(--animation-easing) both slideInTopViewTransition;
762
763    /* Focus */
764    --focus-outline-width: 0.09375rem;
765    --focus-outline-offset: 0.2em;
766
767    /* Badges */
768    --badge-blob-padding-block: 1px;
769    --badge-blob-padding-inline: 12px 8px;
770    --badge-rectangle-padding-block: 1px;
771    --badge-rectangle-padding-inline: 6px;
772    @media screen and (min-width: 750px) {
773      --badge-blob-padding-block: 4px;
774      --badge-blob-padding-inline: 16px 12px;
775      --badge-rectangle-padding-block: 4px;
776      --badge-rectangle-padding-inline: 10px;
777    }
778
779    /* Icons */
780    --icon-size-2xs: 0.6rem;
781    --icon-size-xs: 0.85rem;
782    --icon-size-sm: 1.25rem;
783    --icon-size-md: 1.375rem;
784    --icon-size-lg: 1.5rem;
785    --icon-stroke-width: 1.5px;
786
787    /* Input */
788    --input-email-min-width: 200px;
789    --input-search-max-width: 650px;
790    --input-padding-y: 0.8rem;
791    --input-padding-x: 0.8rem;
792    --input-padding: var(--input-padding-y) var(--input-padding-x);
793    --input-box-shadow-width: var(--style-border-width-inputs);
794    --input-box-shadow: 0 0 0 var(--input-box-shadow-width) var(--color-input-border);
795    --input-box-shadow-focus: 0 0 0 calc(var(--input-box-shadow-width) + 0.5px) var(--color-input-border);
796    --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10));
797    --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5));
798    --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50));
799    --input-textarea-min-height: 55px;
800
801    /* Checkbox */
802    --checkbox-size: 22px;
803    --checkbox-border-radius: 7px;
804    --checkbox-border: 1px solid rgb(var(--color-foreground-rgb) / var(--opacity-35-55));
805    --checkbox-label-padding: 8px;
806
807    @media screen and (min-width: 750px) {
808      --checkbox-size: 16px;
809      --checkbox-border-radius: 5px;
810      --checkbox-label-padding: 6px;
811    }
812
813    /* Button size */
814    --button-size-sm: 30px;
815    --button-size-md: 36px;
816    --button-size: var(--minimum-touch-target);
817    --button-padding-inline: 24px;
818    --button-padding-block: 16px;
819
820    /* Button font-family */
821    --button-font-family-primary: var(--font-body--family);
822    --button-font-family-secondary: var(--font-body--family);
823
824    /* Button text case */
825    --button-text-case: ;
826    --button-text-case-primary: default;
827    --button-text-case-secondary: default;
828
829    /* Borders */
830    --border-color: rgb(var(--color-border-rgb) / var(--opacity-50));
831    --border-width-sm: 1px;
832    --border-width-md: 2px;
833    --border-width-lg: 5px;
834    --border-radius-sm: 0.25rem;
835
836    /* Drawers */
837    --drawer-inline-padding: 25px;
838    --drawer-menu-inline-padding: 2.5rem;
839    --drawer-header-block-padding: 20px;
840    --drawer-content-block-padding: 10px;
841    --drawer-header-desktop-top: 0rem;
842    --drawer-padding: calc(var(--padding-sm) + 7px);
843    --drawer-height: 100dvh;
844    --drawer-width: 95vw;
845    --drawer-max-width: 500px;
846
847    /* Variant Picker Swatches */
848    --variant-picker-swatch-width-unitless: 34;
849    --variant-picker-swatch-height-unitless: 34;
850    --variant-picker-swatch-width: 34px;
851    --variant-picker-swatch-height: 34px;
852    --variant-picker-swatch-radius: 32px;
853    --variant-picker-border-width: 1px;
854    --variant-picker-border-style: solid;
855    --variant-picker-border-opacity: 10%;
856
857    /* Variant Picker Buttons */
858    --variant-picker-button-radius: 14px;
859    --variant-picker-button-border-width: 1px;
860
861    /* Slideshow */
862    --slideshow-controls-size: 3.5rem;
863    --slideshow-controls-icon: 2rem;
864    --peek-next-slide-size: 3rem;
865
866    /* Utilities */
867    --backdrop-opacity: 0.15;
868    --backdrop-color-rgb: var(--color-shadow-rgb);
869    --minimum-touch-target: 44px;
870    --disabled-opacity: 0.5;
871    --skeleton-opacity: 0.025;
872
873    /* Shapes */
874    --shape--circle: circle(50% at center);
875    --shape--sunburst: polygon(100% 50%,94.62% 55.87%,98.3% 62.94%,91.57% 67.22%,93.3% 75%,85.7% 77.39%,85.36% 85.36%,77.39% 85.7%,75% 93.3%,67.22% 91.57%,62.94% 98.3%,55.87% 94.62%,50% 100%,44.13% 94.62%,37.06% 98.3%,32.78% 91.57%,25% 93.3%,22.61% 85.7%,14.64% 85.36%,14.3% 77.39%,6.7% 75%,8.43% 67.22%,1.7% 62.94%,5.38% 55.87%,0% 50%,5.38% 44.13%,1.7% 37.06%,8.43% 32.78%,6.7% 25%,14.3% 22.61%,14.64% 14.64%,22.61% 14.3%,25% 6.7%,32.78% 8.43%,37.06% 1.7%,44.13% 5.38%,50% 0%,55.87% 5.38%,62.94% 1.7%,67.22% 8.43%,75% 6.7%,77.39% 14.3%,85.36% 14.64%,85.7% 22.61%,93.3% 25%,91.57% 32.78%,98.3% 37.06%,94.62% 44.13%);
876    --shape--diamond: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
877    --shape--blob: polygon(85.349% 11.712%, 87.382% 13.587%, 89.228% 15.647%, 90.886% 17.862%, 92.359% 20.204%, 93.657% 22.647%, 94.795% 25.169%, 95.786% 27.752%, 96.645% 30.382%, 97.387% 33.048%, 98.025% 35.740%, 98.564% 38.454%, 99.007% 41.186%, 99.358% 43.931%, 99.622% 46.685%, 99.808% 49.446%, 99.926% 52.210%, 99.986% 54.977%, 99.999% 57.744%, 99.975% 60.511%, 99.923% 63.278%, 99.821% 66.043%, 99.671% 68.806%, 99.453% 71.565%, 99.145% 74.314%, 98.724% 77.049%, 98.164% 79.759%, 97.433% 82.427%, 96.495% 85.030%, 95.311% 87.529%, 93.841% 89.872%, 92.062% 91.988%, 89.972% 93.796%, 87.635% 95.273%, 85.135% 96.456%, 82.532% 97.393%, 79.864% 98.127%, 77.156% 98.695%, 74.424% 99.129%, 71.676% 99.452%, 68.918% 99.685%, 66.156% 99.844%, 63.390% 99.942%, 60.624% 99.990%, 57.856% 99.999%, 55.089% 99.978%, 52.323% 99.929%, 49.557% 99.847%, 46.792% 99.723%, 44.031% 99.549%, 41.273% 99.317%, 38.522% 99.017%, 35.781% 98.639%, 33.054% 98.170%, 30.347% 97.599%, 27.667% 96.911%, 25.024% 96.091%, 22.432% 95.123%, 19.907% 93.994%, 17.466% 92.690%, 15.126% 91.216%, 12.902% 89.569%, 10.808% 87.761%, 8.854% 85.803%, 7.053% 83.703%, 5.418% 81.471%, 3.962% 79.119%, 2.702% 76.656%, 1.656% 74.095%, 0.846% 71.450%, 0.294% 68.740%, 0.024% 65.987%, 0.050% 63.221%, 0.343% 60.471%, 0.858% 57.752%, 1.548% 55.073%, 2.370% 52.431%, 3.283% 49.819%, 4.253% 47.227%, 5.249% 44.646%, 6.244% 42.063%, 7.211% 39.471%, 8.124% 36.858%, 8.958% 34.220%, 9.711% 31.558%, 10.409% 28.880%, 11.083% 26.196%, 11.760% 23.513%, 12.474% 20.839%, 13.259% 18.186%, 14.156% 15.569%, 15.214% 13.012%, 16.485% 10.556%, 18.028% 8.261%, 19.883
877% 6.211%, 22.041% 4.484%, 24.440% 3.110%, 26.998% 2.057%, 29.651% 1.275%, 32.360% 0.714%, 35.101% 0.337%, 37.859% 0.110%, 40.624% 0.009%, 43.391% 0.016%, 46.156% 0.113%, 48.918% 0.289%, 51.674% 0.533%, 54.425% 0.837%, 57.166% 1.215%, 59.898% 1.654%, 62.618% 2.163%, 65.322% 2.750%, 68.006% 3.424%, 70.662% 4.197%, 73.284% 5.081%, 75.860% 6.091%, 78.376% 7.242%, 80.813% 8.551%, 83.148% 10.036%, 85.349% 11.712%);
878
879    /* Buy buttons */
880    --height-buy-buttons: calc(var(--padding-lg) * 2 + var(--icon-size-sm));
881
882    /* Card image width and height variables */
883    --card-width-small: 10rem;
884
885    --height-small: 10rem;
886    --height-medium: 11.5rem;
887    --height-large: 13rem;
888    --height-full: 100vh;
889
890    @media screen and (min-width: 750px) {
891      --height-small: 17.5rem;
892      --height-medium: 21.25rem;
893      --height-large: 25rem;
894    }
895
896    /* Modal */
897    --modal-max-height: 65dvh;
898    --quick-add-modal-height: min(38.5rem, 96vh);
899    --quick-add-modal-width: min(54rem, 96vw);
900    --quick-add-modal-gallery-width: 24rem;
901
902    /* Card styles for search */
903    --card-bg-hover: rgb(var(--color-foreground-rgb) / var(--opacity-5));
904    --card-border-hover: rgb(var(--color-foreground-rgb) / var(--opacity-30));
905    --card-border-focus: rgb(var(--color-foreground-rgb) / var(--opacity-10));
906
907    /* Cart */
908    --cart-primary-font-family: var(--font-body--family);
909    --cart-primary-font-style: var(--font-body--style);
910    --cart-primary-font-weight: var(--font-body--weight);
911    --cart-secondary-font-family: var(--font-secondary--family);
912    --cart-secondary-font-style: var(--font-secondary--style);
913    --cart-secondary-font-weight: var(--font-secondary--weight);
914  }
915</style>
916
917
918<style data-shopify>
919  
920    
921      :root,
922    
923    
924    
925    .color-scheme-1 {
926        --color-background: rgb(254 255 250 / 1.0);
927        /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */
928        --color-background-rgb: 254 255 250;
929        --opacity-5-15: 0.05;
930        --opacity-10-25: 0.1;
931        --opacity-35-55: 0.35;
932        --opacity-40-60: 0.4;
933        --opacity-30-60: 0.3;
934        --color-foreground: rgb(0 0 0 / 0.81);
935        --color-foreground-rgb: 0 0 0;
936        --color-foreground-heading: rgb(0 0 0 / 1.0);
937        --color-foreground-heading-rgb: 0 0 0;
938        --color-primary: rgb(0 0 0 / 0.81);
939        --color-primary-rgb: 0 0 0;
940        --color-primary-hover: rgb(0 0 0 / 1.0);
941        --color-primary-hover-rgb: 0 0 0;
942        --color-border: rgb(0 0 0 / 0.06);
943        --color-border-rgb: 0 0 0;
944        --color-shadow: rgb(0 0 0 / 1.0);
945        --color-shadow-rgb: 0 0 0;
946        --color-primary-button-text: rgb(255 255 255 / 1.0);
947        --color-primary-button-background: rgb(0 0 0 / 1.0);
948        --color-primary-button-border: rgb(0 0 0 / 1.0);
949        --color-primary-button-hover-text: rgb(255 255 255 / 1.0);
950        --color-primary-button-hover-background: rgb(51 51 51 / 1.0);
951        --color-primary-button-hover-border: rgb(0 0 0 / 1.0);
952        --color-secondary-button-text: rgb(0 0 0 / 1.0);
953        --color-secondary-button-background: rgb(0 0 0 / 0.0);
954        --color-secondary-button-border: rgb(0 0 0 / 1.0);
955        --color-secondary-button-hover-text: rgb(51 51 51 / 1.0);
956        --color-secondary-button-hover-background: rgb(250 250 250 / 1.0);
957        --color-secondary-button-hover-border: rgb(51 51 51 / 1.0);
958        --color-input-background: rgb(255 255 255 / 0.78);
959        --color-input-text: rgb(51 51 51 / 1.0);
960        --color-input-text-rgb: 51 51 51;
961        --color-input-border: rgb(223 223 223 / 1.0);
962        --color-input-hover-background: rgb(0 0 0 / 0.01);
963        --color-variant-background: rgb(255 255 255 / 1.0);
964        --color-variant-border: rgb(0 0 0 / 0.13);
965        --color-variant-text: rgb(0 0 0 / 1.0);
966        --color-variant-text-rgb: 0 0 0;
967        --color-variant-hover-background: rgb(245 245 245 / 1.0);
968        --color-variant-hover-text: rgb(0 0 0 / 1.0);
969        --color-variant-hover-border: rgb(230 230 230 / 1.0);
970        --color-selected-variant-background: rgb(0 0 0 / 1.0);
971        --color-selected-variant-border: rgb(0 0 0 / 1.0);
972        --color-selected-variant-text: rgb(255 255 255 / 1.0);
973        --color-selected-variant-hover-background: rgb(26 26 26 / 1.0);
974        --color-selected-variant-hover-text: rgb(255 255 255 / 1.0);
975        --color-selected-variant-hover-border: rgb(26 26 26 / 1.0);
976
977        --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10));
978        --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15));
979        --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50));
980        --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60));
981        --font-h1--color: var(--color-foreground-heading);
982        --font-h2--color: var(--color-foreground-heading);
983        --font-h3--color: var(--color-foreground-heading);
984        --font-h4--color: var(--color-foreground-heading);
985        --font-h5--color: var(--color-foreground-heading);
986        --font-h6--color: var(--color-foreground-heading);
987
988        /* Shadows */
989        
990          --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
991        
992        
993          --shadow-blur: 20px;
994          --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
995        
996      }
997  
998    
999    
1000    
1001    .color-scheme-2 {
1002        --color-background: rgb(245 245 245 / 1.0);
1003        /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */
1004        --color-background-rgb: 245 245 245;
1005        --opacity-5-15: 0.05;
1006        --opacity-10-25: 0.1;
1007        --opacity-35-55: 0.35;
1008        --opacity-40-60: 0.4;
1009        --opacity-30-60: 0.3;
1010        --color-foreground: rgb(0 0 0 / 0.81);
1011        --color-foreground-rgb: 0 0 0;
1012        --color-foreground-heading: rgb(0 0 0 / 1.0);
1013        --color-foreground-heading-rgb: 0 0 0;
1014        --color-primary: rgb(0 0 0 / 0.81);
1015        --color-primary-rgb: 0 0 0;
1016        --color-primary-hover: rgb(255 255 255 / 1.0);
1017        --color-primary-hover-rgb: 255 255 255;
1018        --color-border: rgb(223 223 223 / 1.0);
1019        --color-border-rgb: 223 223 223;
1020        --color-shadow: rgb(0 0 0 / 1.0);
1021        --color-shadow-rgb: 0 0 0;
1022        --color-primary-button-text: rgb(255 255 255 / 1.0);
1023        --color-primary-button-background: rgb(0 0 0 / 1.0);
1024        --color-primary-button-border: rgb(0 0 0 / 1.0);
1025        --color-primary-button-hover-text: rgb(255 255 255 / 1.0);
1026        --color-primary-button-hover-background: rgb(51 51 51 / 1.0);
1027        --color-primary-button-hover-border: rgb(51 51 51 / 1.0);
1028        --color-secondary-button-text: rgb(0 0 0 / 1.0);
1029        --color-secondary-button-background: rgb(0 0 0 / 0.0);
1030        --color-secondary-button-border: rgb(0 0 0 / 1.0);
1031        --color-secondary-button-hover-text: rgb(0 0 0 / 1.0);
1032        --color-secondary-button-hover-background: rgb(255 255 255 / 0.36);
1033        --color-secondary-button-hover-border: rgb(51 51 51 / 0.73);
1034        --color-input-background: rgb(0 0 0 / 0.0);
1035        --color-input-text: rgb(0 0 0 / 0.53);
1036        --color-input-text-rgb: 0 0 0;
1037        --color-input-border: rgb(0 0 0 / 0.13);
1038        --color-input-hover-background: rgb(255 255 255 / 0.36);
1039        --color-variant-background: rgb(255 255 255 / 1.0);
1040        --color-variant-border: rgb(230 230 230 / 1.0);
1041        --color-variant-text: rgb(0 0 0 / 1.0);
1042        --color-variant-text-rgb: 0 0 0;
1043        --color-variant-hover-background: rgb(245 245 245 / 1.0);
1044        --color-variant-hover-text: rgb(0 0 0 / 1.0);
1045        --color-variant-hover-border: rgb(230 230 230 / 1.0);
1046        --color-selected-variant-background: rgb(0 0 0 / 1.0);
1047        --color-selected-variant-border: rgb(0 0 0 / 1.0);
1048        --color-selected-variant-text: rgb(255 255 255 / 1.0);
1049        --color-selected-variant-hover-background: rgb(26 26 26 / 1.0);
1050        --color-selected-variant-hover-text: rgb(255 255 255 / 1.0);
1051        --color-selected-variant-hover-border: rgb(26 26 26 / 1.0);
1052
1053        --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10));
1054        --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15));
1055        --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50));
1056        --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60));
1057        --font-h1--color: var(--color-foreground-heading);
1058        --font-h2--color: var(--color-foreground-heading);
1059        --font-h3--color: var(--color-foreground-heading);
1060        --font-h4--color: var(--color-foreground-heading);
1061        --font-h5--color: var(--color-foreground-heading);
1062        --font-h6--color: var(--color-foreground-heading);
1063
1064        /* Shadows */
1065        
1066          --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1067        
1068        
1069          --shadow-blur: 20px;
1070          --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1071        
1072      }
1073  
1074    
1075    
1076    
1077    .color-scheme-3 {
1078        --color-background: rgb(238 241 234 / 1.0);
1079        /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */
1080        --color-background-rgb: 238 241 234;
1081        --opacity-5-15: 0.05;
1082        --opacity-10-25: 0.1;
1083        --opacity-35-55: 0.35;
1084        --opacity-40-60: 0.4;
1085        --opacity-30-60: 0.3;
1086        --color-foreground: rgb(0 0 0 / 0.81);
1087        --color-foreground-rgb: 0 0 0;
1088        --color-foreground-heading: rgb(0 0 0 / 1.0);
1089        --color-foreground-heading-rgb: 0 0 0;
1090        --color-primary: rgb(0 0 0 / 0.81);
1091        --color-primary-rgb: 0 0 0;
1092        --color-primary-hover: rgb(0 0 0 / 1.0);
1093        --color-primary-hover-rgb: 0 0 0;
1094        --color-border: rgb(0 0 0 / 0.81);
1095        --color-border-rgb: 0 0 0;
1096        --color-shadow: rgb(0 0 0 / 1.0);
1097        --color-shadow-rgb: 0 0 0;
1098        --color-primary-button-text: rgb(255 255 255 / 1.0);
1099        --color-primary-button-background: rgb(0 0 0 / 1.0);
1100        --color-primary-button-border: rgb(0 0 0 / 1.0);
1101        --color-primary-button-hover-text: rgb(255 255 255 / 1.0);
1102        --color-primary-button-hover-background: rgb(51 51 51 / 1.0);
1103        --color-primary-button-hover-border: rgb(51 51 51 / 1.0);
1104        --color-secondary-button-text: rgb(0 0 0 / 1.0);
1105        --color-secondary-button-background: rgb(0 0 0 / 0.0);
1106        --color-secondary-button-border: rgb(0 0 0 / 1.0);
1107        --color-secondary-button-hover-text: rgb(0 0 0 / 0.81);
1108        --color-secondary-button-hover-background: rgb(255 255 255 / 0.36);
1109        --color-secondary-button-hover-border: rgb(0 0 0 / 0.81);
1110        --color-input-background: rgb(0 0 0 / 0.0);
1111        --color-input-text: rgb(0 0 0 / 0.81);
1112        --color-input-text-rgb: 0 0 0;
1113        --color-input-border: rgb(0 0 0 / 0.81);
1114        --color-input-hover-background: rgb(255 255 255 / 0.36);
1115        --color-variant-background: rgb(255 255 255 / 1.0);
1116        --color-variant-border: rgb(230 230 230 / 1.0);
1117        --color-variant-text: rgb(0 0 0 / 1.0);
1118        --color-variant-text-rgb: 0 0 0;
1119        --color-variant-hover-background: rgb(245 245 245 / 1.0);
1120        --color-variant-hover-text: rgb(0 0 0 / 1.0);
1121        --color-variant-hover-border: rgb(230 230 230 / 1.0);
1122        --color-selected-variant-background: rgb(0 0 0 / 1.0);
1123        --color-selected-variant-border: rgb(0 0 0 / 1.0);
1124        --color-selected-variant-text: rgb(255 255 255 / 1.0);
1125        --color-selected-variant-hover-background: rgb(26 26 26 / 1.0);
1126        --color-selected-variant-hover-text: rgb(255 255 255 / 1.0);
1127        --color-selected-variant-hover-border: rgb(26 26 26 / 1.0);
1128
1129        --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10));
1130        --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15));
1131        --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50));
1132        --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60));
1133        --font-h1--color: var(--color-foreground-heading);
1134        --font-h2--color: var(--color-foreground-heading);
1135        --font-h3--color: var(--color-foreground-heading);
1136        --font-h4--color: var(--color-foreground-heading);
1137        --font-h5--color: var(--color-foreground-heading);
1138        --font-h6--color: var(--color-foreground-heading);
1139
1140        /* Shadows */
1141        
1142          --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1143        
1144        
1145          --shadow-blur: 20px;
1146          --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1147        
1148      }
1149  
1150    
1151    
1152    
1153    .color-scheme-4 {
1154        --color-background: rgb(225 237 245 / 1.0);
1155        /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */
1156        --color-background-rgb: 225 237 245;
1157        --opacity-5-15: 0.05;
1158        --opacity-10-25: 0.1;
1159        --opacity-35-55: 0.35;
1160        --opacity-40-60: 0.4;
1161        --opacity-30-60: 0.3;
1162        --color-foreground: rgb(0 0 0 / 0.81);
1163        --color-foreground-rgb: 0 0 0;
1164        --color-foreground-heading: rgb(0 0 0 / 1.0);
1165        --color-foreground-heading-rgb: 0 0 0;
1166        --color-primary: rgb(0 0 0 / 0.81);
1167        --color-primary-rgb: 0 0 0;
1168        --color-primary-hover: rgb(0 0 0 / 1.0);
1169        --color-primary-hover-rgb: 0 0 0;
1170        --color-border: rgb(29 54 134 / 0.5);
1171        --color-border-rgb: 29 54 134;
1172        --color-shadow: rgb(0 0 0 / 1.0);
1173        --color-shadow-rgb: 0 0 0;
1174        --color-primary-button-text: rgb(255 255 255 / 1.0);
1175        --color-primary-button-background: rgb(0 0 0 / 1.0);
1176        --color-primary-button-border: rgb(29 54 134 / 1.0);
1177        --color-primary-button-hover-text: rgb(255 255 255 / 1.0);
1178        --color-primary-button-hover-background: rgb(51 51 51 / 1.0);
1179        --color-primary-button-hover-border: rgb(0 0 0 / 1.0);
1180        --color-secondary-button-text: rgb(0 0 0 / 1.0);
1181        --color-secondary-button-background: rgb(0 0 0 / 0.0);
1182        --color-secondary-button-border: rgb(0 0 0 / 1.0);
1183        --color-secondary-button-hover-text: rgb(0 0 0 / 0.81);
1184        --color-secondary-button-hover-background: rgb(255 255 255 / 0.36);
1185        --color-secondary-button-hover-border: rgb(0 0 0 / 0.81);
1186        --color-input-background: rgb(0 0 0 / 0.0);
1187        --color-input-text: rgb(0 0 0 / 0.81);
1188        --color-input-text-rgb: 0 0 0;
1189        --color-input-border: rgb(0 0 0 / 0.81);
1190        --color-input-hover-background: rgb(255 255 255 / 0.36);
1191        --color-variant-background: rgb(255 255 255 / 1.0);
1192        --color-variant-border: rgb(230 230 230 / 1.0);
1193        --color-variant-text: rgb(0 0 0 / 1.0);
1194        --color-variant-text-rgb: 0 0 0;
1195        --color-variant-hover-background: rgb(245 245 245 / 1.0);
1196        --color-variant-hover-text: rgb(0 0 0 / 1.0);
1197        --color-variant-hover-border: rgb(230 230 230 / 1.0);
1198        --color-selected-variant-background: rgb(0 0 0 / 1.0);
1199        --color-selected-variant-border: rgb(0 0 0 / 1.0);
1200        --color-selected-variant-text: rgb(255 255 255 / 1.0);
1201        --color-selected-variant-hover-background: rgb(26 26 26 / 1.0);
1202        --color-selected-variant-hover-text: rgb(255 255 255 / 1.0);
1203        --color-selected-variant-hover-border: rgb(26 26 26 / 1.0);
1204
1205        --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10));
1206        --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15));
1207        --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50));
1208        --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60));
1209        --font-h1--color: var(--color-foreground-heading);
1210        --font-h2--color: var(--color-foreground-heading);
1211        --font-h3--color: var(--color-foreground-heading);
1212        --font-h4--color: var(--color-foreground-heading);
1213        --font-h5--color: var(--color-foreground-heading);
1214        --font-h6--color: var(--color-foreground-heading);
1215
1216        /* Shadows */
1217        
1218          --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1219        
1220        
1221          --shadow-blur: 20px;
1222          --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1223        
1224      }
1225  
1226    
1227    
1228    
1229    .color-scheme-5 {
1230        --color-background: rgb(51 51 51 / 1.0);
1231        /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */
1232        --color-background-rgb: 51 51 51;
1233        --opacity-5-15: 0.15;
1234        --opacity-10-25: 0.25;
1235        --opacity-35-55: 0.55;
1236        --opacity-40-60: 0.6;
1237        --opacity-30-60: 0.6;
1238        --color-foreground: rgb(255 255 255 / 1.0);
1239        --color-foreground-rgb: 255 255 255;
1240        --color-foreground-heading: rgb(255 255 255 / 1.0);
1241        --color-foreground-heading-rgb: 255 255 255;
1242        --color-primary: rgb(255 255 255 / 1.0);
1243        --color-primary-rgb: 255 255 255;
1244        --color-primary-hover: rgb(255 255 255 / 0.69);
1245        --color-primary-hover-rgb: 255 255 255;
1246        --color-border: rgb(255 255 255 / 0.69);
1247        --color-border-rgb: 255 255 255;
1248        --color-shadow: rgb(0 0 0 / 1.0);
1249        --color-shadow-rgb: 0 0 0;
1250        --color-primary-button-text: rgb(0 0 0 / 1.0);
1251        --color-primary-button-background: rgb(255 255 255 / 1.0);
1252        --color-primary-button-border: rgb(255 255 255 / 1.0);
1253        --color-primary-button-hover-text: rgb(255 255 255 / 1.0);
1254        --color-primary-button-hover-background: rgb(0 0 0 / 1.0);
1255        --color-primary-button-hover-border: rgb(0 0 0 / 1.0);
1256        --color-secondary-button-text: rgb(255 255 255 / 1.0);
1257        --color-secondary-button-background: rgb(0 0 0 / 0.0);
1258        --color-secondary-button-border: rgb(255 255 255 / 0.69);
1259        --color-secondary-button-hover-text: rgb(255 255 255 / 0.93);
1260        --color-secondary-button-hover-background: rgb(255 255 255 / 0.04);
1261        --color-secondary-button-hover-border: rgb(255 255 255 / 0.69);
1262        --color-input-background: rgb(51 51 51 / 1.0);
1263        --color-input-text: rgb(255 255 255 / 0.93);
1264        --color-input-text-rgb: 255 255 255;
1265        --color-input-border: rgb(255 255 255 / 0.69);
1266        --color-input-hover-background: rgb(255 255 255 / 0.04);
1267        --color-variant-background: rgb(255 255 255 / 1.0);
1268        --color-variant-border: rgb(230 230 230 / 1.0);
1269        --color-variant-text: rgb(0 0 0 / 1.0);
1270        --color-variant-text-rgb: 0 0 0;
1271        --color-variant-hover-background: rgb(245 245 245 / 1.0);
1272        --color-variant-hover-text: rgb(0 0 0 / 1.0);
1273        --color-variant-hover-border: rgb(230 230 230 / 1.0);
1274        --color-selected-variant-background: rgb(0 0 0 / 1.0);
1275        --color-selected-variant-border: rgb(0 0 0 / 1.0);
1276        --color-selected-variant-text: rgb(255 255 255 / 1.0);
1277        --color-selected-variant-hover-background: rgb(26 26 26 / 1.0);
1278        --color-selected-variant-hover-text: rgb(255 255 255 / 1.0);
1279        --color-selected-variant-hover-border: rgb(26 26 26 / 1.0);
1280
1281        --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10));
1282        --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15));
1283        --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50));
1284        --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60));
1285        --font-h1--color: var(--color-foreground-heading);
1286        --font-h2--color: var(--color-foreground-heading);
1287        --font-h3--color: var(--color-foreground-heading);
1288        --font-h4--color: var(--color-foreground-heading);
1289        --font-h5--color: var(--color-foreground-heading);
1290        --font-h6--color: var(--color-foreground-heading);
1291
1292        /* Shadows */
1293        
1294          --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1295        
1296        
1297          --shadow-blur: 20px;
1298          --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1299        
1300      }
1301  
1302    
1303    
1304    
1305    .color-scheme-6 {
1306        --color-background: rgb(0 0 0 / 0.0);
1307        /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */
1308        --color-background-rgb: 0 0 0;
1309        --opacity-5-15: 0.15;
1310        --opacity-10-25: 0.25;
1311        --opacity-35-55: 0.55;
1312        --opacity-40-60: 0.6;
1313        --opacity-30-60: 0.6;
1314        --color-foreground: rgb(255 255 255 / 1.0);
1315        --color-foreground-rgb: 255 255 255;
1316        --color-foreground-heading: rgb(255 255 255 / 1.0);
1317        --color-foreground-heading-rgb: 255 255 255;
1318        --color-primary: rgb(255 255 255 / 1.0);
1319        --color-primary-rgb: 255 255 255;
1320        --color-primary-hover: rgb(255 255 255 / 0.69);
1321        --color-primary-hover-rgb: 255 255 255;
1322        --color-border: rgb(230 230 230 / 1.0);
1323        --color-border-rgb: 230 230 230;
1324        --color-shadow: rgb(0 0 0 / 1.0);
1325        --color-shadow-rgb: 0 0 0;
1326        --color-primary-button-text: rgb(0 0 0 / 1.0);
1327        --color-primary-button-background: rgb(255 255 255 / 1.0);
1328        --color-primary-button-border: rgb(255 255 255 / 1.0);
1329        --color-primary-button-hover-text: rgb(255 255 255 / 1.0);
1330        --color-primary-button-hover-background: rgb(0 0 0 / 1.0);
1331        --color-primary-button-hover-border: rgb(0 0 0 / 1.0);
1332        --color-secondary-button-text: rgb(255 255 255 / 1.0);
1332
1333        --color-secondary-button-background: rgb(0 0 0 / 0.0);
1334        --color-secondary-button-border: rgb(255 255 255 / 1.0);
1335        --color-secondary-button-hover-text: rgb(255 255 255 / 1.0);
1336        --color-secondary-button-hover-background: rgb(255 255 255 / 0.08);
1337        --color-secondary-button-hover-border: rgb(255 255 255 / 1.0);
1338        --color-input-background: rgb(255 255 255 / 1.0);
1339        --color-input-text: rgb(0 0 0 / 0.53);
1340        --color-input-text-rgb: 0 0 0;
1341        --color-input-border: rgb(0 0 0 / 0.13);
1342        --color-input-hover-background: rgb(250 250 250 / 1.0);
1343        --color-variant-background: rgb(255 255 255 / 1.0);
1344        --color-variant-border: rgb(230 230 230 / 1.0);
1345        --color-variant-text: rgb(0 0 0 / 1.0);
1346        --color-variant-text-rgb: 0 0 0;
1347        --color-variant-hover-background: rgb(245 245 245 / 1.0);
1348        --color-variant-hover-text: rgb(0 0 0 / 1.0);
1349        --color-variant-hover-border: rgb(230 230 230 / 1.0);
1350        --color-selected-variant-background: rgb(0 0 0 / 1.0);
1351        --color-selected-variant-border: rgb(0 0 0 / 1.0);
1352        --color-selected-variant-text: rgb(255 255 255 / 1.0);
1353        --color-selected-variant-hover-background: rgb(26 26 26 / 1.0);
1354        --color-selected-variant-hover-text: rgb(255 255 255 / 1.0);
1355        --color-selected-variant-hover-border: rgb(26 26 26 / 1.0);
1356
1357        --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10));
1358        --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15));
1359        --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50));
1360        --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60));
1361        --font-h1--color: var(--color-foreground-heading);
1362        --font-h2--color: var(--color-foreground-heading);
1363        --font-h3--color: var(--color-foreground-heading);
1364        --font-h4--color: var(--color-foreground-heading);
1365        --font-h5--color: var(--color-foreground-heading);
1366        --font-h6--color: var(--color-foreground-heading);
1367
1368        /* Shadows */
1369        
1370          --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1371        
1372        
1373          --shadow-blur: 20px;
1374          --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1375        
1376      }
1377  
1378    
1379    
1380    
1381    .color-scheme-58084d4c-a86e-4d0a-855e-a0966e5043f7 {
1382        --color-background: rgb(0 0 0 / 0.0);
1383        /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */
1384        --color-background-rgb: 0 0 0;
1385        --opacity-5-15: 0.15;
1386        --opacity-10-25: 0.25;
1387        --opacity-35-55: 0.55;
1388        --opacity-40-60: 0.6;
1389        --opacity-30-60: 0.6;
1390        --color-foreground: rgb(0 0 0 / 1.0);
1391        --color-foreground-rgb: 0 0 0;
1392        --color-foreground-heading: rgb(0 0 0 / 1.0);
1393        --color-foreground-heading-rgb: 0 0 0;
1394        --color-primary: rgb(0 0 0 / 1.0);
1395        --color-primary-rgb: 0 0 0;
1396        --color-primary-hover: rgb(0 0 0 / 0.53);
1397        --color-primary-hover-rgb: 0 0 0;
1398        --color-border: rgb(230 230 230 / 1.0);
1399        --color-border-rgb: 230 230 230;
1400        --color-shadow: rgb(0 0 0 / 1.0);
1401        --color-shadow-rgb: 0 0 0;
1402        --color-primary-button-text: rgb(255 255 255 / 1.0);
1403        --color-primary-button-background: rgb(0 0 0 / 1.0);
1404        --color-primary-button-border: rgb(0 0 0 / 1.0);
1405        --color-primary-button-hover-text: rgb(255 255 255 / 1.0);
1406        --color-primary-button-hover-background: rgb(51 51 51 / 1.0);
1407        --color-primary-button-hover-border: rgb(51 51 51 / 1.0);
1408        --color-secondary-button-text: rgb(0 0 0 / 1.0);
1409        --color-secondary-button-background: rgb(0 0 0 / 0.0);
1410        --color-secondary-button-border: rgb(0 0 0 / 1.0);
1411        --color-secondary-button-hover-text: rgb(51 51 51 / 1.0);
1412        --color-secondary-button-hover-background: rgb(250 250 250 / 1.0);
1413        --color-secondary-button-hover-border: rgb(51 51 51 / 1.0);
1414        --color-input-background: rgb(255 255 255 / 1.0);
1415        --color-input-text: rgb(0 0 0 / 0.53);
1416        --color-input-text-rgb: 0 0 0;
1417        --color-input-border: rgb(0 0 0 / 0.13);
1418        --color-input-hover-background: rgb(250 250 250 / 1.0);
1419        --color-variant-background: rgb(255 255 255 / 1.0);
1420        --color-variant-border: rgb(230 230 230 / 1.0);
1421        --color-variant-text: rgb(0 0 0 / 1.0);
1422        --color-variant-text-rgb: 0 0 0;
1423        --color-variant-hover-background: rgb(245 245 245 / 1.0);
1424        --color-variant-hover-text: rgb(0 0 0 / 1.0);
1425        --color-variant-hover-border: rgb(230 230 230 / 1.0);
1426        --color-selected-variant-background: rgb(0 0 0 / 1.0);
1427        --color-selected-variant-border: rgb(0 0 0 / 1.0);
1428        --color-selected-variant-text: rgb(255 255 255 / 1.0);
1429        --color-selected-variant-hover-background: rgb(26 26 26 / 1.0);
1430        --color-selected-variant-hover-text: rgb(255 255 255 / 1.0);
1431        --color-selected-variant-hover-border: rgb(26 26 26 / 1.0);
1432
1433        --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10));
1434        --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15));
1435        --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50));
1436        --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60));
1437        --font-h1--color: var(--color-foreground-heading);
1438        --font-h2--color: var(--color-foreground-heading);
1439        --font-h3--color: var(--color-foreground-heading);
1440        --font-h4--color: var(--color-foreground-heading);
1441        --font-h5--color: var(--color-foreground-heading);
1442        --font-h6--color: var(--color-foreground-heading);
1443
1444        /* Shadows */
1445        
1446          --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1447        
1448        
1449          --shadow-blur: 20px;
1450          --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1451        
1452      }
1453  
1454    
1455    
1456    
1457    .color-scheme-515910f4-a3e9-48d3-8079-ac481ef96b10 {
1458        --color-background: rgb(254 255 250 / 1.0);
1459        /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */
1460        --color-background-rgb: 254 255 250;
1461        --opacity-5-15: 0.05;
1462        --opacity-10-25: 0.1;
1463        --opacity-35-55: 0.35;
1464        --opacity-40-60: 0.4;
1465        --opacity-30-60: 0.3;
1466        --color-foreground: rgb(0 0 0 / 0.81);
1467        --color-foreground-rgb: 0 0 0;
1468        --color-foreground-heading: rgb(0 0 0 / 1.0);
1469        --color-foreground-heading-rgb: 0 0 0;
1470        --color-primary: rgb(0 0 0 / 0.81);
1471        --color-primary-rgb: 0 0 0;
1472        --color-primary-hover: rgb(0 0 0 / 1.0);
1473        --color-primary-hover-rgb: 0 0 0;
1474        --color-border: rgb(0 0 0 / 0.06);
1475        --color-border-rgb: 0 0 0;
1476        --color-shadow: rgb(0 0 0 / 1.0);
1477        --color-shadow-rgb: 0 0 0;
1478        --color-primary-button-text: rgb(255 255 255 / 1.0);
1479        --color-primary-button-background: rgb(0 0 0 / 1.0);
1480        --color-primary-button-border: rgb(0 0 0 / 1.0);
1481        --color-primary-button-hover-text: rgb(255 255 255 / 1.0);
1482        --color-primary-button-hover-background: rgb(51 51 51 / 1.0);
1483        --color-primary-button-hover-border: rgb(0 0 0 / 1.0);
1484        --color-secondary-button-text: rgb(0 0 0 / 1.0);
1485        --color-secondary-button-background: rgb(0 0 0 / 0.0);
1486        --color-secondary-button-border: rgb(0 0 0 / 1.0);
1487        --color-secondary-button-hover-text: rgb(51 51 51 / 1.0);
1488        --color-secondary-button-hover-background: rgb(250 250 250 / 1.0);
1489        --color-secondary-button-hover-border: rgb(51 51 51 / 1.0);
1490        --color-input-background: rgb(255 255 255 / 0.78);
1491        --color-input-text: rgb(51 51 51 / 1.0);
1492        --color-input-text-rgb: 51 51 51;
1493        --color-input-border: rgb(223 223 223 / 1.0);
1494        --color-input-hover-background: rgb(0 0 0 / 0.01);
1495        --color-variant-background: rgb(255 255 255 / 1.0);
1496        --color-variant-border: rgb(0 0 0 / 0.13);
1497        --color-variant-text: rgb(0 0 0 / 1.0);
1498        --color-variant-text-rgb: 0 0 0;
1499        --color-variant-hover-background: rgb(245 245 245 / 1.0);
1500        --color-variant-hover-text: rgb(0 0 0 / 1.0);
1501        --color-variant-hover-border: rgb(230 230 230 / 1.0);
1502        --color-selected-variant-background: rgb(0 0 0 / 1.0);
1503        --color-selected-variant-border: rgb(0 0 0 / 1.0);
1504        --color-selected-variant-text: rgb(255 255 255 / 1.0);
1505        --color-selected-variant-hover-background: rgb(26 26 26 / 1.0);
1506        --color-selected-variant-hover-text: rgb(255 255 255 / 1.0);
1507        --color-selected-variant-hover-border: rgb(26 26 26 / 1.0);
1508
1509        --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10));
1510        --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15));
1511        --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50));
1512        --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60));
1513        --font-h1--color: var(--color-foreground-heading);
1514        --font-h2--color: var(--color-foreground-heading);
1515        --font-h3--color: var(--color-foreground-heading);
1516        --font-h4--color: var(--color-foreground-heading);
1517        --font-h5--color: var(--color-foreground-heading);
1518        --font-h6--color: var(--color-foreground-heading);
1519
1520        /* Shadows */
1521        
1522          --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1523        
1524        
1525          --shadow-blur: 20px;
1526          --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1527        
1528      }
1529  
1530    
1531    
1532    
1533    .color-scheme-d70ac8c4-eb3e-43d2-9c84-148cdbac2972 {
1534        --color-background: rgb(247 246 234 / 1.0);
1535        /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */
1536        --color-background-rgb: 247 246 234;
1537        --opacity-5-15: 0.05;
1538        --opacity-10-25: 0.1;
1539        --opacity-35-55: 0.35;
1540        --opacity-40-60: 0.4;
1541        --opacity-30-60: 0.3;
1542        --color-foreground: rgb(23 22 9 / 1.0);
1543        --color-foreground-rgb: 23 22 9;
1544        --color-foreground-heading: rgb(23 22 9 / 1.0);
1545        --color-foreground-heading-rgb: 23 22 9;
1546        --color-primary: rgb(23 22 9 / 1.0);
1547        --color-primary-rgb: 23 22 9;
1548        --color-primary-hover: rgb(23 22 9 / 1.0);
1549        --color-primary-hover-rgb: 23 22 9;
1550        --color-border: rgb(0 0 0 / 0.06);
1551        --color-border-rgb: 0 0 0;
1552        --color-shadow: rgb(0 0 0 / 1.0);
1553        --color-shadow-rgb: 0 0 0;
1554        --color-primary-button-text: rgb(255 255 255 / 1.0);
1555        --color-primary-button-background: rgb(0 0 0 / 1.0);
1556        --color-primary-button-border: rgb(0 0 0 / 1.0);
1557        --color-primary-button-hover-text: rgb(255 255 255 / 1.0);
1558        --color-primary-button-hover-background: rgb(51 51 51 / 1.0);
1559        --color-primary-button-hover-border: rgb(0 0 0 / 1.0);
1560        --color-secondary-button-text: rgb(0 0 0 / 1.0);
1561        --color-secondary-button-background: rgb(0 0 0 / 0.0);
1562        --color-secondary-button-border: rgb(0 0 0 / 1.0);
1563        --color-secondary-button-hover-text: rgb(51 51 51 / 1.0);
1564        --color-secondary-button-hover-background: rgb(250 250 250 / 1.0);
1565        --color-secondary-button-hover-border: rgb(51 51 51 / 1.0);
1566        --color-input-background: rgb(255 255 255 / 0.78);
1567        --color-input-text: rgb(51 51 51 / 1.0);
1568        --color-input-text-rgb: 51 51 51;
1569        --color-input-border: rgb(223 223 223 / 1.0);
1570        --color-input-hover-background: rgb(0 0 0 / 0.01);
1571        --color-variant-background: rgb(255 255 255 / 1.0);
1572        --color-variant-border: rgb(0 0 0 / 0.13);
1573        --color-variant-text: rgb(0 0 0 / 1.0);
1574        --color-variant-text-rgb: 0 0 0;
1575        --color-variant-hover-background: rgb(245 245 245 / 1.0);
1576        --color-variant-hover-text: rgb(0 0 0 / 1.0);
1577        --color-variant-hover-border: rgb(230 230 230 / 1.0);
1578        --color-selected-variant-background: rgb(0 0 0 / 1.0);
1579        --color-selected-variant-border: rgb(0 0 0 / 1.0);
1580        --color-selected-variant-text: rgb(255 255 255 / 1.0);
1581        --color-selected-variant-hover-background: rgb(26 26 26 / 1.0);
1582        --color-selected-variant-hover-text: rgb(255 255 255 / 1.0);
1583        --color-selected-variant-hover-border: rgb(26 26 26 / 1.0);
1584
1585        --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10));
1586        --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15));
1587        --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50));
1588        --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60));
1589        --font-h1--color: var(--color-foreground-heading);
1590        --font-h2--color: var(--color-foreground-heading);
1591        --font-h3--color: var(--color-foreground-heading);
1592        --font-h4--color: var(--color-foreground-heading);
1593        --font-h5--color: var(--color-foreground-heading);
1594        --font-h6--color: var(--color-foreground-heading);
1595
1596        /* Shadows */
1597        
1598          --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1599        
1600        
1601          --shadow-blur: 20px;
1602          --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15));
1603        
1604      }
1605  
1606
1607  body, .color-scheme-1, .color-scheme-2, .color-scheme-3, .color-scheme-4, .color-scheme-5, .color-scheme-6, .color-scheme-58084d4c-a86e-4d0a-855e-a0966e5043f7, .color-scheme-515910f4-a3e9-48d3-8079-ac481ef96b10, .color-scheme-d70ac8c4-eb3e-43d2-9c84-148cdbac2972 {
1608    color: var(--color-foreground);
1609    background-color: var(--color-background);
1610  }
1611</style>
1612<link rel="preload" as="font" href="//www.bostonproper.com/cdn/shop/t/1521/assets/MessinaSans-Regular.woff2?v=143903206038847021881790713714" type="font/woff2" crossorigin>
1613<link rel="preload" as="font" href="//www.bostonproper.com/cdn/shop/t/1521/assets/MessinaSans-Light.woff2?v=52620737138227856671790713714" type="font/woff2" crossorigin>
1614<link rel="preload" as="font" href="//www.bostonproper.com/cdn/shop/t/1521/assets/Signifier-Light.woff2?v=141591112723842981461790713714" type="font/woff2" crossorigin>
1615
1616<style data-shopify>
1617  /* Hide the browser's native clear "×" on type="search" inputs. BP renders
1618     its own custom clear icon (search drawer + /search page), so the native
1619     one showed as a duplicate ×-on-× when the field had focus/hover. */
1620  input[type="search"]::-webkit-search-cancel-button,
1621  input[type="search"]::-webkit-search-decoration {
1622    -webkit-appearance: none;
1623    appearance: none;
1624    display: none;
1625  }
1626
1627  /* Third-party tracking pixels (Dstillery, etc.) get injected as 1×1
1628     <img> elements appended to <body>. base.css's global
1629     `img { width: 100%; height: auto }` overrides their width/height
1630     attributes and stretches each one into a full-viewport-width square,
1631     dumping a huge blank block below the footer. Pin tracking pixels back
1632     to their intrinsic size and pull them out of flow — the beacon still
1633     fires (display/position don't block the request).
1634
1635     EXCLUSIONS:
1636       :not([class*="stylitics"]) — the Stylitics "How to Wear It"
1637         widget renders each tile as <img width="1" height="1"
1638         class="stylitics-ui-image …"> as a lazy-load placeholder and
1639         then resizes via the `--max-size` CSS variable. Without this
1640         exclusion the tiles stay pinned at 1×1.
1641       :not([data-testid]) — widget code typically carries a testid;
1642         tracking pixels don't. Defence-in-depth for other vendors
1643         that follow Stylitics's pattern.
1644       :not([loading]) — same. Lazy-loaded content images carry
1645         loading="lazy" / "eager"; tracking beacons don't. */
1646  img[width="1"][height="1"]:not([class*="stylitics"]):not([data-testid]):not([loading]),
1647  img[width="0"][height="0"]:not([class*="stylitics"]):not([data-testid]):not([loading]) {
1648    width: 1px !important;
1649    height: 1px !important;
1650    position: absolute !important;
1651    pointer-events: none;
1652  }
1653
1654  @font-face {
1655    font-family: 'Messina Sans VF';
1656    src: url('//www.bostonproper.com/cdn/shop/t/1521/assets/MessinaSans-Light.woff2?v=52620737138227856671790713714') format('woff2');
1657    font-weight: 300;
1658    font-style: normal;
1659    font-display: swap;
1660  }
1661  @font-face {
1662    font-family: 'Messina Sans VF';
1663    src: url('//www.bostonproper.com/cdn/shop/t/1521/assets/MessinaSans-Regular.woff2?v=143903206038847021881790713714') format('woff2');
1664    font-weight: 400;
1665    font-style: normal;
1666    font-display: swap;
1667  }
1668  @font-face {
1669    font-family: 'Messina Sans VF';
1670    src: url('//www.bostonproper.com/cdn/shop/t/1521/assets/MessinaSans-SemiBold.woff2?v=136830414853171670151790713714') format('woff2');
1671    font-weight: 500 600;
1672    font-style: normal;
1673    font-display: swap;
1674  }
1675  @font-face {
1676    font-family: 'Messina Sans VF';
1677    src: url('//www.bostonproper.com/cdn/shop/t/1521/assets/MessinaSans-Bold.woff2?v=151736514687132566241790713714') format('woff2');
1678    font-weight: 700;
1679    font-style: normal;
1680    font-display: swap;
1681  }
1682
1683  @font-face {
1684    font-family: 'Signifier';
1685    src: url('//www.bostonproper.com/cdn/shop/t/1521/assets/Signifier-Light.woff2?v=141591112723842981461790713714') format('woff2');
1686    font-weight: 300;
1687    font-style: normal;
1688    font-display: swap;
1689  }
1690  @font-face {
1691    font-family: 'Signifier';
1692    src: url('//www.bostonproper.com/cdn/shop/t/1521/assets/Signifier-Regular.woff2?v=76067088345373958441790713714') format('woff2');
1693    font-weight: 400;
1694    font-style: normal;
1695    font-display: swap;
1696  }
1697
1698  /* ============================================================
1699     Boston Proper design tokens.
1700
1701     Single source of truth for spacing, colors, and font families
1702     used by BP custom sections (bp-hero-slider, bp-shop-by-category,
1703     bp-product-carousel, ...). New sections SHOULD read from these
1704     tokens instead of hardcoding pixel values or hex colors. See
1705     CLAUDE.md for usage conventions.
1706     ============================================================ */
1707  :root {
1708    /* Typography — Messina Sans VF is the site-wide default body
1709       family; Signifier is opt-in for display/heading copy. The five
1710       Horizon font-family vars are overridden here so every section
1711       inherits Messina Sans without per-section rules. */
1712    --font-body--family: 'Messina Sans VF', system-ui, -apple-system, 'Segoe UI', sans-serif;
1713    --font-paragraph--family: 'Messina Sans VF', system-ui, -apple-system, 'Segoe UI', sans-serif;
1714    --font-subheading--family: 'Messina Sans VF', system-ui, -apple-system, 'Segoe UI', sans-serif;
1715    --font-heading--family: 'Messina Sans VF', system-ui, -apple-system, 'Segoe UI', sans-serif;
1716    --font-accent--family: 'Messina Sans VF', system-ui, -apple-system, 'Segoe UI', sans-serif;
1717
1718    --bp-font-body: 'Messina Sans VF', system-ui, -apple-system, 'Segoe UI', sans-serif;
1719    --bp-font-display: 'Signifier', 'Times New Roman', serif;
1720
1721    /* Spacing — values below are the MOBILE defaults; the desktop
1722       overrides live in the @media block at the bottom of :root. Section
1723       gutter is the horizontal distance from viewport edge to content;
1724       section gap is the gap between heading/nav rows or between cards
1725       in a track; card gap is the gap between elements inside a single
1726       card. */
1727    --bp-section-pad-x: 16px;
1728    --bp-section-pad-y: 32px;
1729    --bp-section-gap:   16px;
1730    --bp-card-gap:      12px;
1731
1732    /* Colors */
1733    --bp-color-text:       #171609;
1734    --bp-color-bg-cream:   #F7F6EA;
1735    --bp-color-bg-page:    #FEFFFA;
1736    --bp-color-promo:      #B5341B;
1737    /* #CA3D3D was only 4.55:1 on cream (razor-thin pass). Nudged to
1738       #C23636 (~5.0:1 on cream) for AA margin — imperceptibly darker red. */
1739    --bp-color-sales-red:  #C23636;
1740    --bp-color-cta-text:   #FDFFFA;
1741    /* Sand CTA palette (Figma). Filled sand button + its inverse. Paired
1742       so `--sand` and `--sand-invert` just swap fg/bg. */
1743    --bp-color-cta-sand:      #E8DFD0;
1744    --bp-color-cta-sand-text: #2B241A;
1745    /* Body-copy grey darkened from #74736B (4.39:1 on cream / 4.14:1 on
1746       neutral — failed WCAG AA 4.5:1) to #666559, which clears 4.5:1 on
1747       white, cream and neutral. Disabled/OOS greys stay #74736B (exempt). */
1748    --bp-color-body-copy:  #666559;
1749    /* Muted/secondary ink for eyebrows, sub-labels, counts. Replaces the
1750       scattered rgba(23,22,9,0.45–0.55) usages that failed WCAG AA 4.5:1
1751       (~3.0–4.05:1). 0.65 ≈ 4.9:1 on white/cream. */
1752    --bp-color-text-muted: rgba(23, 22, 9, 0.65);
1753    --bp-color-neutral:    #F0EFEA;
1754
1755    /* Type scale — single source for the sizes already used across the
1756       BP sections. Mobile values live here; desktop overrides are in the
1757       @media block below. Consumed by the .bp-fs-* utility classes and
1758       by the shared blocks (_bp-heading, _bp-body). */
1759    --bp-fs-h1: 36px;  /* hero / page lead (mobile of clamp(36,6vw,50)) */
1760    --bp-fs-h2: 32px;  /* section title (matches bp-fc/bp-itb/bp-grid mobile) */
1761    --bp-fs-h3: 28px;
1762    --bp-fs-h4: 24px;
1763    --bp-fs-h5: 20px;
1764    --bp-fs-h6: 16px;
1765
1766    --bp-fs-body-lg: 17px; /* eyebrows + lead descriptions */
1767    --bp-fs-body-md: 14px; /* default body copy */
1768    --bp-fs-body-sm: 13px; /* fine print / meta */
1769    --bp-fs-body-xs: 12px; /* micro labels */
1770  }
1771
1772  /* Desktop spacing + type-scale overrides — single point of truth for
1773     the breakpoint where the BP layout shifts from mobile-compact to
1774     desktop-roomy. */
1775  @media screen and (min-width: 1024px) {
1776    :root {
1777      --bp-section-pad-x: 40px;
1778      --bp-section-pad-y: 40px;
1779      --bp-section-gap:   20px;
1780
1781      --bp-fs-h1: 50px;  /* hero */
1782      --bp-fs-h2: 40px;  /* section title (bp-fc h1 variant / bp-itb desktop) */
1783      --bp-fs-h3: 32px;  /* sub-section */
1784      --bp-fs-h4: 24px;
1785      --bp-fs-h5: 20px;
1786      --bp-fs-h6: 18px;
1787    }
1788  }
1789
1790  /* Type-scale utility classes — apply just the size + tracking +
1791     leading. Family/colour come from the wrapping element so the same
1792     scale step works for display (Signifier) and body (Messina) copy. */
1793  .bp-fs-h1 { font-size: var(--bp-fs-h1); letter-spacing: -0.02em; line-height: 110%; }
1794  .bp-fs-h2 { font-size: var(--bp-fs-h2); letter-spacing: -0.02em; line-height: 115%; }
1795  .bp-fs-h3 { font-size: var(--bp-fs-h3); letter-spacing: -0.02em; line-height: 120%; }
1796  .bp-fs-h4 { font-size: var(--bp-fs-h4); letter-spacing: -0.01em; line-height: 125%; }
1797  .bp-fs-h5 { font-size: var(--bp-fs-h5); line-height: 130%; }
1798  .bp-fs-h6 { font-size: var(--bp-fs-h6); line-height: 135%; }
1799
1800  .bp-fs-body-lg { font-size: var(--bp-fs-body-lg); line-height: 150%; }
1801  .bp-fs-body-md { font-size: var(--bp-fs-body-md); line-height: 145%; }
1802  .bp-fs-body-sm { font-size: var(--bp-fs-body-sm); line-height: 145%; }
1803  .bp-fs-body-xs { font-size: var(--bp-fs-body-xs); line-height: 145%; }
1804
1805  /* Topnav alignment: pin the header rows and announcement bar to the
1806     same 40px gutter as the BP custom sections.
1807
1808     Horizon's section system uses a 3-column grid:
1809       minmax(--page-margin, 1fr)
1810       --full-page-grid-central-column-width  (clamped to --page-content-width = 1440px)
1811       minmax(--page-margin, 1fr)
1812     On viewports wider than ~1520px the side tracks grow above
1813     --page-margin to center the 1440px content column. So overriding
1814     --page-margin alone keeps the side tracks at 40px MIN but they
1815     still expand on wide screens. We also override the central column
1816     to "100% - 80px" so the 1fr side tracks collapse to exactly the
1817     40px minimum on every viewport, regardless of width. */
1818  .header__row,
1819  .announcement-bar {
1820    --page-margin: var(--bp-section-pad-x);
1821    --full-page-grid-central-column-width: calc(100% - var(--bp-section-pad-x) * 2);
1822  }
1823
1824  /* Mobile header — keep the right-side icons (search / wishlist /
1825     bag) inside the viewport on narrow widths (≤749px). The BP
1826     logo is an inline SVG (bp-logo.svg) rendered with a fixed
1827     --header-logo-image-width-mobile: 198px via inline style on
1828     the wrapper span. Combined with 4 × ~44px bookend cells that
1829     hold the hamburger / search / wishlist / bag, the total width
1830     hits 374px which is iPhone X (375px) viewport width — leaving
1831     no room for the bag icon. Cap the SVG container width with
1832     clamp() so the logo scales down on narrow viewports while
1833     staying close to 198px once there's enough room for it. */
1834  @media screen and (max-width: 749px) {
1835    .header__row .header-logo {
1836      min-width: 0;
1837      max-width: 100%;
1838      overflow: hidden;
1839    }
1840    .header__row .header-logo__image,
1841    .header__row .header-logo__image--svg {
1842      width: clamp(140px, 42vw, 198px);
1843      height: auto;
1844      max-width: 100%;
1845    }
1846    .header__row .header-logo__image--svg svg {
1847      width: 100%;
1848      height: auto;
1849      max-width: 100%;
1850      display: block;
1851    }
1852
1853    /* The scroll-logo variant (small icon-only mark, "Header
1854       scroll-logo swap") must NOT be clamped up to wordmark width.
1855       It shares the .header-logo__image / .header-logo__image--svg
1856       classes with the original/inverse wordmark above, so the
1857       generic rule clamps it to 140-198px too. 44x44 (to match the
1858       right-side action icon hit area) looked oversized/misaligned
1859       in practice — 30x30 reads closer to the intended mark size
1860       while still being bigger than the original 23x18px inline
1861       value baked into blocks/_header-logo.liquid. object-fit:
1862       contain (images) / SVG's default preserveAspectRatio (inline
1863       fallback mark) keep the artwork itself from distorting. */
1864    .header__row .header-logo__image-container--scroll .header-logo__image,
1865    .header__row .header-logo__image-container--scroll .header-logo__image--svg {
1866      width: 30px;
1867      height: 30px;
1868      max-width: none;
1869    }
1870
1871    .header__row .header-logo__image-container--scroll .header-logo__image--svg svg {
1872      width: 100%;
1873      height: 100%;
1874      max-width: none;
1875    }
1876
1877    /* Nudge to correct residual vertical misalignment of the scroll
1878       mark that flex-centering alone didn't fully resolve (mobile
1879       compact bar only — the original/inverse wordmark is unaffected
1880       since this is scoped to data-bp-nav='compact'). */
1881    #header-component[data-bp-nav='compact'] .header__row .header-logo {
1882      padding-bottom: 6px;
1883    }
1884  }
1885
1886  /* Announcement bar slide alignment.
1887
1888     Horizon ships `.text-block--align-center` (and -left / -right)
1889     that set `--text-align: center` on the slide as a CSS variable,
1890     plus an inline `--text-align: center` from the schema, but no
1891     rule in `.text-block` actually consumes it back into the
1892     text-align property — only `.button` does. So the alignment
1893     class + inline var are inert without this consumer.
1894
1895     Apply text-align: var(--text-align) on the slide + paragraph so
1896     the schema's alignment choice takes effect. Defaults to center,
1897     which matches the design and is what the BP announcement bar
1898     always wants regardless of theme settings. */
1899  .announcement-bar__slide,
1900  .announcement-bar__text {
1901    text-align: var(--text-align, center);
1902  }
1903
1904  /* Announcement bar pause/play control (Atlas parity). Pinned to the
1905     right edge of the bar; inherits the bar's text color. The button is
1906     rendered by sections/header-announcements.liquid and wired to
1907     Horizon's announcement-bar-component pause()/play(). */
1908  .bp-announcement-playpause {
1909    position: absolute;
1910    right: 10px;
1911    top: 50%;
1912    transform: translateY(-50%);
1913    display: inline-flex;
1914    align-items: center;
1915    justify-content: center;
1916    width: 28px;
1917    height: 28px;
1918    padding: 0;
1919    background: transparent;
1920    border: 0;
1921    color: var(--color-foreground, currentColor);
1922    cursor: pointer;
1923    opacity: 0.75;
1924    transition: opacity 0.15s ease;
1925  }
1926  .bp-announcement-playpause:hover { opacity: 1; }
1927  /* Show exactly ONE glyph, reflecting the bar's actual state: the PAUSE bars
1928     while playing (click to pause), the PLAY triangle while paused (click to
1929     play). Driven off the bar's `[paused]` attribute so it stays correct
1930     through Horizon's re-render of the bar (which reset the JS `hidden` toggle,
1931     leaving both — or the wrong — icon showing). `!important` to beat the
1932     cascade rule that was overriding the play SVG's `hidden` (QA 7/27). */
1933  .bp-announcement-playpause .bp-announcement-playpause__pause { display: block !important; }
1934  .bp-announcement-playpause .bp-announcement-playpause__play  { display: none  !important; }
1935  announcement-bar-component[paused] .bp-announcement-playpause__pause { display: none  !important; }
1936  announcement-bar-component[paused] .bp-announcement-playpause__play  { display: block !important; }
1937  /* The play/pause is pinned at the bar's right edge (right:10px), and
1938     Horizon's next carat also lands at the right edge (slideshow-arrows is
1939     `inset:0` with `justify-content:space-between`), so the two overlap —
1940     on desktop AND mobile (QA 7/27, Adrienne). Pull the arrow track's right
1941     edge in past the button so the next carat sits just left of it — Atlas
1942     order: […slides] [next] [play/pause]. Only the next arrow moves (the prev
1943     stays at left via space-between); the centered slide text is a separate
1944     element and is unaffected. */
1945  .announcement-bar slideshow-arrows { right: 40px; }
1946
1947  /* a11y (WCAG 2.1.1): keep the desktop mega-menu submenu open while
1948     keyboard focus is inside it. Horizon only reveals it on
1949     [aria-expanded='true'] + :hover (blocks/_header-menu.liquid:422), so
1950     tabbing into the panel could collapse it if the trigger's blur fires
1951     /deactivate before focus lands. Mirrors the :hover rule for focus. */
1952  .menu-list__submenu:focus-within {
1953    --submenu-content-opacity: 1;
1954    visibility: visible;
1955  }
1956
1957  /* Keyboard-only down caret on top-level mega-menu items (menubar pattern —
1958     Alfred 7/27). Shown when a trigger is focused via the keyboard
1959     (:focus-visible) so keyboard users get a clear "opens a submenu"
1960     affordance; mouse hover/click never shows it. The caret is a CSS triangle
1961     in the link's own colour. bp-mega-hover.js wires the menubar behaviour
1962     (Enter/Space/ArrowDown opens, arrows navigate, Escape/Tab close). */
1963  .menu-list__list-item.bp-menu-item-li > .menu-list__link[aria-haspopup='true'] {
1964    position: relative;
1965  }
1966  .menu-list__list-item.bp-menu-item-li > .menu-list__link[aria-haspopup='true']:focus-visible::after {
1967    content: "";
1968    position: absolute;
1969    left: 50%;
1970    /* Centered just BELOW the label rather than inline after it — the inline
1971       caret overlapped the (fixed-min-width, centered) nav text (QA 7/27). */
1972    top: calc(50% + 0.85em);
1973    transform: translate(-50%, -50%);
1974    width: 0;
1975    height: 0;
1976    border-inline: 4px solid transparent;
1977    border-top: 5px solid currentColor;
1978    pointer-events: none;
1979  }
1980
1981  /* Off-white page background (#FEFFFA, Figma spec) applied GLOBALLY —
1982     every template, not just index/collection (PDPs etc. were falling
1983     back to Horizon's default white). Sections that paint their own bg
1984     (cream bands, color schemes) still win over the body. The nav header
1985     rows are overridden to match. The announcement bar is intentionally
1986     NOT included — it's driven by its own merchant color scheme
1987     (header-announcements.liquid), and forcing off-white would erase a
1988     colored/dark promo bar. */
1989  body {
1990    background-color: var(--bp-color-bg-page);
1991  }
1992  .header,
1993  .header__row,
1994  .header-wrapper {
1995    background-color: var(--bp-color-bg-page);
1996  }
1997
1998  /* QA 7/16 — the Figma page color is off-white #FEFFFA, not pure white.
1999     Horizon's DEFAULT color scheme (scheme-1) paints #ffffff, and that's
2000     what the PDP main sections, the header, and the mega-menu read through
2001     --color-background — so those surfaces stayed white despite the body
2002     override above. Remap just the white scheme to the BP page-bg token so
2003     every scheme-1 surface (all pages that use the default scheme) goes
2004     off-white. bp-fonts renders AFTER color-schemes in theme.liquid, so this
2005     wins on equal specificity without !important. The other schemes
2006     (grey #f5f5f5, cream #eef1ea, blue, dark) are intentional — left alone. */
2007  .color-scheme-1 {
2008    --color-background: var(--bp-color-bg-page);
2009    --color-background-rgb: 254, 255, 250;
2010  }
2011
2012  /* ============================================================
2013     BP Product Drawer — re-skin Horizon's quick-add modal as a
2014     right-side slide-in drawer.
2015
2016     MOVED to assets/bp-fonts-deferred.css (loaded non-render-
2017     blocking from theme.liquid). The drawer is a native <dialog
2018     class="quick-add-modal"> that is UA display:none until a card
2019     click opens it — an interaction-revealed surface — so its
2020     open/appearance rules don't need to block first paint. Horizon's
2021     own base .quick-add-modal styles stay render-blocking and keep
2022     the dialog functional. See CLAUDE.md "Topnav 40px gutter" note
2023     for the specificity-bumping pattern the moved rules use.
2024     ============================================================ */
2025
2026  /* ============================================================
2027     BP product card — shared by bp-product-carousel and bp-collection
2028     (PLP). Lives here (not in either section) because both surfaces
2029     need the styles, and CSS in a section stylesheet block only loads
2030     when that section is rendered.
2031     ============================================================ */
2032  .bp-card-host { display: contents; }
2033
2034  .bp-card {
2035    position: relative;
2036    display: flex;
2037    flex-direction: column;
2038    gap: var(--bp-card-gap);
2039    color: var(--bp-color-text);
2040  }
2041
2042  .bp-card__media {
2043    position: relative;
2044    display: block;
2045    aspect-ratio: 3 / 4;
2046    overflow: hidden;
2047    background: var(--bp-color-bg-cream);
2048    color: inherit;
2049  }
2050  .bp-card__media-link {
2051    position: absolute;
2052    inset: 0;
2053    display: block;
2054    text-decoration: none;
2055    color: inherit;
2056  }
2057  .bp-card__quick-add {
2058    position: absolute;
2059    width: 1px;
2060    height: 1px;
2061    overflow: hidden;
2062    clip: rect(0 0 0 0);
2063    pointer-events: none;
2064  }
2065  .bp-card__image {
2066    position: absolute;
2067    inset: 0;
2068    width: 100%;
2069    height: 100%;
2070    object-fit: cover;
2071    display: block;
2072    transition: opacity 0.4s ease;
2073  }
2074  .bp-card__image--secondary { opacity: 0; }
2075  /* Hover-swap default: when the merchant turns secondary-hover off
2076     via the §9.4 setting, the secondary image stays hidden.
2077     The primary only fades out when a secondary image is actually
2078     present (`:has(.bp-card__image--secondary)`). Single-image
2079     products (many Collective / Hanky Panky items) render no secondary
2080     element, so without this guard the primary faded to opacity 0 on
2081     hover and the card went BLANK — hover must keep showing the first
2082     image when there's nothing to swap to (QA 7/31). */
2083  @media (hover: hover) {
2084    .bp-card[data-bp-card-secondary-hover='true'] .bp-card__media:has(.bp-card__image--secondary):hover .bp-card__image--primary { opacity: 0; }
2085    .bp-card[data-bp-card-secondary-hover='true'] .bp-card__media:hover .bp-card__image--secondary { opacity: 1; }
2086  }
2087
2088  .bp-card__badges {
2089    position: absolute;
2090    top: 12px;
2091    left: 12px;
2092    z-index: 2;
2093    display: flex;
2094    flex-direction: column;
2095    align-items: flex-start;
2096    gap: 6px;
2097  }
2098
2099  .bp-card__badge {
2100    background: var(--bp-color-bg-cream);
2101    color: var(--bp-color-text);
2102    padding: 4px 10px;
2103    font-family: var(--bp-font-display);
2104    font-size: 14px;
2105    font-style: normal;
2106    font-weight: 300;
2107    line-height: 120%;
2108    letter-spacing: -0.28px;
2109  }
2110
2111  .bp-card__quick {
2112    position: absolute;
2113    bottom: 12px;
2114    right: 12px;
2115    z-index: 2;
2116    width: 36px;
2117    height: 36px;
2118    border-radius: 0;
2119    border: 1px solid rgba(23, 22, 9, 0.15);
2120    background: var(--bp-color-bg-page);
2121    color: var(--bp-color-text);
2122    display: inline-flex;
2123    align-items: center;
2124    justify-content: center;
2125    cursor: pointer;
2126    opacity: 0;
2127    transform: translateY(4px);
2128    transition: opacity 0.2s ease, transform 0.2s ease, background-color 0.2s ease;
2129  }
2130  .bp-card__quick:hover { background: var(--bp-color-text); color: #fff; }
2131
2132  /* Quick-drawer gallery nav (.bp-qd-gallery-nav) is injected by JS onto
2133     <bp-pdp-gallery>. Its positioning/flip styles live inside a mobile
2134     @media block scoped to .bp-qd__media-slot, so on desktop — or when the
2135     gallery is the main PDP gallery (not in the drawer) — the buttons fall
2136     to the bottom unstyled: two disabled, both-right-pointing arrows. Hide
2137     the nav globally by default; bp-quick-drawer's mobile rules re-show it
2138     inside the drawer media slot. */
2139  .bp-qd-gallery-nav { display: none; }
2140
2141  /* Quick-view button visibility — driven by §9.4 setting keys.
2142     "Always" applies on any device (logically: always = always);
2143     "Hover" only fires on hover-capable devices. Mobile show/hide
2144     is keyed on (hover: none) so it doesn't fight the desktop rules
2145     on touch laptops that report (hover: hover). */
2146
2147  /* "Always visible" — opt-out of the hover-reveal animation. */
2148  .bp-card[data-bp-card-qv-vis-d='always'] .bp-card__quick {
2149    opacity: 1;
2150    transform: none;
2151  }
2152
2153  /* Hover-capable devices: hover-to-reveal (default for desktop). */
2154  @media (hover: hover) {
2155    .bp-card[data-bp-card-qv-vis-d='hover'] .bp-card__media:hover .bp-card__quick {
2156      opacity: 1;
2157      transform: translateY(0);
2158    }
2159  }
2160
2161  /* Touch-only: explicit mobile show/hide. */
2162  @media (hover: none) {
2163    .bp-card[data-bp-card-qv-vis-m='shown'] .bp-card__quick {
2164      opacity: 1;
2165      transform: none;
2166    }
2167    .bp-card[data-bp-card-qv-vis-m='hidden'] .bp-card__quick {
2168      display: none;
2169    }
2170  }
2171
2172  /* Whole-product trigger style — make the card surface look clickable
2173     and remove the bag-icon affordance. The bag itself isn't rendered
2174     in this mode (see bp-product-card.liquid), so this just signals
2175     interactivity. */
2176  .bp-card[data-bp-card-qb-style='whole_product'] {
2177    cursor: pointer;
2178  }
2179
2180  /* Swatch host wrapper — passes through for layout; the click target
2181     is the inner `.swatch` element (Horizon's). */
2182  .bp-card__swatch-host { display: inline-flex; cursor: pointer; }
2183
2184  .bp-card__body {
2185    display: flex;
2186    flex-direction: column;
2187    gap: 6px;
2188  }
2189  .bp-card__collection {
2190    margin: 0;
2191    font-family: var(--bp-font-body);
2192    font-size: 11px;
2193    font-weight: 500;
2194    letter-spacing: 0.08em;
2195    text-transform: uppercase;
2196    color: var(--bp-color-text-muted);
2197    line-height: 1.3;
2198  }
2199  .bp-card__title {
2200    margin: 0;
2201    font-family: var(--bp-font-body);
2202    font-size: 15px;
2203    font-weight: 400;
2204    line-height: 1.3;
2205    letter-spacing: -0.15px;
2206  }
2207  .bp-card__title a {
2208    color: inherit;
2209    text-decoration: none;
2210  }
2211  .bp-card__title a:hover { text-decoration: underline; text-underline-offset: 3px; }
2212
2213  .bp-card__price-row {
2214    display: flex;
2215    flex-wrap: wrap;
2216    align-items: baseline;
2217    gap: 6px 10px;
2218    font-family: var(--bp-font-body);
2219    font-size: 14px;
2220    font-weight: 500;
2221    line-height: 145%;
2222    letter-spacing: -0.14px;
2223  }
2224  .bp-card__price {
2225    color: var(--bp-color-text, #171609);
2226    font-weight: 500;
2227  }
2228  .bp-card__compare {
2229    /* Strikethrough/compare price grey — #74736B, matching the PDP
2230       (bp-pdp-styles .compare-at-price) per QA (Amber). NB: #74736B is the
2231       WCAG-exempt grey (it fails AA 4.5:1); kept consistent with the PDP at
2232       the team's request over the darker --bp-color-body-copy (#666559). */
2233    color: #74736B;
2234    text-decoration: line-through;
2235    font-weight: 500;
2236  }
2237  .bp-card__promo {
2238    color: #CA3D3D;
2239    font-size: 12px;
2240    font-weight: 400;
2241    line-height: 145%;
2242    letter-spacing: -0.12px;
2243    flex-basis: 100%;
2244  }
2245  /* Desktop: try to sit inline with the price; when it doesn't fit,
2246     flex-wrap pushes it to the next line. No margin-left:auto here
2247     — that would right-align the wrapped copy. Plain flex-grow:0
2248     keeps it hugging the price on the same line. */
2249  @media screen and (min-width: 1024px) {
2250    .bp-card__promo {
2251      flex-basis: auto;
2252      margin-left: 0;
2253      text-align: left;
2254    }
2255  }
2256
2257  .bp-card__swatches {
2258    display: flex;
2259    align-items: center;
2260    gap: 10px;
2261    margin: 8px 0 0;
2262    padding: 4px;
2263    list-style: none;
2264  }
2265  .bp-card__swatch-item {
2266    display: inline-flex;
2267    align-items: center;
2268    position: relative;
2269  }
2270  /* Sale-discount badge on a swatch — Body/Semi/Tiny spec:
2271     Messina 10 / 660 / 145% / -0.1px, Sales-Red on white with a
2272     red border. Anchors top-right of the swatch dot. */
2273  .bp-card__swatch-discount {
2274    position: absolute;
2275    top: -6px;
2276    right: -8px;
2277    display: inline-flex;
2278    flex-direction: column;
2279    justify-content: center;
2280    align-items: center;
2281    padding: 0 2px;
2282    border: 1px solid #CA3D3D;
2283    background: #FDFFFA;
2284    color: #CA3D3D;
2285    text-align: center;
2286    font-family: var(--bp-font-body);
2287    font-size: 10px;
2288    font-weight: 700;
2289    line-height: 145%;
2290    letter-spacing: -0.1px;
2291    pointer-events: none;
2292    white-space: nowrap;
2293  }
2294  /* BP a11y: interactive swatches are a <button> wrapping a decorative
2295     <img>. The button is a transparent wrapper (focus ring only) — the
2296     visual ring stays on .bp-card__swatch-img so the many bare-<span>
2297     swatch renderers (Bloomreach cards/carousel, search, you'll-also-love)
2298     keep it without needing the button. */
2299  .bp-card__swatch {
2300    appearance: none;
2301    -webkit-appearance: none;
2302    padding: 0;
2303    border: 0;
2304    background: transparent;
2305    border-radius: 50%;
2306    cursor: pointer;
2307    display: block;
2308    line-height: 0;
2309    flex-shrink: 0;
2310  }
2311  .bp-card__swatch:focus-visible {
2312    outline: 2px solid var(--bp-color-text);
2313    outline-offset: 4px;
2314  }
2315  .bp-card__swatch-img {
2316    width: 24px;
2317    height: 24px;
2318    border-radius: 50%;
2319    object-fit: cover;
2320    display: block;
2321    flex-shrink: 0;
2322    /* 2px white gap + 1px cream ring — layered box-shadow keeps
2323       the element size stable while painting the ring outside the image. */
2324    box-shadow: 0 0 0 2px #fff, 0 0 0 3px #E1E0D4;
2325  }
2326  /* Design-preview mock dot — solid background color, no image,
2327     same 23px footprint as the real swatch. */
2328  .bp-card__swatch-img--mock {
2329    background-clip: content-box;
2330    background-size: cover;
2331    border-color: rgba(23, 22, 9, 0.15);
2332  }
2333  /* Active ring targets the visible dot whether the active class sits on
2334     the button (bp-product-card / bp-card-hydrate) or directly on the img
2335     (bare-span renderers). */
2336  .bp-card__swatch--active .bp-card__swatch-img,
2337  .bp-card__swatch-img.bp-card__swatch--active {
2338    box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--bp-color-text);
2339  }
2340  .bp-card__swatch-more {
2341    font-family: var(--bp-font-body);
2342    font-size: 12px;
2343    color: rgba(23, 22, 9, 0.65);
2344    margin-left: 2px;
2345  }
2346  /* +N is now a PDP link — keep it visually identical to the old text
2347     (inherit colour, no underline) but tappable, with a hover cue. */
2348  .bp-card__swatch-more-link {
2349    color: inherit;
2350    text-decoration: none;
2351  }
2352  .bp-card__swatch-more-link:hover { text-decoration: underline; text-underline-offset: 2px; }
2353
2354  /* ============================================================
2355     BP Shop-the-Look drawer — global styles.
2356
2357     MOVED to assets/bp-fonts-deferred.css (loaded non-render-
2358     blocking from theme.liquid). `.bp-stl-drawer` is a native
2359     <dialog> (UA display:none until .showModal() opens it from a
2360     "Shop the look" trigger) — an interaction-revealed surface with
2361     no closed-state hide rule of its own — so its appearance rules
2362     don't need to block first paint. Markup: snippets/
2363     bp-stl-drawer.liquid; behavior: assets/bp-stl-drawer.js.
2364     ============================================================ */
2365
2366  /* ============================================================
2367     BP Footer utilities bar — override Horizon's footer-utilities
2368     so the bottom copyright / policy bar inherits the cream
2369     background that bp-footer uses, and the link color stays on-brand.
2370     ============================================================ */
2371  .footer-utilities {
2372    background-color: var(--bp-color-bg-cream);
2373    color: var(--bp-color-text);
2374  }
2375  .footer-utilities a {
2376    color: var(--bp-color-text);
2377  }
2378
2379  /* ============================================================
2380     BP Mega Menu (desktop) — markup lives in blocks/_bp-menu-item.liquid.
2381     Horizon already handles submenu positioning, hover open/close,
2382     and the <header-menu> layout. We only add: vertical centering of
2383     the menu row + the .bp-mega* content styles for the dropdown.
2384     ============================================================ */
2385
2386  /* Vertically center menu items in the header row */
2387  header-menu .menu-list,
2388  .menu-list {
2389    align-items: center;
2390  }
2391
2392  /* Top-level nav links — smooth hover transitions.
2393     Uses Messina Sans VF (variable font) so font-weight can transition
2394     smoothly via font-variation-settings rather than snapping. Plus a
2395     gentle underline that grows from the center under each label. */
2396  .menu-list__list-item .menu-list__link {
2397    position: relative;
2398    transition: opacity 0.2s ease, font-variation-settings 0.25s ease;
2399    font-variation-settings: 'wght' 400;
2400  }
2401  .menu-list__list-item .menu-list__link::after {
2402    content: '';
2403    position: absolute;
2404    left: 50%;
2405    bottom: 0;
2406    width: 0;
2407    height: 1px;
2408    background: currentColor;
2409    transform: translateX(-50%);
2410    transition: width 0.25s ease;
2411    pointer-events: none;
2412  }
2413  .menu-list__list-item:hover .menu-list__link,
2414  .menu-list__list-item:focus-within .menu-list__link,
2415  .menu-list__list-item.bp-menu-open .menu-list__link,
2416  .menu-list__list-item .menu-list__link[aria-expanded='true'],
2417  .menu-list__list-item .menu-list__link.menu-list__link--active {
2418    font-weight: 700;
2419    font-variation-settings: 'wght' 700;
2420  }
2421  .menu-list__list-item:hover .menu-list__link::after,
2422  .menu-list__list-item:focus-within .menu-list__link::after,
2423  .menu-list__list-item.bp-menu-open .menu-list__link::after {
2424    width: 100%;
2425  }
2426  /* Sibling fade — when one nav item is hovered/open, gently dim the others */
2427  .menu-list:hover .menu-list__list-item .menu-list__link,
2428  .menu-list:has(.bp-menu-open) .menu-list__list-item .menu-list__link {
2429    opacity: 0.55;
2430  }
2431  .menu-list:hover .menu-list__list-item:hover .menu-list__link,
2432  .menu-list .menu-list__list-item.bp-menu-open .menu-list__link,
2433  .menu-list .menu-list__list-item:focus-within .menu-list__link {
2434    opacity: 1;
2435  }
2436
2437  /* BP mega submenu — own classes (.bp-mega-submenu, not Horizon's
2438     .menu-list__submenu) so Horizon's submenu CSS doesn't apply. Open/
2439     close is driven by .bp-menu-open on the LI, set by our JS hover
2440     handler (assets/bp-mega-hover.js) with a debounced close. */
2441  .bp-mega-submenu {
2442    position: fixed;
2443    left: 0;
2444    right: 0;
2445    top: var(--header-height, 60px);
2446    width: 100vw;
2447    max-width: 100vw;
2448    z-index: 90;
2449    /* Off-white to match the header (QA 7/16) — falls back to the BP page
2450       bg token, not #fff, if --color-background is ever unset. */
2451    background: var(--color-background, var(--bp-color-bg-page));
2452    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06);
2453    opacity: 0;
2454    pointer-events: none;
2455    transition: opacity 0.15s ease;
2456  }
2457  .menu-list__list-item.bp-menu-open > .bp-mega-submenu {
2458    opacity: 1;
2459    pointer-events: auto;
2460  }
2461  .bp-mega-submenu__inner {
2462    width: 100%;
2463    /* CLAUDE.md spacing tokens — match the rest of the BP sections.
2464       Top is 20px (a touch tight against the nav row); sides + bottom
2465       use the standard --bp-section-pad-x / -y so the content's left
2466       edge aligns with the logo (which sits at --bp-section-pad-x via
2467       the topnav --page-margin override in this same file). No
2468       max-width / centering — full-bleed minus gutters. */
2469    padding: 20px var(--bp-section-pad-x) var(--bp-section-pad-y);
2470    box-sizing: border-box;
2471  }
2472
2473  /* Layout: columns + (optional) right-side promos. Uses BP spacing
2474     tokens (CLAUDE.md): --bp-section-gap = 20px desktop. */
2475  .bp-mega {
2476    display: flex;
2477    align-items: flex-start;
2478    gap: var(--bp-section-gap);
2479    align-self: stretch;
2480    width: 100%;
2481    white-space: normal;
2482    word-wrap: break-word;
2483    overflow-wrap: break-word;
2484    font-family: var(--font-body--family);
2485    font-size: var(--font-size--sm);
2486    line-height: 1.4;
2487    color: var(--color-foreground);
2488  }
2489  .bp-mega *, .bp-mega *::before, .bp-mega *::after { white-space: normal; }
2490
2491  /* Columns side-by-side, equal width, BP spacing */
2492  .bp-mega__columns {
2493    flex: 1 1 auto;
2494    display: flex;
2495    gap: var(--bp-section-gap);
2496  }
2497  .bp-mega__column {
2498    flex: 1 1 0;
2499    min-width: 0;
2500  }
2501
2502  .bp-mega__column {
2503    display: flex;
2504    flex-direction: column;
2505    gap: var(--gap-sm);
2506    min-width: 0;
2507  }
2508  /* Column / tab heading — Body/Semi/Small (Messina Sans VF, 14px, 660). */
2509  .bp-mega__heading {
2510    margin: 0 0 var(--bp-card-gap);
2511    color: var(--bp-color-text);
2512    font-family: var(--bp-font-body);
2513    font-size: 14px;
2514    font-style: normal;
2515    font-weight: 700;
2516    line-height: 145%;
2517    letter-spacing: -0.14px;
2518  }
2519  .bp-mega__heading a { color: inherit; text-decoration: none; }
2520
2521  .bp-mega__links {
2522    list-style: none;
2523    margin: 0;
2524    padding: 0;
2525    display: flex;
2526    flex-direction: column;
2527    gap: 6px;
2528  }
2529  .bp-mega__links a {
2530    font-family: var(--font-body--family);
2531    font-size: var(--font-size--sm);
2532    color: var(--color-foreground);
2533    text-decoration: none;
2534    line-height: 1.4;
2535  }
2536  .bp-mega__links a:hover { text-decoration: underline; }
2537
2538  .bp-mega__promos {
2539    flex: 0 0 auto;
2540    /* Pin to the right edge of the dropdown (just inside the
2541       --bp-section-pad-x gutter). margin-inline-start:auto pushes us
2542       past the columns regardless of how much space they take. */
2543    margin-inline-start: auto;
2544    display: grid;
2545    /* Default = two fixed-width columns. The :has(:only-child) rule
2546       below swaps to a single wider column when only one promo
2547       renders. Was repeat(auto-fit, 220px), but auto-fit would
2548       collapse to a single column on dropdowns where the menu
2549       columns squeezed this container narrow — making the second
2550       promo wrap below the first instead of sitting beside it. */
2551    grid-template-columns: repeat(2, 220px);
2552    gap: var(--bp-section-gap);
2553    justify-content: end;
2554  }
2555  .bp-mega__promo { min-width: 0; max-width: 100%; }
2556  .bp-mega__promo-link {
2557    display: flex;
2558    flex-direction: column;
2559    gap: var(--gap-xs);
2560    text-decoration: none;
2561    color: var(--color-foreground);
2562    width: 100%;
2563  }
2564  .bp-mega__promo-image {
2565    position: relative;
2566    width: 100%;
2567    aspect-ratio: 4 / 5;
2568    background: var(--color-foreground-muted, #ddd);
2569    overflow: hidden;
2570  }
2571  .bp-mega__promo-image svg,
2572  .bp-mega__promo-image img,
2573  .bp-mega__promo-video {
2574    position: absolute;
2575    inset: 0;
2576    width: 100%;
2577    height: 100%;
2578    object-fit: cover;
2579    display: block;
2580  }
2581
2582  /* Promo typography — Messina Sans VF semi (660) for the title;
2583     500 for the body copy. Colors: Black for title, --bp-color-body-copy
2584     (#74736B) for the supporting paragraph. */
2585  .bp-mega__promo-title {
2586    margin: 0;
2587    color: var(--bp-color-text);
2588    font-family: var(--bp-font-body);
2589    font-size: 14px;
2590    font-style: normal;
2591    font-weight: 700;
2592    line-height: 145%;
2593    letter-spacing: -0.14px;
2594  }
2595  .bp-mega__promo-copy {
2596    margin: 0;
2597    color: var(--bp-color-body-copy);
2598    font-family: var(--bp-font-body);
2599    font-size: 12px;
2600    font-style: normal;
2601    font-weight: 500;
2602    line-height: 145%;
2603    letter-spacing: -0.12px;
2604  }
2605  .bp-mega__promo-cta {
2606    margin-top: 4px;
2607    color: var(--bp-color-text);
2608    font-family: var(--bp-font-body);
2609    font-size: 12px;
2610    font-weight: 500;
2611    line-height: 145%;
2612    letter-spacing: -0.12px;
2613    text-decoration: underline;
2614    text-underline-offset: 3px;
2615  }
2616
2617  /* Single-promo variant: when only one promo is rendered inside a
2618     columns_promos dropdown, give it the width of two regular promos
2619     (~460px) and a 3:2 landscape image, capped at 370px tall. Driven
2620     by :only-child so no Liquid changes needed. */
2621  .bp-mega__promos:has(> .bp-mega__promo:only-child) {
2622    grid-template-columns: minmax(0, 460px);
2623  }
2624  .bp-mega__promos > .bp-mega__promo:only-child .bp-mega__promo-image {
2625    aspect-ratio: 3 / 2;
2626    height: 370px;
2627    width: 100%;
2628    align-self: stretch;
2629  }
2630
2631  @media screen and (max-width: 989px) {
2632    .bp-mega--columns-promos { flex-direction: column; }
2633    .bp-mega__promos { grid-template-columns: repeat(2, minmax(0, 1fr)); }
2634  }
2635
2636  /* ----- Layout: image_tiles (Occasions) ----------------------------
2637     Flat row of tiles. Each tile = square image + title + Shop Now.
2638     Tile width is fluid; on tighter widths the row wraps. Designed
2639     to lay out 6 tiles in one row at desktop widths. */
2640  .bp-mega--image-tiles { display: block; }
2641  .bp-mega__tiles {
2642    display: grid;
2643    grid-template-columns: repeat(6, minmax(0, 1fr));
2644    gap: var(--bp-section-gap);
2645    width: 100%;
2646  }
2647  @media screen and (max-width: 1279px) {
2648    .bp-mega__tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
2649  }
2650  @media screen and (max-width: 989px) {
2651    .bp-mega__tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
2652  }
2653  .bp-mega__tile {
2654    display: flex;
2655    flex-direction: column;
2656    gap: var(--bp-card-gap);
2657    color: var(--bp-color-text);
2658    text-decoration: none;
2659  }
2660  .bp-mega__tile-image {
2661    position: relative;
2662    aspect-ratio: 1 / 1;
2663    background: var(--bp-color-bg-cream);
2664    overflow: hidden;
2665  }
2666  /* Image-tiles layout ONLY: 4/5 portrait per the wireframe — the square
2667     (1/1) cropped the imagery (Ernie 7/27). Scoped to the image_tiles
2668     container so other mega layouts are unaffected. The <img> still
2669     object-fit:covers this box. */
2670  .bp-mega--image-tiles .bp-mega__tile-image {
2671    aspect-ratio: 4 / 5;
2672  }
2673  .bp-mega__tile-image img,
2674  .bp-mega__tile-image svg {
2675    position: absolute;
2676    inset: 0;
2677    width: 100%;
2678    height: 100%;
2679    object-fit: cover;
2680    display: block;
2681  }
2682  .bp-mega__tile-title {
2683    margin: 0;
2684    font-family: var(--bp-font-body);
2685    font-size: 15px;
2686    font-weight: 500;
2687    line-height: 1.3;
2688    letter-spacing: -0.15px;
2689    color: var(--bp-color-text);
2690  }
2691  .bp-mega__tile-cta {
2692    font-family: var(--bp-font-body);
2693    font-size: 13px;
2694    line-height: 1.4;
2695    color: var(--bp-color-text);
2696    text-decoration: underline;
2697    text-underline-offset: 3px;
2698  }
2699
2700  /* ----- Layout: tabs_promos (Brands We Love) -----------------------
2701     3-column grid: vertical tab list | active panel | promos.
2702     Tab activation is handled by assets/bp-mega-hover.js (initTabs). */
2703  .bp-mega--tabs-promos { display: block; }
2704  .bp-mega__tabs {
2705    display: grid;
2706    grid-template-columns: minmax(180px, 1fr) minmax(0, 2fr) minmax(0, 2fr);
2707    gap: var(--bp-section-gap);
2708    width: 100%;
2709    align-items: start;
2710  }
2711  .bp-mega__tabs-list {
2712    list-style: none;
2713    margin: 0;
2714    padding: 0;
2715    display: flex;
2716    flex-direction: column;
2717    gap: 4px;
2718  }
2719  .bp-mega__tab {
2720    display: flex;
2721    align-items: center;
2722    justify-content: space-between;
2723    width: 100%;
2724    padding: 14px 16px;
2725    background: transparent;
2726    border: 0;
2727    cursor: pointer;
2728    text-align: left;
2729    color: var(--bp-color-text);
2730    font-family: var(--bp-font-body);
2731    font-size: 14px;
2732    line-height: 1.3;
2733    letter-spacing: -0.14px;
2734    transition: background-color 0.15s ease, font-weight 0.15s ease;
2735  }
2736  .bp-mega__tab:hover {
2737    background: var(--bp-color-neutral);
2738  }
2739  .bp-mega__tab.is-active {
2740    background: var(--bp-color-neutral);
2741    font-weight: 600;
2742  }
2743  .bp-mega__tab-chevron {
2744    display: inline-flex;
2745    align-items: center;
2746    justify-content: center;
2747    flex: 0 0 auto;
2748    margin-left: 12px;
2749    opacity: 0.85;
2750    /* New chevron asset is drawn left-pointing; flip to point right
2751       (toward the tab panel that opens on the right). */
2752    transform: scaleX(-1);
2753  }
2754  .bp-mega__tabs-panels {
2755    min-width: 0;
2756  }
2757  .bp-mega__tab-panel {
2758    display: none;
2759    padding: 4px 0;
2760  }
2761  .bp-mega__tab-panel.is-active {
2762    display: block;
2763  }
2764  /* Tabs layout uses a slightly looser link gap (8px vs 6px elsewhere). */
2765  .bp-mega--tabs-promos .bp-mega__links {
2766    gap: 8px;
2767  }
2768  /* Two-column tab links (merchant toggle: block.settings.tabs_link_columns).
2769     Long lists like Brands We Love overflow one tall column and leave the
2770     right half of the panel empty; splitting into two balanced columns uses
2771     that white space beside the promos. Give the panel track more room (3fr)
2772     so both columns breathe, then flow the <ul> as CSS multi-column — items
2773     fill top-to-bottom of column 1, then column 2, which keeps an
2774     alphabetical brand list reading naturally (A–M | N–Z). */
2775  .bp-mega__tabs[data-bp-tab-columns="2"] {
2776    grid-template-columns: minmax(180px, 1fr) minmax(0, 3fr) minmax(0, 2fr);
2777  }
2778  .bp-mega__tabs[data-bp-tab-columns="2"] .bp-mega__links {
2779    display: block;
2780    columns: 2;
2781    column-gap: var(--bp-section-gap);
2782  }
2783  .bp-mega__tabs[data-bp-tab-columns="2"] .bp-mega__links li {
2784    margin-bottom: 8px;
2785    break-inside: avoid;
2786    -webkit-column-break-inside: avoid;
2787  }
2788  .bp-mega__tabs[data-bp-tab-columns="2"] .bp-mega__links li:last-child {
2789    margin-bottom: 0;
2790  }
2791  .bp-mega__promos--tabs {
2792    /* Match the columns_promos promos (styleEDIT): fixed 220px columns so the
2793       images render full-size. `minmax(0,1fr)` collapsed them to a sliver
2794       because the promos container is content-sized (flex:0 0 auto) — the
2795       fr units had no defined width to divide, so the 4:5 images shrank to
2796       their min. The tabs dropdown has ample room on the right (tabs + brand
2797       list only fill the left half). */
2798    grid-template-columns: repeat(2, 220px);
2799    display: grid;
2800    gap: var(--bp-section-gap);
2801  }
2802
2803  @media screen and (max-width: 989px) {
2804    .bp-mega__tabs,
2805    .bp-mega__tabs[data-bp-tab-columns="2"] { grid-template-columns: 1fr; }
2806    .bp-mega__promos--tabs { grid-template-colu
2806mns: repeat(2, minmax(0, 1fr)); }
2807    /* Not enough width for two link columns once the tabs stack — collapse. */
2808    .bp-mega__tabs[data-bp-tab-columns="2"] .bp-mega__links { columns: 1; }
2809  }
2810
2811  @media screen and (max-width: 749px) {
2812    .bp-mega { display: none; }
2813  }
2814
2815  /* BP Cart Drawer — markup, CSS, and JS live in
2816     snippets/bp-cart-drawer.liquid (rendered from theme.liquid).
2817     Hide Horizon's cart-drawer-component since BP has its own. */
2818  cart-drawer-component { display: none !important; }
2819
2820  /* ===== §9.1 BP Section knobs — base rules ===========================
2821     Consumes CSS variables emitted by snippets/bp-section-knobs.liquid.
2822     Sections opt in by carrying `data-bp-section`, `data-section-id`,
2823     and `data-bp-mode-{d,m}` attributes on the wrapping element.
2824     Mobile is the default; desktop overrides at ≥1024px (§1).
2825     ================================================================= */
2826
2827  [data-bp-section] {
2828    background: var(--bp-knobs-bg-section, transparent);
2829    color: var(--bp-knobs-text, var(--bp-color-text));
2830  }
2831
2832  [data-bp-section][data-bp-mode-m='padded'] {
2833    padding-block: var(--bp-knobs-pad-y-m, var(--bp-section-pad-y));
2834    padding-inline: var(--bp-knobs-pad-x-m, var(--bp-section-pad-x));
2835  }
2836  [data-bp-section][data-bp-mode-m='full'] {
2837    padding-block: var(--bp-knobs-pad-y-m, var(--bp-section-pad-y));
2838    padding-inline: 0;
2839  }
2840
2841  /* Inner block — only renders meaningfully when padded. Holds the
2842     inner background color so a padded section can have a section bg
2843     AND a different inner-block bg (per §9.1). */
2844  [data-bp-section] .bp-section__inner {
2845    background: var(--bp-knobs-bg-inner, transparent);
2846  }
2847
2848  /* Title alignment — opt in via class `bp-section__title` on the
2849     heading. text-align is inheritable, so descendant copy follows. */
2850  [data-bp-section] .bp-section__title {
2851    text-align: var(--bp-knobs-align-m, start);
2852  }
2853
2854  @media screen and (min-width: 1024px) {
2855    [data-bp-section][data-bp-mode-d='padded'] {
2856      padding-block: var(--bp-knobs-pad-y-d, var(--bp-section-pad-y));
2857      padding-inline: var(--bp-knobs-pad-x-d, var(--bp-section-pad-x));
2858    }
2859    [data-bp-section][data-bp-mode-d='full'] {
2860      padding-block: var(--bp-knobs-pad-y-d, var(--bp-section-pad-y));
2861      padding-inline: 0;
2862    }
2863    [data-bp-section] .bp-section__title {
2864      text-align: var(--bp-knobs-align-d, start);
2865    }
2866  }
2867
2868  /* ===== §9.3 BP Media block — base rules ============================
2869     Used by snippets/bp-section-media.liquid. The snippet emits a
2870     [data-bp-media] wrapper with optional `--bp-media-ratio-{d,m}`
2871     custom properties and an optional .bp-media__overlay child.
2872     The overlay's solid vs. gradient + coverage live entirely in CSS
2873     so the merchant gets live-preview without re-rendering markup.
2874
2875     §9.3 rule: images always fill the full width of their slot.
2876     position:relative + absolute children + object-fit cover does
2877     this regardless of the slot's height (which the section sizes).
2878     ================================================================= */
2879
2880  [data-bp-media] {
2881    position: relative;
2882    overflow: hidden;
2883    width: 100%;
2884    /* Mobile-first ratio. Falls through to the desktop ratio when no
2885       mobile-specific value is set. `auto` (the default) leaves the
2886       slot to be sized by its parent (e.g. fixed mobile band height,
2887       desktop grid row stretch). */
2888    aspect-ratio: var(--bp-media-ratio-m, var(--bp-media-ratio-d, auto));
2889  }
2890
2891  [data-bp-media] .bp-media__image,
2892  [data-bp-media] .bp-media__video {
2893    position: absolute;
2894    inset: 0;
2895    width: 100%;
2896    height: 100%;
2897    /* Fit: cover (default, fills + crops) vs contain (whole asset shown,
2898       may letterbox against the slot bg). Set per media block via the
2899       {prefix}_fit knob — e.g. a rotating-logo video that must never be
2900       cropped uses 'contain'. */
2901    object-fit: var(--bp-media-fit, cover);
2902    /* Focal point. Mobile-first; desktop override below.
2903       Merchants pick from a 9-position select on the media block. */
2904    object-position: var(--bp-media-pos-m, var(--bp-media-pos-d, center center));
2905    display: block;
2906  }
2907
2908  [data-bp-media] .bp-media__placeholder {
2909    position: absolute;
2910    inset: 0;
2911    background: linear-gradient(135deg, #e8e6df 0%, #cfccc1 100%);
2912  }
2913
2914  /* Overlay — sits on top of the media, solid or gradient. The
2915     coverage % indicates how much of the height (anchored to the
2916     bottom) carries the colour:
2917       - solid: a hard band from 0 to coverage% (transparent above)
2918       - gradient: fades from full colour at the bottom to transparent
2919                   at coverage% from the bottom
2920     Selectors are unscoped so block-level surfaces (hero slides,
2921     look tiles, category cards) can use the same overlay without
2922     needing the [data-bp-media] block-prefix machinery — drop the
2923     element inside any position:relative parent and it fills it. */
2924  .bp-media__overlay {
2925    position: absolute;
2926    inset: 0;
2927    pointer-events: none;
2928    /* Opacity is responsive: --…-opacity-m (mobile) then the single
2929       --…-opacity, then a default. Desktop override lives in the media
2930       query below. */
2931    opacity: var(--bp-media-overlay-opacity-m, var(--bp-media-overlay-opacity, 0.3));
2932  }
2933  /* Gradient DIRECTION + COVERAGE are driven per breakpoint by
2934     --bp-media-overlay-dir-{m,d} and --bp-media-overlay-coverage-{m,d}
2935     (emitted from the "Overlay position" + "Coverage" controls —
2936     bottom→`to top`, top→`to bottom`, left→`to right`, right→`to left`).
2937     Each falls back to its single-value var, then the bottom-anchored /
2938     full-image default, so sections that set only the shared values (or
2939     nothing) are unchanged. */
2940  .bp-media__overlay--solid {
2941    background: linear-gradient(
2942      var(--bp-media-overlay-dir-m, to top),
2943      var(--bp-media-overlay-color, #000) 0,
2944      var(--bp-media-overlay-color, #000) var(--bp-media-overlay-coverage-m, var(--bp-media-overlay-coverage, 100%)),
2945      transparent var(--bp-media-overlay-coverage-m, var(--bp-media-overlay-coverage, 100%))
2946    );
2947  }
2948  .bp-media__overlay--gradient {
2949    background: linear-gradient(
2950      var(--bp-media-overlay-dir-m, to top),
2951      var(--bp-media-overlay-color, #000) 0,
2952      transparent var(--bp-media-overlay-coverage-m, var(--bp-media-overlay-coverage, 100%))
2953    );
2954  }
2955
2956  @media screen and (min-width: 1024px) {
2957    [data-bp-media] {
2958      aspect-ratio: var(--bp-media-ratio-d, auto);
2959    }
2960    [data-bp-media] .bp-media__image,
2961    [data-bp-media] .bp-media__video {
2962      object-position: var(--bp-media-pos-d, center center);
2963    }
2964    /* Desktop overlay — opacity, direction, and coverage each fall back to
2965       the mobile value, then the single-value var, then the default, so a
2966       desktop-only or single-value setup still works. */
2967    .bp-media__overlay {
2968      opacity: var(--bp-media-overlay-opacity-d, var(--bp-media-overlay-opacity-m, var(--bp-media-overlay-opacity, 0.3)));
2969    }
2970    .bp-media__overlay--solid {
2971      background: linear-gradient(
2972        var(--bp-media-overlay-dir-d, var(--bp-media-overlay-dir-m, to top)),
2973        var(--bp-media-overlay-color, #000) 0,
2974        var(--bp-media-overlay-color, #000) var(--bp-media-overlay-coverage-d, var(--bp-media-overlay-coverage-m, var(--bp-media-overlay-coverage, 100%))),
2975        transparent var(--bp-media-overlay-coverage-d, var(--bp-media-overlay-coverage-m, var(--bp-media-overlay-coverage, 100%)))
2976      );
2977    }
2978    .bp-media__overlay--gradient {
2979      background: linear-gradient(
2980        var(--bp-media-overlay-dir-d, var(--bp-media-overlay-dir-m, to top)),
2981        var(--bp-media-overlay-color, #000) 0,
2982        transparent var(--bp-media-overlay-coverage-d, var(--bp-media-overlay-coverage-m, var(--bp-media-overlay-coverage, 100%)))
2983      );
2984    }
2985  }
2986
2987  /* ===== WCAG 2.2.2 pause/play button (bp-section-media.liquid) ======
2988     Shown whenever a video autoplays without native controls. Positioned
2989     bottom-left inside [data-bp-media]; z-index 2 keeps it above the
2990     overlay (which sits at z-index 1 by stacking order). ============== */
2991  .bp-media__pause-btn {
2992    position: absolute;
2993    bottom: 12px;
2994    left: 12px;
2995    z-index: 2;
2996    display: inline-flex;
2997    align-items: center;
2998    justify-content: center;
2999    width: 40px;
3000    height: 40px;
3001    padding: 0;
3002    border: none;
3003    border-radius: 50%;
3004    background-color: rgba(0, 0, 0, 0.6);
3005    color: #fff;
3006    cursor: pointer;
3007    transition: background-color 0.15s ease;
3008  }
3009  .bp-media__pause-btn:hover,
3010  .bp-media__pause-btn:focus {
3011    background-color: rgba(0, 0, 0, 0.82);
3012  }
3013  .bp-media__pause-btn:focus-visible {
3014    outline: 2px solid #fff;
3015    outline-offset: 2px;
3016  }
3017  .bp-media__pause-btn:focus:not(:focus-visible) {
3018    outline: none;
3019  }
3020
3021  /* ===== §9.2 BP CTA Group + Button — base rules =====================
3022     Sections wrap their CTAs in `[data-bp-cta-group]` with
3023     `data-dir-d="row|column"` and `data-dir-m="row|column"` to
3024     control multi-button layout per breakpoint. Each button is a
3025     `.bp-cta` rendered by snippets/bp-cta-button.liquid carrying
3026     `data-w-{d,m}="fit|custom"` plus inline `--bp-cta-w-{d,m}`
3027     custom-percent values for the Custom width mode.
3028     ================================================================= */
3029
3030  [data-bp-cta-group] {
3031    display: flex;
3032    flex-direction: column;
3033    flex-wrap: wrap;
3034    gap: 12px;
3035    align-items: stretch;
3036  }
3037  /* Full-width toggle stretches the group container itself (not just its
3038     buttons), so a group centered/shrink-wrapped by its parent still spans
3039     the full available width and its stacked buttons truly fill it. Only the
3040     CTA-group block opts in (data-full-width="true"); legacy section-level
3041     groups have no attribute and are unaffected. */
3042  [data-bp-cta-group][data-full-width='true'] { width: 100%; }
3043  [data-bp-cta-group][data-dir-m='row'] {
3044    flex-direction: row;
3045    align-items: center;
3046  }
3047  @media screen and (min-width: 1024px) {
3048    [data-bp-cta-group][data-dir-d='row'] {
3049      flex-direction: row;
3050      align-items: center;
3051    }
3052    [data-bp-cta-group][data-dir-d='column'] {
3053      flex-direction: column;
3054      align-items: stretch;
3055    }
3056  }
3057
3058  /* Button width — default Fit (content-sized). Custom mode picks
3059     the width up from the inline --bp-cta-w-{d,m} variable.
3060     In a STACKED group, buttons grow to full container width — UNLESS the
3061     group opts out via the Full-width toggle (bp-cta-group emits
3062     data-full-width="false"), where align-self:start defeats the group's
3063     align-items:stretch so each button hugs its fit/custom width instead.
3064     Groups with no attribute (legacy section-level [data-bp-cta-group])
3065     keep the full-width default. */
3066  .bp-cta[data-w-m='fit']  { width: auto; }
3067  .bp-cta[data-w-m='custom'] { width: var(--bp-cta-w-m, 100%); }
3068  @media screen and (max-width: 1023px) {
3069    [data-bp-cta-group]:not([data-dir-m='row']):not([data-full-width='false']) .bp-block-cta { width: 100%; }
3070    [data-bp-cta-group]:not([data-dir-m='row']):not([data-full-width='false']) .bp-cta { width: 100%; }
3071    [data-bp-cta-group]:not([data-dir-m='row'])[data-full-width='false'] .bp-block-cta,
3072    [data-bp-cta-group]:not([data-dir-m='row'])[data-full-width='false'] .bp-cta { align-self: flex-start; }
3073  }
3074  @media screen and (min-width: 1024px) {
3075    .bp-cta[data-w-d='fit']    { width: auto; }
3076    .bp-cta[data-w-d='custom'] { width: var(--bp-cta-w-d, 100%); }
3077    [data-bp-cta-group][data-dir-d='column']:not([data-full-width='false']) .bp-block-cta { width: 100%; }
3078    [data-bp-cta-group][data-dir-d='column']:not([data-full-width='false']) .bp-cta { width: 100%; }
3079    [data-bp-cta-group][data-dir-d='column'][data-full-width='false'] .bp-block-cta,
3080    [data-bp-cta-group][data-dir-d='column'][data-full-width='false'] .bp-cta { align-self: flex-start; }
3081  }
3082
3083  /* Base button shape — height + padding + typography. The colour
3084     palette comes from the section-local --bp-knobs-text + a small
3085     set of role-specific defaults below; sections can also layer in
3086     their own per-section CTA tokens via extra classes. */
3087  .bp-cta {
3088    display: inline-flex;
3089    align-items: center;
3090    justify-content: center;
3091    gap: 8px;
3092    height: 52px;
3093    padding: 0 28px;
3094    font-family: var(--bp-font-body);
3095    font-size: 17px;
3096    font-weight: 500;
3097    line-height: normal;
3098    letter-spacing: -0.17px;
3099    text-decoration: none;
3100    /* Default variant (secondary-like) — outlined dark on transparent.
3101       Always uses BP brand tokens, NOT --bp-knobs-text, so the button
3102       palette stays consistent regardless of the section's text color.
3103       Sections that need a different palette layer in their own scoped
3104       override (e.g. hero slides on dark imagery use `primary-light`). */
3105    border: 1px solid var(--bp-color-text);
3106    color: var(--bp-color-text);
3107    background: transparent;
3108    transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, opacity 0.2s ease;
3109    cursor: pointer;
3110    white-space: nowrap;
3111    box-sizing: border-box;
3112  }
3113  /* Keyboard focus indicator (WCAG 2.4.7). No focus style existed, so tabbing
3114     to a CTA showed nothing — flagged on the Image + Text Banner (Alfred, 7/27,
3115     ADA). `:focus-visible` (not `:focus`) so a mouse click doesn't leave a
3116     ring. The ring is OFFSET outside the button so it sits on the section/page
3117     background: a dark ring reads on the light surfaces every standard variant
3118     lives on; the on-dark variants (used over imagery) switch to the light
3119     label color below. Matches the existing `.bp-card__swatch:focus-visible`
3120     pattern. Also keep link-style CTAs underlined on hover so they never
3121     collapse to plain text (the second half of the ticket). */
3122  .bp-cta:focus-visible {
3123    outline: 2px solid var(--bp-color-text);
3124    outline-offset: 3px;
3125  }
3126  .bp-cta--primary-light:focus-visible,
3127  .bp-cta--secondary-light:focus-visible,
3128  .bp-cta--link-white:focus-visible {
3129    outline-color: var(--bp-color-cta-text);
3130  }
3131  .bp-cta--link:hover,
3132  .bp-cta--link:focus-visible,
3133  .bp-cta--link-white:hover,
3134  .bp-cta--link-white:focus-visible {
3135    text-decoration: underline;
3136  }
3137  .bp-cta__icon {
3138    display: inline-flex;
3139    align-items: center;
3140    width: 20px;
3141    height: 20px;
3142  }
3143  .bp-cta__icon img {
3144    width: 100%;
3145    height: 100%;
3146    display: block;
3147    object-fit: contain;
3148  }
3149
3150  /* Primary — fixed BP brand palette: dark fill + light label. The
3151     palette stays consistent across sections regardless of the
3152     section's `bp_text_color` setting; sections that need a different
3153     look on dark imagery pick `primary-light` (white fill, dark
3154     label) instead. */
3155  .bp-cta--primary {
3156    background: var(--bp-color-text);
3157    color: var(--bp-color-cta-text);
3158    border-color: var(--bp-color-text);
3159  }
3160  .bp-cta--primary:hover {
3161    background: transparent;
3162    color: var(--bp-color-text);
3163  }
3164
3165  /* Primary-light: inverse of primary — white fill + dark label.
3166     Use on sections that sit on dark imagery (e.g. hero closing
3167     sliders) where a dark filled CTA clashes with the background. */
3168  .bp-cta--primary-light {
3169    background: var(--bp-color-bg-page);
3170    color: var(--bp-color-text);
3171    border-color: #fff;
3172  }
3173  /* primary-light is the white-filled button used ON DARK imagery / dark
3174     sections. Its hover must stay LIGHT — transparent fill + near-white label
3175     and border — otherwise it resolves to dark-on-dark and the button reads
3176     "all black" on hover (QA: Dragana — "Find your look" / "View Details" on
3177     the homepage promo header). This is the correct default for the style, so
3178     it no longer needs the per-CTA "Hover style: White" opt-in. */
3179  .bp-cta--primary-light:hover {
3180    background: transparent;
3181    color: var(--bp-color-cta-text);
3182    border-color: var(--bp-color-cta-text);
3183  }
3184
3185  /* Sand: filled sand (#E8DFD0) button with dark-brown (#2B241A) label.
3186     Hover inverts to the sand-invert palette. */
3187  .bp-cta--sand {
3188    background: var(--bp-color-cta-sand);
3189    color: var(--bp-color-cta-sand-text);
3190    border-color: var(--bp-color-cta-sand);
3191  }
3192  .bp-cta--sand:hover {
3193    background: var(--bp-color-cta-sand-text);
3194    color: var(--bp-color-cta-sand);
3195    border-color: var(--bp-color-cta-sand-text);
3196  }
3197
3198  /* Sand (inverted): dark-brown fill with sand label — the invert of
3199     --sand. Hover swaps to the filled-sand palette. */
3200  .bp-cta--sand-invert {
3201    background: var(--bp-color-cta-sand-text);
3202    color: var(--bp-color-cta-sand);
3203    border-color: var(--bp-color-cta-sand-text);
3204  }
3205  .bp-cta--sand-invert:hover {
3206    background: var(--bp-color-cta-sand);
3207    color: var(--bp-color-cta-sand-text);
3208    border-color: var(--bp-color-cta-sand);
3209  }
3210
3211  .bp-cta--secondary:hover {
3212    background: var(--bp-color-text);
3213    color: var(--bp-color-cta-text);
3214  }
3215
3216  /* Secondary-light: the on-dark counterpart to `secondary`. Same
3217     outlined geometry, but a WHITE border + WHITE label on a
3218     transparent fill so it reads on dark imagery (e.g. the "Who we are"
3219     banner over a photo) where the standard dark `secondary` outline
3220     would disappear. Hover inverts exactly like `secondary` does —
3221     fills with the border color (white) and flips the label dark. */
3222  .bp-cta--secondary-light {
3223    background: transparent;
3224    color: var(--bp-color-cta-text);
3225    border-color: var(--bp-color-cta-text);
3226  }
3227  .bp-cta--secondary-light:hover {
3228    background: var(--bp-color-cta-text);
3229    color: var(--bp-color-text);
3230    border-color: var(--bp-color-cta-text);
3231  }
3232  .bp-cta--link {
3233    height: auto;
3234    padding: 0;
3235    border: 0;
3236    text-decoration: underline;
3237    text-underline-offset: 4px;
3238  }
3239  .bp-cta--link:hover { opacity: 0.65; }
3240
3241  /* Underline link, white text — for CTAs sitting on dark imagery /
3242     dark section backgrounds where the standard `link` (which inherits
3243     foreground color) would read black-on-black. Same geometry as
3244     `--link`; explicitly sets color to var(--bp-color-cta-text) so it
3245     doesn't pick up the surrounding text color. */
3246  .bp-cta--link-white {
3247    height: auto;
3248    padding: 0;
3249    border: 0;
3250    background: transparent;
3251    color: var(--bp-color-cta-text, #FDFFFA);
3252    text-decoration: underline;
3253    text-underline-offset: 4px;
3254  }
3255  .bp-cta--link-white:hover { opacity: 0.65; }
3256
3257  /* Opt-in hover: transparent fill + white border + white text. Set per CTA
3258     via the BP CTA block's "Hover style" = White. For CTAs on dark backgrounds
3259     (e.g. the black homepage promo bar) where the default per-style hover
3260     resolves to dark-on-dark (QA: Dragana). !important so it wins over the
3261     equal-specificity per-variant :hover rules regardless of source order. */
3262  .bp-cta--hover-white:hover {
3263    background: transparent !important;
3264    color: #fff !important;
3265    border-color: #fff !important;
3266    opacity: 1 !important;
3267  }
3268
3269  /* (Legacy --bp-cta-on override removed — primary's palette is now
3270     fixed at the base, so there's no longer a white-on-white scenario
3271     for sections to opt out of. Sections that need a light CTA on
3272     dark imagery should pick the `primary-light` variant instead.) */
3273
3274  /* ===== §9.1.x Text-overlay placement (9-position) ==================
3275     Used by sections that lay copy on top of media (hero slides,
3276     grid tiles). The wrapping element opts in via `[data-bp-overlay]`
3277     and reads four custom properties per breakpoint emitted by
3278     snippets/bp-overlay-place.liquid:
3279       --bp-overlay-block-{d,m}     start | center | end  (vertical)
3280       --bp-overlay-inline-{d,m}    start | center | end  (horizontal)
3281       --bp-overlay-text-{d,m}      start | center | end
3282
3283     The element is a column-direction flex container, so the
3284     vertical (block) axis is the MAIN axis (justify-content) and the
3285     horizontal (inline) axis is the CROSS axis (align-items). The
3286     text-align inherits from this container down to descendants. */
3287  [data-bp-overlay] {
3288    display: flex;
3289    flex-direction: column;
3290    justify-content: var(--bp-overlay-block-m, end);
3291    align-items: var(--bp-overlay-inline-m, center);
3292  }
3293  [data-bp-overlay] > * {
3294    text-align: var(--bp-overlay-text-m, center);
3295  }
3296  @media screen and (min-width: 1024px) {
3297    [data-bp-overlay] {
3298      justify-content: var(--bp-overlay-block-d, center);
3299      align-items: var(--bp-overlay-inline-d, start);
3300    }
3301    [data-bp-overlay] > * {
3302      text-align: var(--bp-overlay-text-d, start);
3303    }
3304  }
3305
3306  /* ============================================================
3307     Discount Kit (Helium) — Peak Progress GWP bar
3308     Targets the markup the app's embed injects (`#peak-progress-wrapper`).
3309     Restyled to match the BP free-gift bar in the Figma: Messina Sans
3310     typography, BP color tokens, slim 4px track with cream background +
3311     gold fill + a dot indicator at the fill's right edge.
3312     If marketing later swaps in a different DK block (e.g. tiered),
3313     these selectors stop matching gracefully — DK's own styles show
3314     through.
3315     ============================================================ */
3316  #peak-progress-wrapper {
3317    padding: 16px 0 24px;
3318    border-bottom: 1px solid rgba(23, 22, 9, 0.08);
3319    font-family: var(--bp-font-body);
3320    color: var(--bp-color-text);
3321  }
3322  #peak-progress-wrapper .peak-progress-container {
3323    display: block;
3324  }
3325  #peak-progress-wrapper .peak-progress-message {
3326    display: flex;
3327    justify-content: space-between;
3328    align-items: baseline;
3329    margin-bottom: 8px;
3330    gap: 12px;
3331  }
3332  #peak-progress-wrapper .threshold-title,
3333  #peak-progress-wrapper .threshold-count-message,
3334  #peak-progress-wrapper .threshold-counter {
3335    font-family: var(--bp-font-body);
3336    font-size: 14px;
3337    font-weight: 700;
3338    letter-spacing: -0.14px;
3339    color: var(--bp-color-text);
3340  }
3341  #peak-progress-wrapper .peak-progress-bar-outer {
3342    position: relative;
3343    height: 4px;
3344    background: #E8DFD0;
3345    border-radius: 0;
3346    overflow: visible;
3347  }
3348  #peak-progress-wrapper .peak-progress-bar-inner {
3349    position: relative;
3350    height: 100%;
3351    background: #EBAE55;
3352    border-radius: 0;
3353    transition: width 0.3s ease;
3354  }
3355  /* Dot indicator at the right edge of the fill — matches the BP Figma.
3356     Pinned to the inner bar's end via `right: 0` + `translate(50%, -50%)`
3357     so it tracks the fill width without extra JS. */
3358  #peak-progress-wrapper .peak-progress-bar-inner::after {
3359    content: '';
3360    position: absolute;
3361    top: 50%;
3362    right: 0;
3363    transform: translate(50%, -50%);
3364    width: 12px;
3365    height: 12px;
3366    border-radius: 50%;
3367    background: var(--bp-color-bg-page);
3368    border: 2px solid #EBAE55;
3369    box-sizing: border-box;
3370  }
3371  #peak-progress-wrapper .progress-copy {
3372    margin: 12px 0 0;
3373  }
3374  #peak-progress-wrapper .peak-progress-amount {
3375    font-family: var(--bp-font-body);
3376    font-size: 13px;
3377    color: var(--bp-color-body-copy);
3378  }
3379
3380  /* ============================================================
3381     BP Search Drawer + Search Panel
3382     ============================================================ */
3383
3384  /* Prevent Horizon's search modal from appearing — bp-search-drawer
3385     always intercepts the trigger and handles search instead (its own JS
3386     branches internally on settings.bp_br_search_enabled to pick
3387     Bloomreach vs. native Shopify results; the container/UI is the same
3388     either way). Target both the custom-element wrapper and the inner dialog. */
3389  dialog-component#search-modal,
3390  #search-modal dialog {
3391    display: none !important;
3392  }
3393
3394  /* /search page — hide the "Search" / "Search results" title (it stays in
3395     the DOM as the page's a11y <h1>, just visually hidden) and let the
3396     search input span full width, so the page opens with a full-width bar
3397     over the two-column results, matching the topnav search popup. */
3398  .search-page__header h1 {
3399    position: absolute !important;
3400    width: 1px;
3401    height: 1px;
3402    margin: -1px;
3403    padding: 0;
3404    border: 0;
3405    overflow: hidden;
3406    clip: rect(0 0 0 0);
3407    white-space: nowrap;
3408  }
3409  .search-page__header {
3410    display: block;
3411  }
3412
3413  /* Restyle Horizon's boxed _search-input into the Figma underline bar:
3414     search icon + input on one row, a single bottom rule, full width. */
3415  .search-page__header .search-page-input__parent { width: 100%; }
3416  .search-page__header search-page-input-component {
3417    max-width: 100% !important;
3418    width: 100%;
3419    display: flex;
3420    align-items: center;
3421    gap: 8px;
3422    margin: 0 0 28px;
3423    padding-block: 10px;
3424    border-bottom: 1px solid var(--bp-color-body-copy, #74736B);
3425    background: transparent;
3426  }
3427  .search-page__header .search-page-input {
3428    border: 0 !important;
3429    border-radius: 0 !important;
3430    background: transparent !important;
3431    padding: 4px 0 !important;
3432    font-family: var(--bp-font-body);
3433    font-size: 16px;
3434    color: var(--bp-color-text);
3435  }
3436  .search-page__header .search-page-input::placeholder {
3437    color: rgba(23, 22, 9, 0.62);
3438  }
3439  /* Icon inline (Horizon positions it absolutely for the boxed look). */
3440  .search-page__header search-page-input-component .search__icon {
3441    position: static !important;
3442    left: auto !important;
3443    flex-shrink: 0;
3444    width: 44px;
3445    height: 44px;
3446    aspect-ratio: 1 / 1;
3447    color: var(--bp-color-text);
3448    opacity: 0.6;
3449  }
3450  .search-page__header search-page-input-component .search__icon svg {
3451    width: 44px;
3452    height: 44px;
3453  }
3454  /* Keep the clear button pinned to the right edge of the row. */
3455  .search-page__header search-page-input-component .search__reset-button {
3456    right: 0;
3457  }
3458
3459  .bp-sp {
3460    background: var(--bp-color-bg-page);
3461    padding: 28px var(--bp-section-pad-x) 40px;
3462  }
3463
3464  .bp-sp__body {
3465    display: grid;
3466    grid-template-columns: 200px 1fr;
3467    gap: 48px;
3468    align-items: start;
3469  }
3470
3471  .bp-sp__sidebar {
3472    display: flex;
3473    flex-direction: column;
3474    gap: 24px;
3475    flex-shrink: 0;
3476  }
3477
3478  .bp-sp__group-title {
3479    margin: 0 0 10px;
3480    font-family: var(--bp-font-body);
3481    font-size: 13px;
3482    font-weight: 700;
3483    line-height: 145%;
3484    color: var(--bp-color-text);
3485  }
3486
3487  .bp-sp__links {
3488    list-style: none;
3489    margin: 0;
3490    padding: 0;
3491    display: flex;
3492    flex-direction: column;
3493    gap: 8px;
3494  }
3495
3496  .bp-sp__link {
3497    font-family: var(--bp-font-body);
3498    font-size: 14px;
3499    font-weight: 400;
3500    line-height: 145%;
3501    color: var(--bp-color-text);
3502    text-decoration: none;
3503  }
3504  .bp-sp__link:hover {
3505    text-decoration: underline;
3506    text-underline-offset: 3px;
3507  }
3508
3509  .bp-sp__products-title {
3510    margin: 0 0 16px;
3511    font-family: var(--bp-font-body);
3512    font-size: 13px;
3513    font-weight: 700;
3514    line-height: 145%;
3515    color: var(--bp-color-text);
3516  }
3517
3518  .bp-sp__grid {
3519    list-style: none;
3520    margin: 0;
3521    padding: 0;
3522    display: grid;
3523    /* Tablet 3 per row; desktop 4 (below); mobile 2 (below). 3-up read as too
3524       large on desktop for both the /search results and the topnav search-
3525       drawer suggested results, which share this grid (QA 7/16, Adrienne). */
3526    grid-template-columns: repeat(3, 1fr);
3527    gap: var(--bp-section-gap);
3528  }
3529  @media screen and (min-width: 1024px) {
3530    .bp-sp__grid {
3531      grid-template-columns: repeat(4, 1fr);
3532    }
3533  }
3534
3535  .bp-sp__item {
3536    min-width: 0;
3537  }
3538  .bp-sp__item > product-card,
3539  .bp-sp__item .bp-card-host { display: contents; }
3540
3541  /* Match the sitewide product-card ratio (3 / 4, see .bp-card__media above).
3542     The old 325 / 513 (~0.634) was taller/narrower than the source art, so
3543     object-fit: cover cropped the sides of every search-drawer thumbnail. */
3544  .bp-sp__item .bp-card__media {
3545    aspect-ratio: 3 / 4;
3546    height: auto;
3547  }
3548
3549  .bp-sp__footer {
3550    margin-top: 24px;
3551  }
3552
3553  .bp-sp__view-all {
3554    display: inline-flex;
3555    align-items: center;
3556    justify-content: center;
3557    padding: 10px 28px;
3558    font-family: var(--bp-font-body);
3559    font-size: 14px;
3560    font-weight: 500;
3561    line-height: 1;
3562    letter-spacing: 0.01em;
3563    color: var(--bp-color-text);
3564    background: transparent;
3565    border: 1px solid var(--bp-color-text);
3566    cursor: pointer;
3567    text-decoration: none;
3568    transition: background 0.15s ease, color 0.15s ease;
3569  }
3570  .bp-sp__view-all:hover {
3571    background: var(--bp-color-text);
3572    color: var(--bp-color-cta-text, #FDFFFA);
3573  }
3574
3575  @media screen and (max-width: 1023px) {
3576    .bp-sp__body {
3577      grid-template-columns: 180px 1fr;
3578      gap: 32px;
3579    }
3580  }
3581
3582  @media screen and (max-width: 767px) {
3583    .bp-sp {
3584      padding: 20px 16px 32px;
3585    }
3586    .bp-sp__body {
3587      grid-template-columns: 1fr;
3588      gap: 24px;
3589    }
3590    .bp-sp__grid {
3591      grid-template-columns: repeat(2, 1fr);
3592    }
3593    .bp-sp__view-all {
3594      width: 100%;
3595    }
3596  }
3597
3598  /* GTM / ad-network tracking pixels injected into <body> are 1×1
3599     images rendered inline, adding ~20px of line-height space below
3600     the footer. Force them out of the normal flow. We target by
3601     domain and by size so legitimate content images are unaffected.
3602
3603     EXCLUSIONS on the size-based selector mirror the earlier rule
3604     (~L37) — the Stylitics "How to Wear It" widget renders each tile
3605     as <img width="1" height="1" class="stylitics-ui-image"
3606     data-testid="stylitics-ui-image" loading="eager"> as a lazy-load
3607     placeholder, then resizes via Stylitics' --max-size CSS variable.
3608     Without these :not() guards the tiles stay pinned at 1×1 and the
3609     widget looks empty. */
3610  img[src*="dstillery.com"],
3611  img[src*="doubleclick.net"],
3612  img[src*="google-analytics.com"],
3613  img[src*="facebook.com/tr"],
3614  img[src*="bat.bing.com"],
3615  img[width="1"][height="1"]:not([class*="stylitics"]):not([data-testid]):not([loading]) {
3616    position: absolute !important;
3617    width: 1px !important;
3618    height: 1px !important;
3619    overflow: hidden !important;
3620    pointer-events: none !important;
3621  }
3622
3623  /* ============================================================
3624     Narvar (Shipping Protection) — restyle injected buttons + hide
3625     the Narvar product surface.
3626
3627     Narvar's storefront JS injects:
3628       - <button id="CartDrawer-Checkout-DP-With">    primary checkout
3629       - <button id="CartDrawer-Checkout-DP-Without"> secondary "without
3630                                                       shipping protection"
3631       - A product page for the underlying SKU `narvardeliveryprotection`
3632         (shouldn't be browsable as a normal product)
3633
3634     Atlas's CSS used Tailwind utilities (rgb(0 0 0 / opacity), 50px
3635     height, font-weight 600). We rewrite using BP design tokens
3636     (--bp-color-text, --bp-color-cta-text, --bp-font-body, 52px to
3637     match the BP cart drawer's other checkout buttons) so the
3638     Narvar buttons land in the same visual rhythm as the rest of
3639     the BP cart drawer instead of looking like an Atlas/Tailwind
3640     graft.
3641
3642     Atlas reference: Narvar custom CSS pasted by client 2026-05-22.
3643     ============================================================ */
3644
3645  /* NOTE: previously had a global
3646       div[data-product-handle="narvardeliveryprotection"]
3647       { display: none !important; }
3648     rule here to hide the Narvar SKU from PLP/search. Removed —
3649     our cart line items now (correctly, for Narvar to detect them)
3650     carry data-product-handle, so the rule also hid the Narvar
3651     line ITEM in the cart, breaking checkout. Hide the product
3652     from PLP/search via Shopify product visibility instead
3653     (Admin → Product → Sales channels → uncheck Online Store)
3654     or by leaving it out of every collection.
3655
3656     Now also adding the canonical CartPage-* IDs alongside the
3657     CartDrawer-* ones — Narvar uses different ID prefixes on the
3658     /cart page vs the drawer, so the styling has to cover both. */
3659
3660  /* Primary checkout button (Narvar injects this in place of the
3661     stock checkout button when the toggle is ON). Match BP's
3662     `.bp-cart-drawer__btn--primary` look. */
3663  button#CartDrawer-Checkout-DP-With {
3664    height: 52px;
3665    margin: 0;
3666    padding: 0 24px;
3667    background: var(--bp-color-text);
3668    color: var(--bp-color-cta-text);
3669    border: 1px solid var(--bp-color-text);
3670    font-family: var(--bp-font-body);
3671    font-size: 17px;
3672    font-weight: 500;
3673    line-height: normal;
3674    letter-spacing: -0.17px;
3675    text-transform: none;
3676    cursor: pointer;
3677    transition: opacity 0.2s ease, background 0.2s ease;
3678  }
3679  button#CartDrawer-Checkout-DP-With:hover {
3680    opacity: 0.85;
3681  }
3682
3683  /* Narvar's current widget build adds its own stable class
3684     (.narvar-cart-widget-button-checkout) alongside the DP-With id and
3685     ships `background` + text-color rules on that class via a
3686     stylesheet it injects itself (loaded later, after bp-fonts.liquid,
3687     via GTM) — same load-order problem already documented above for
3688     the CTA-casing fix. Out-specify with the bp-cart-drawer ancestor +
3689     !important so BP black always wins regardless of when Narvar's
3690     stylesheet lands, instead of just hoping the ID selector above is
3691     specific enough. */
3692  bp-cart-drawer button#CartDrawer-Checkout-DP-With,
3693  bp-cart-drawer button.narvar-cart-widget-button-checkout {
3694    background: var(--bp-color-text, #171609) !important;
3695    color: var(--bp-color-cta-text) !important;
3696  }
3697
3698  /* Protection total appended to the primary Checkout button. Narvar
3699     renders a `#checkout-price` span inside its DP-With button on BOTH
3700     the flyout and the /cart page. We previously hid it on the flyout
3701     only (`bp-cart-drawer #checkout-price { display:none }`), per an
3702     earlier "design doesn't show the price" note — but the /cart page
3703     was never scoped by that rule, so it always showed the total. That
3704     left the two surfaces inconsistent: page had the total, flyout did
3705     not. QA 7/27 (Dragana) asks the flyout to match the page, so the
3706     hide is removed and the total (subtotal + protection) shows on the
3707     checkout button on both surfaces. */
3708
3709  /* Secondary "Checkout without shipping protection" button. Match
3710     BP's `.bp-cart-drawer__btn--secondary` look — same height, BP
3711     typography, dark outline on cream/white surface. */
3712  button#CartDrawer-Checkout-DP-Without {
3713    height: 52px;
3714    margin: 0;
3715    padding: 0 24px;
3716    background: transparent;
3717    color: var(--bp-color-text);
3718    border: 1px solid var(--bp-color-text);
3719    font-family: var(--bp-font-body);
3720    font-size: 17px;
3721    font-weight: 500;
3722    line-height: normal;
3723    letter-spacing: -0.17px;
3724    text-transform: none;
3725    cursor: pointer;
3726    transition: background 0.2s ease, color 0.2s ease;
3727  }
3728  button#CartDrawer-Checkout-DP-Without:hover {
3729    background: var(--bp-color-bg-cream);
3730  }
3731
3732  /* Same buttons but on the /cart page — Narvar uses CartPage-* IDs
3733     there. Mirror the styling so the cart page looks consistent with
3734     the drawer. */
3735  button#CartPage-Checkout-DP-With {
3736    height: 52px;
3737    margin: 0;
3738    padding: 0 24px;
3739    background: var(--bp-color-text);
3740    color: var(--bp-color-cta-text);
3741    border: 1px solid var(--bp-color-text);
3742    font-family: var(--bp-font-body);
3743    font-size: 17px;
3744    font-weight: 500;
3745    line-height: normal;
3746    letter-spacing: -0.17px;
3747    cursor: pointer;
3748    transition: opacity 0.2s ease;
3749  }
3750  button#CartPage-Checkout-DP-With:hover {
3751    opacity: 0.85;
3752  }
3753  button#CartPage-Checkout-DP-Without {
3754    height: 52px;
3755    margin: 0;
3756    padding: 0 24px;
3757    background: transparent;
3758    color: var(--bp-color-text);
3759    border: 1px solid var(--bp-color-text);
3760    font-family: var(--bp-font-body);
3761    font-size: 17px;
3762    font-weight: 500;
3763    line-height: normal;
3764    letter-spacing: -0.17px;
3765    cursor: pointer;
3766    transition: background 0.2s ease;
3767  }
3768  button#CartPage-Checkout-DP-Without:hover {
3769    background: var(--bp-color-bg-cream);
3770  }
3771
3772  /* Narvar widget mount — collapse margin until Narvar populates it,
3773     so the empty <div> doesn't leave a phantom gap above the
3774     subtotal block. `:not(:empty)` keeps the natural spacing once
3775     Narvar's React renders content into the mount. */
3776  .bp-cart-drawer__narvar-widget:not(:empty) {
3777    margin: 0;
3778  }
3779
3780  /* ---- Shipping Protection loading skeleton (QA 7/27, Dragana) ----
3781     Narvar injects the real cream box a few seconds after the flyout opens /
3782     the cart page loads (its async bundle). This shimmer placeholder holds the
3783     box's shape until then, so there's no empty-whitespace gap that then pops.
3784     It mimics `.narvar-cart-widget-card` (cream, 8px padding, column, ~64px).
3785     Hidden the instant Narvar's real widget lands in the adjacent mount
3786     (`:has(+ mount > *)`) and when the JS marks it done / times out.
3787     Supersedes the earlier reserve-space approach (#307), which read as an
3788     empty whitespace gap. */
3789  .bp-cart-drawer__sp-skeleton,
3790  .bp-cart-page__sp-skeleton {
3791    display: flex;
3792    flex-direction: column;
3793    gap: 8px;
3794    padding: 8px;
3795    min-height: 64px;
3796    box-sizing: border-box;
3797    background: var(--bp-color-bg-cream, #F7F6EA);
3798    border-radius: 0;
3799  }
3800  .bp-cart-drawer__sp-skeleton:has(+ .bp-cart-drawer__narvar-widget > *),
3801  .bp-cart-page__sp-skeleton:has(+ .bp-cart-page__narvar-widget > *),
3802  .bp-sp-skeleton--hidden {
3803    display: none !important;
3804  }
3805  .bp-cart-drawer__sp-skeleton-head,
3806  .bp-cart-page__sp-skeleton-head {
3807    display: flex;
3808    align-items: center;
3809    justify-content: space-between;
3810    gap: 8px;
3811  }
3812  .bp-sp-skeleton-bar {
3813    display: block;
3814    height: 12px;
3815    border-radius: 2px;
3816    background: linear-gradient(
3817      90deg,
3818      rgba(23, 22, 9, 0.06) 25%,
3819      rgba(23, 22, 9, 0.12) 37%,
3820      rgba(23, 22, 9, 0.06) 63%
3821    );
3822    background-size: 400% 100%;
3823    animation: bpSpShimmer 1.4s ease infinite;
3824  }
3825  .bp-cart-drawer__sp-skeleton-title,
3826  .bp-cart-page__sp-skeleton-title { width: 128px; height: 14px; }
3827  .bp-cart-drawer__sp-skeleton-amt,
3828  .bp-cart-page__sp-skeleton-amt { width: 44px; height: 14px; }
3829  .bp-cart-drawer__sp-skeleton-desc,
3830  .bp-cart-page__sp-skeleton-desc { width: 82%; height: 10px; }
3831  @keyframes bpSpShimmer {
3832    0%   { background-position: 100% 50%; }
3833    100% { background-position: 0 50%; }
3834  }
3835  @media (prefers-reduced-motion: reduce) {
3836    .bp-sp-skeleton-bar { animation: none; }
3837  }
3838
3839  /* Shipping Protection — skin Narvar's NATIVE widget as the BP cream box
3840     (design parity). Narvar owns the price + copy + opt-out logic; we only
3841     style its card. Key off Narvar's STABLE classes (narvar-cart-widget-*)
3842     only — the _*_196oa_* hashes change on every app version. */
3843  .narvar-cart-widget-card {
3844    background: var(--bp-color-bg-cream, #F7F6EA) !important;
3845    /* Figma parity (QA 7/23, Brooke): 8px padding + flex container.
3846       Direct children are Narvar's header row (title + amount) and the
3847       description — they MUST stack, so column direction is required;
3848       row (the flex default) would sit the description beside the
3849       header. Narvar owns the header's own internal left/right layout
3850       via its hashed classes; we don't touch it. */
3851    display: flex !important;
3852    flex-direction: column !important;
3853    padding: 8px !important;
3854    gap: 8px !important;
3855    justify-content: center !important;
3856    /* stretch (not flex-start) so the direct children fill the row —
3857       Narvar's header row needs full width for its own space-between to
3858       push the amount to the right. Setting width:100% on the header
3859       directly isn't an option: its class (_196oa_) is a per-version
3860       hash. Text stays left-aligned either way. */
3861    align-items: stretch !important;
3862    align-self: stretch !important;
3863    color: var(--bp-color-text, #171609) !important;
3864    border-radius: 0 !important;
3865  }
3866  /* Force BP black on ALL widget text — Narvar's --color-accent (blue) leaks
3867     into nested spans (the amount + title inner spans). */
3868  .narvar-cart-widget-card,
3869  .narvar-cart-widget-card * {
3870    color: var(--bp-color-text, #171609) !important;
3871  }
3872  /* The design shows just the "Shipping Protection" label + info icon —
3873     hide Narvar's UPS/InsureShield logo image IN THE CARD only (the info
3874     modal shares the .narvar-cart-widget-logo class and keeps its hero logo). */
3875  .narvar-cart-widget-card .narvar-cart-widget-logo {
3876    display: none !important;
3877  }
3878  .narvar-cart-widget-title {
3879    /* Heading / H6 — Signifier */
3880    font-family: var(--bp-font-display) !important;
3881    font-size: 14px !important;
3882    font-weight: 300 !important;
3883    line-height: 120% !important;
3884    letter-spacing: -0.28px !important;
3885    color: var(--bp-color-text, #171609) !important;
3886  }
3887  .narvar-cart-widget-amount,
3888  .narvar-cart-widget-amount span {
3889    /* Body / Book / Small — Messina, right-aligned */
3890    font-family: var(--bp-font-body) !important;
3891    font-size: 14px !important;
3892    font-weight: 400 !important;
3893    letter-spacing: -0.14px !important;
3894    color: var(--bp-color-text, #171609) !important;
3895  }
3896  .narvar-cart-widget-description {
3897    /* Body / Book / Tiny — Messina */
3898    font-family: var(--bp-font-body) !important;
3899    font-size: 10px !important;
3900    font-weight: 400 !important;
3901    line-height: 145% !important;
3902    letter-spacing: -0.1px !important;
3903    color: var(--bp-color-text, #171609) !important;
3904    margin-top: -12px;
3905  }
3906  /* Mobile: pull the description up tight under the header (QA 7/23, Brooke). */
3907  @media screen and (max-width: 749px) {
3908    .narvar-cart-widget-description {
3909      margin-top: -16px !important;
3910    }
3911  }
3912  /* Info icon → BP black (Narvar defaults to a blue accent) + clickable
3913     (the drawer closes on click so Narvar's info surface isn't clipped). */
3914  .narvar-cart-widget-info-icon {
3915    fill: var(--bp-color-text, #171609) !important;
3916    width: 13px !important;
3917    height: 13px !important;
3918    cursor: pointer;
3919  }
3920
3921  /* ---- Narvar Shipping Protection info modal ("Peace of mind, delivered").
3922     Narvar injects it with minimal/broken styles; skin it with BP tokens.
3923     Stable IDs (#insurance-modal-*) are reliable — the _*_1mgdm_* hashes churn
3924     per app version. Shown when the widget info icon is clicked (the cart
3925     drawer closes so this isn't clipped). ---- */
3926  #insurance-modal-container {
3927    position: fixed;
3928    inset: 0;
3929    width: 100vw;
3930    z-index: 9999999999;
3931    display: flex;
3932    align-items: center;
3933    justify-content: center;
3934    padding: 16px;
3935    background: rgba(23, 22, 9, 0.45);
3936  }
3937  #insurance-modal-content {
3938    position: relative;
3939    width: 100%;
3940    max-width: 420px;
3941    max-height: 88vh;
3942    overflow-y: auto;
3943    background: #FDFFFA;
3944    color: var(--bp-color-text, #171609);
3945    font-family: var(--bp-font-body);
3946    padding: 32px 24px 24px;
3947  }
3948  #insurance-modal-header {
3949    position: relative;
3950    text-align: center;
3951    margin-bottom: 20px;
3952  }
3953  #insurance-modal-icon-wrapper {
3954    display: flex;
3955    justify-content: center;
3956    margin-bottom: 12px;
3957  }
3958  #insurance-modal-icon-image {
3959    width: auto !important;
3960    height: 40px !important;
3961  }
3962  #insurance-modal-hero-title {
3963    font-family: var(--bp-font-display);
3964    font-size: 22px;
3965    font-weight: 300;
3966    line-height: 120%;
3967    letter-spacing: -0.44px;
3968    margin: 0;
3969    color: var(--bp-color-text, #171609);
3970  }
3971  #insurance-modal-close-button {
3972    position: absolute;
3973    top: -14px;
3974    right: -8px;
3975    background: transparent;
3976    border: 0;
3977    padding: 4px;
3978    line-height: 0;
3979    cursor: pointer;
3980  }
3981  #insurance-modal-features-list {
3982    list-style: none;
3983    padding: 0;
3984    margin: 0 0 4px;
3985  }
3986  #insurance-modal-features-list li { margin: 0 0 14px; }
3987  [id^="insurance-modal-feature-"][id$="-title"] {
3988    font-family: var(--bp-font-body);
3989    font-size: 14px;
3990    font-weight: 600;
3991    color: var(--bp-color-text, #171609);
3992  }
3993  [id^="insurance-modal-feature-"][id$="-text"] {
3994    font-family: var(--bp-font-body);
3995    font-size: 13px;
3996    line-height: 145%;
3997    color: var(--bp-color-text, #171609);
3998  }
3999  #insurance-modal-content hr {
4000    border: 0;
4001    border-top: 1px solid rgba(23, 22, 9, 0.15);
4002    margin: 16px 0;
4003  }
4004  #insurance-modal-body-text,
4005  #insurance-modal-footer {
4006    font-family: var(--bp-font-body);
4007    font-size: 11px;
4008    line-height: 150%;
4009    color: var(--bp-color-body-copy, #74736B);
4010    margin: 0;
4011  }
4012  #insurance-modal-footer a { color: inherit; text-decoration: underline; }
4013  #insurance-modal-powered-by { align-items: center; }
4014  /* The "Powered by Narvar Secure" logo has no width/height attr, so a global
4015     img rule was stretching it — pin it to its intrinsic 16px. */
4016  #insurance-modal-powered-by-icon {
4017    width: 16px !important;
4018    height: 16px !important;
4019    flex: 0 0 16px;
4020  }
4021
4022  /* Narvar's toggle-card shell ships with a built-in `margin: 1rem 0`
4023     from its CSS module (hashed class `_card_196oa_1`, which changes
4024     on every Narvar extension bump). We target the stable widget-style
4025     class instead — `.opt-out-button` is the class Narvar's React
4026     applies to the card root when its widget_style setting is the
4027     opt-out button variant (matches what BP uses). Zero out the
4028     margin so our drawer's own `gap` controls spacing.
4029
4030     If a future widget-style switch is made (toggle / checkbox /
4031     opt-in-button / add-button / flyout), add the corresponding
4032     class here — see Narvar's `C` constant for the full list. */
4033  .opt-out-button {
4034    margin: 0 !important;
4035  }
4036
4037  /* Spacing between Narvar's primary (DP-With) and secondary
4038     (DP-Without) injected buttons. Narvar's React inlines
4039     `style="margin: 1rem 0"` on the DP-Without button; force a
4040     top-only gap so the buttons sit flush against the form
4041     bottom but still breathe between each other. Applied to both
4042     surfaces (drawer + cart page). */
4043  button#CartDrawer-Checkout-DP-Without,
4044  button#CartPage-Checkout-DP-Without {
4045    margin: 0.5rem 0 0 !important;
4046  }
4047  /* Mobile: tighter 4px gap between the primary + secondary Narvar
4048     buttons (half the desktop value, same ratio as before — was 8px
4049     over 1rem/16px). Kept directly after the 0.5rem rule above — equal
4050     specificity + !important on both means source order decides, so
4051     this MUST come last to win on mobile. */
4052  @media screen and (max-width: 749px) {
4053    button#CartDrawer-Checkout-DP-Without,
4054    button#CartPage-Checkout-DP-Without {
4055      margin: 4px 0 0 !important;
4056    }
4057  }
4058
4059  /* CTA casing (QA 7/14) — Narvar's injected checkout buttons should read
4060     Title Case ("Checkout Without Shipping Protection"), matching the native
4061     "Checkout" / "View Bag" CTAs and the design. The Narvar app's custom_css
4062     (config/settings_data.json) forces text-transform: uppercase at the same
4063     `button#id` specificity as bp-fonts, so load order decided it — hence the
4064     inconsistent casing. Out-specify by scoping to the BP cart wrappers
4065     (bp-cart-drawer / bp-cart-page → higher specificity) + !important so BP
4066     always wins. `capitalize` (not `none`) because Narvar's own label text is
4067     lower/upper-cased, so capitalize is what yields the Title-Case look. */
4068  bp-cart-drawer button#CartDrawer-Checkout-DP-With,
4069  bp-cart-drawer button#CartDrawer-Checkout-DP-Without,
4070  bp-cart-page button#CartPage-Checkout-DP-With,
4071  bp-cart-page button#CartPage-Checkout-DP-Without {
4072    text-transform: capitalize !important;
4073  }
4074
4075  /* ============================================================
4076     BP hero slide + shop-by-category link styles — moved here
4077     from sections/blocks during the block migration.
4078
4079     Why: Shopify's per-block / per-section stylesheet loading
4080     proved unreliable for these specific markup patterns when
4081     the section was migrated from inline section-defined blocks
4082     to theme blocks. Putting the rules in the global bp-fonts
4083     style block guarantees they apply regardless of which
4084     section/block stylesheet Shopify chooses to load.
4085
4086     References:
4087       - blocks/_bp-hero-slide.liquid (rendered article markup)
4088       - blocks/_bp-shop-link.liquid (rendered <li> markup)
4089       - sections/bp-hero-slider.liquid (wrapper + nav + dots)
4090       - sections/bp-shop-by-category.liquid (heading + <ul>)
4091     ============================================================ */
4092
4093  /* Shopify wraps every rendered theme block in a
4094     <div class="shopify-block" data-shopify-editor-block="...">
4095     wrapper for theme-editor click-to-edit. That wrapper breaks
4096     direct-child layouts (the slide track's grid, the link list's
4097     flex row, etc.) because the slide/list-item is no longer a
4098     direct child of the parent — it sits inside the wrapper.
4099
4100     `display: contents` makes the wrapper layout-transparent: its
4101     children behave as if they were direct children of the
4102     parent for layout purposes (grid items, flex items). Block
4103     identity for the editor stays — the wrapper still exists in
4104     the DOM and carries data-shopify-editor-block. */
4105  .bp-hero__track > .shopify-block,
4106  .bp-hero__content-inner > .shopify-block,
4107  .bp-shop-by-category__list > .shopify-block {
4108    display: contents;
4109  }
4110
4111  /* ----- bp-hero-slide ----- */
4112
4113  .bp-hero__slide {
4114    grid-column: 1 / 2;
4115    grid-row: 1 / 2;
4116    position: relative;
4117    display: block;
4118    width: 100%;
4119    max-width: 100vw;
4120    min-height: var(--bp-hero-min-height-mobile);
4121    aspect-ratio: var(--bp-hero-ratio-m, auto);
4122    color: var(--bp-hero-text-color);
4123
4124    opacity: 0;
4125    visibility: hidden;
4126    pointer-events: none;
4127    transition: opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1),
4128                visibility 0s linear 0.8s;
4129  }
4130
4131  bp-hero-slider[data-has-ratio-m='true'] .bp-hero__slide {
4132    display: flex;
4133    flex-direction: column;
4134    /* Unset the min-height so the slide's own aspect-ratio (set on
4135       .bp-hero__slide above) drives its height on mobile. A min-height
4136       floor here (e.g. max(50vh, max-content)) overrode the ratio and
4137       pinned every slide to ~50vh, so the picked "Aspect ratio (mobile)"
4138       had no visible effect. Copy taller than the ratio still grows the
4139       slide via the flex column's max-content. */
4140    min-height: unset;
4141  }
4142  bp-hero-slider[data-has-ratio-m='true'] .bp-hero__content {
4143    flex: 1;
4144    position: relative;
4145    width: 100%;
4146    min-height: auto;
4147  }
4148  @media screen and (min-width: 1024px) {
4149    bp-hero-slider[data-has-ratio-d='true'] .bp-hero__slide {
4150      display: flex;
4151      flex-direction: column;
4152      min-height: max-content;
4153    }
4154    bp-hero-slider[data-has-ratio-d='true'] .bp-hero__content {
4155      flex: 1;
4156      position: relative;
4157      width: 100%;
4158      min-height: auto;
4159    }
4160  }
4161
4162  .bp-hero__slide.is-active {
4163    opacity: 1;
4164    visibility: visible;
4165    pointer-events: auto;
4166    transition: opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1),
4167                visibility 0s linear 0s;
4168  }
4169
4170  @media (prefers-reduced-motion: reduce) {
4171    .bp-hero__slide,
4172    .bp-hero__slide.is-active {
4173      transition: none;
4174    }
4175    /* a11y (WCAG 2.3.3): neutralise every smooth-scroll rail site-wide in
4176       one place — the BP carousels (product-carousel, category-tiles,
4177       shop-the-look, tabbed-gallery, our-most-loved, cart, etc.) each set
4178       `scroll-behavior: smooth` locally. This overrides them all for users
4179       who prefer reduced motion, instead of guarding 13 files. */
4180    html:focus-within,
4181    *,
4182    *::before,
4183    *::after {
4184      scroll-behavior: auto !important;
4185    }
4186  }
4187
4188  .bp-hero__media {
4189    position: absolute;
4190    inset: 0;
4191    width: 100%;
4192    height: 100%;
4193    overflow: hidden;
4194    background: var(--color-background-muted, #f3f3f0);
4195    z-index: 0;
4196  }
4197
4198  .bp-hero__picture {
4199    position: absolute;
4200    inset: 0;
4201    width: 100%;
4202    height: 100%;
4203    display: block;
4204  }
4205
4206  .bp-hero__image {
4207    position: absolute;
4208    inset: 0;
4209    width: 100%;
4210    height: 100%;
4211    object-fit: cover;
4212    object-position: var(--bp-hero-img-pos-m);
4213    display: block;
4214  }
4215  @media screen and (min-width: 1024px) {
4216    .bp-hero__image {
4217      object-position: var(--bp-hero-img-pos-d);
4218    }
4219  }
4220
4221  .bp-hero__image--placeholder {
4222    background: linear-gradient(135deg, #e8e6df 0%, #cfccc1 100%);
4223  }
4224
4225  .bp-hero__content {
4226    position: relative;
4227    z-index: 1;
4228    flex-direction: column;
4229    min-height: var(--bp-hero-min-height-mobile);
4230    padding: var(--bp-hero-content-padding-mobile);
4231    padding-bottom: 88px;
4232    gap: 16px;
4233    color: var(--bp-hero-text-color);
4234  }
4235
4236  .bp-hero__content-inner {
4237    display: flex;
4238    flex-direction: column;
4239    gap: 16px;
4240    width: 100%;
4241    max-width: var(--bp-hero-content-max-mobile);
4242    align-items: var(--bp-overlay-inline-m, start);
4243  }
4244  @media screen and (min-width: 1024px) {
4245    .bp-hero__content-inner {
4246      align-items: var(--bp-overlay-inline-d, start);
4247    }
4248  }
4249
4250  .bp-hero__eyebrow {
4251    margin: 0;
4252    color: var(--bp-hero-text-color);
4253    font-family: var(--bp-font-body);
4254    font-size: 17px;
4255    font-style: normal;
4256    font-weight: 500;
4257    line-height: 110%;
4258    letter-spacing: -0.17px;
4259    text-transform: uppercase;
4260  }
4261
4262  .bp-hero__title {
4263    margin: 0;
4264    color: var(--bp-hero-text-color);
4265    font-family: var(--bp-font-display);
4266    font-size: clamp(36px, 6vw, 50px);
4267    font-style: normal;
4268    font-weight: 300;
4269    line-height: 120%;
4270    letter-spacing: -1px;
4271  }
4272
4273  .bp-hero__description {
4274    margin: 0;
4275    color: var(--bp-hero-text-color);
4276    font-family: var(--bp-font-body);
4277    font-size: 17px;
4278    font-style: normal;
4279    font-weight: 500;
4280    line-height: 145%;
4281    letter-spacing: -0.17px;
4282  }
4283  .bp-hero__description > * {
4284    margin: 0;
4285    color: inherit;
4286    font: inherit;
4287    letter-spacing: inherit;
4288  }
4289  .bp-hero__description > * + * {
4290    margin-top: 8px;
4291  }
4292
4293  .bp-hero__ctas {
4294    margin-top: 16px;
4295    width: 100%;
4296    align-items: var(--bp-overlay-inline-m, start);
4297    justify-content: var(--bp-overlay-inline-m, start);
4298  }
4299
4300  .bp-hero__cta.bp-cta {
4301    border-color: var(--bp-hero-text-color);
4302    color: #000;
4303  }
4304  .bp-hero__cta.bp-cta--primary {
4305    background: var(--bp-color-text);
4306    color: #fff;
4307  }
4308  .bp-hero__cta.bp-cta--primary:hover {
4309    background: transparent;
4310    color: var(--bp-hero-text-color);
4311  }
4312  .bp-hero__cta.bp-cta--primary-light {
4313    background: var(--bp-color-bg-page);
4314    color: var(--bp-color-text);
4315    border-color: #fff;
4316  }
4317  .bp-hero__cta.bp-cta--primary-light:hover {
4318    background: transparent;
4319    color: var(--bp-hero-text-color);
4320    border-color: var(--bp-hero-text-color);
4321  }
4322  .bp-hero__cta.bp-cta--secondary:hover {
4323    background: var(--bp-hero-text-color);
4324    color: #fff;
4325  }
4326
4327  @media screen and (max-width: 480px) {
4328    .bp-hero__content {
4329      padding-bottom: 24px;
4330    }
4331  }
4332
4333  @media screen and (max-width: 749px) {
4334    .bp-hero__title {
4335      font-size: clamp(24px, 6vw, 36px);
4336      letter-spacing: -0.5px;
4337    }
4338  }
4339
4340  @media screen and (min-width: 1024px) {
4341    .bp-hero__slide {
4342      min-height: var(--bp-hero-min-height-desktop);
4343      aspect-ratio: var(--bp-hero-ratio-d, auto);
4344    }
4345
4346    .bp-hero__content {
4347      min-height: var(--bp-hero-min-height-desktop);
4348      padding: var(--bp-hero-content-padding-desktop);
4349      padding-bottom: var(--bp-hero-content-padding-desktop);
4350    }
4351
4352    .bp-hero__content-inner {
4353      max-width: none;
4354      gap: 20px;
4355    }
4356    .bp-hero__description {
4357      max-width: var(--bp-hero-content-max-desktop);
4358    }
4359
4360    .bp-hero__ctas {
4361      width: 100%;
4362      margin-top: 24px;
4363      align-items: var(--bp-overlay-inline-d, start);
4364      justify-content: var(--bp-overlay-inline-d, start);
4365    }
4366
4367    .bp-hero__cta.bp-cta {
4368      min-width: 140px;
4369    }
4370  }
4371
4372  /* ----- bp-shop-by-category link ----- */
4373
4374  .bp-shop-by-category__item {
4375    flex-shrink: 0;
4376  }
4377
4378  .bp-shop-by-category__link {
4379    display: inline-block;
4380    color: inherit;
4381    text-decoration: underline;
4382    text-underline-offset: 4px;
4383    font-family: var(--bp-font-body);
4384    font-size: 17px;
4385    font-style: normal;
4386    font-weight: 500;
4387    line-height: normal;
4388    letter-spacing: -0.17px;
4389    transition: opacity 0.2s ease;
4390  }
4391  .bp-shop-by-category__link:hover { opacity: 0.65; }
4392
4393  /* ============================================================
4394     PAGE.CAREERS / PAGE.ABOUTUS — default body-copy color
4395     ------------------------------------------------------------
4396     Body-style bp-text blocks default to var(--bp-color-body-copy,
4397     #74736B). Overrides the FINAL fallback in bp-text's color chain
4398     (`color: var(--bp-text-color, var(--bp-knobs-text,
4399     var(--bp-color-text))))` — not the `color` property itself —
4400     so a merchant-set text_color on the block (which writes
4401     --bp-text-color inline) STILL WINS.
4402
4403     Scoped to .bp-text--ff-body so display-family bp-text (h1-h6
4404     using Signifier) keeps the dark --bp-color-text default.
4405     ============================================================ */
4406  main[data-template='page.careers'] .bp-text--ff-body,
4407  main[data-template='page.aboutus'] .bp-text--ff-body,
4408  main[data-template='page.sherylsloves'] .bp-text--ff-body,
4409  main[data-template='page.prospect-introduction'] .bp-text--ff-body {
4410    --bp-color-text: var(--bp-color-body-copy, #74736B);
4411  }
4412
4413  /* /pages/customer-care — hero (bp-image-text-banner) keeps the 32px
4414     mobile top padding but drops bottom padding to 0 so the link
4415     grid below sits flush against the hero. The §9.1 bp_padding_y_m
4416     knob is a single value (block top+bottom); the override below
4417     zeros only padding-block-end. */
4418  @media screen and (max-width: 1023px) {
4419    main[data-template='page.customer-care'] [data-section-id$='__hero'] {
4420      padding-block-end: 0 !important;
4421    }
4422  }
4423
4424  /* /pages/prospect-introduction — imagery grid content-tile spec.
4425     The Figma frame is 40px padding / 10px gap / flex-column /
4426     flex-start / stretch on the inner copy stack. Default §9.1.x
4427     tile-content uses 24×16 padding and 8px gap; override here. */
4428  main[data-template='page.prospect-introduction'] [data-section-id$='__bp_intro_imagery_grid'] .bp-grid__tile-content {
4429    padding: 40px !important;
4430  }
4431  main[data-template='page.prospect-introduction'] [data-section-id$='__bp_intro_imagery_grid'] .bp-grid__tile-content-inner {
4432    display: flex !important;
4433    flex-direction: column !important;
4434    align-items: flex-start !important;
4435    gap: 10px !important;
4436    align-self: stretch !important;
4437  }
4438
4439  /* /pages/brands-we-love — intro section spec.
4440     The section stays full-bleed (bp_bg_section cream extends to
4441     viewport edges) and uses its natural stacked layout. The
4442     overrides just dial the vertical padding to 80/40 and zero
4443     the bp-fc__inner padding + min-height that were stacking on
4444     top of the §9.1 section padding. */
4445  html body [data-section-id$='__bwl_intro'],
4446  html body [data-section-id='bwl_intro'] {
4447    padding-block: 80px 40px !important;
4448  }
4449  html body [data-section-id$='__bwl_intro'] .bp-fc__inner,
4450  html body [data-section-id='bwl_intro'] .bp-fc__inner {
4451    padding: 0 !important;
4452    min-height: 0 !important;
4453    gap: 0 !important;
4454  }
4455  html body [data-section-id$='__bwl_intro'] .bp-fc__features:empty,
4456  html body [data-section-id='bwl_intro'] .bp-fc__features:empty {
4457    display: none !important;
4458  }
4459  @media (max-width: 1023px) {
4460    html body [data-section-id$='__bwl_intro'],
4461    html body [data-section-id='bwl_intro'] {
4462      padding-block: 40px 24px !important;
4463    }
4464  }
4465
4466  /* /pages/brands-we-love — brand-grid tile titles match Figma H4:
4467     24/300/Signifier/120%/-0.48px, white. The global .bp-fs-h4 sets
4468     125% / -0.01em; this scoped rule tightens line-height + letter-
4469     spacing to the spec exactly. The H4 preset on bp-text already
4470     supplies size 24 + tag h4; per-instance JSON overrides
4471     (font_family: display, font_weight: 300) carry the family/weight. */
4472  html body [data-section-id$='__bwl_grid'] .bp-grid__tile .bp-text.bp-fs-h4,
4473  html body [data-section-id='bwl_grid'] .bp-grid__tile .bp-text.bp-fs-h4 {
4474    line-height: 120% !important;
4475    letter-spacing: -0.48px !important;
4476  }
4477
4478  /* /pages/brands-we-love — hero "big one" CTA forced to left.
4479     The single Shop Now CTA must hug the left edge of the slide on
4480     both breakpoints. Forces the group's main-axis to flex-start
4481     AND defeats the §9.2 mobile stretch rule
4482     ([data-bp-cta-group]:not([data-dir-m='row']) .bp-block-cta { width: 100% })
4483     which was making the button full-width on mobile and centering
4484     the label via the button's own justify-content: center. */
4485  html body [data-section-id$='__bwl_hero'] .bp-hero__content [data-bp-cta-group],
4486  html body [data-section-id='bwl_hero'] .bp-hero__content [data-bp-cta-group] {
4487    justify-content: flex-start !important;
4488    align-items: flex-start !important;
4489  }
4490  html body [data-section-id$='__bwl_hero'] .bp-hero__content [data-bp-cta-group] .bp-block-cta,
4491  html body [data-section-id$='__bwl_hero'] .bp-hero__content [data-bp-cta-group] .bp-cta,
4492  html body [data-section-id='bwl_hero'] .bp-hero__content [data-bp-cta-group] .bp-block-cta,
4493  html body [data-section-id='bwl_hero'] .bp-hero__content [data-bp-cta-group] .bp-cta {
4494    width: auto !important;
4495    margin-right: auto !important;
4496    align-self: flex-start !important;
4497  }
4498
4499  /* ============================================================
4500     YOTPO WIDGET — BP typography overrides
4501     ============================================================
4502     Yotpo injects its widget via tf-integration / yotpo-loader
4503     scripts and inlines its own font (Futura-PT / Open Sans) on
4504     the rendered elements. Force the BP body family on every
4505     Yotpo text node so reviews + Q&A match the rest of the site.
4506     The review BODY copy (.yotpo-read-more-text +
4507     .yotpo-comment-content retailer reply) additionally gets the
4508     Figma "Body/XSmall Book" spec — Messina 12 / 400 / 145% /
4509     -0.12 / body-copy gray. */
4510  .yotpo-widget-instance,
4511  .yotpo-widget-instance *,
4512  .yotpo-reviews-main-widget,
4513  .yotpo-reviews-main-widget *,
4514  .yotpo-reviews-star-ratings-widget,
4515  .yotpo-reviews-star-ratings-widget * {
4516    font-family: var(--bp-font-body), 'Messina Sans VF', system-ui, -apple-system, sans-serif !important;
4517  }
4518  .yotpo-widget-instance .yotpo-read-more-text,
4519  .yotpo-widget-instance .yotpo-text-container,
4520  .yotpo-widget-instance .yotpo-comment-content {
4521    color: var(--bp-color-body-copy, #74736B) !important;
4522    font-family: var(--bp-font-body), 'Messina Sans VF', system-ui, sans-serif !important;
4523    font-size: 12px !important;
4524    font-style: normal !important;
4525    font-weight: 400 !important;
4526    line-height: 145% !important;
4527    letter-spacing: -0.12px !important;
4528  }
4529  /* Bold title elements — review headline + retailer reply heading.
4530     Figma "Body/Semi/Small" spec: Messina 14 / 660 / 145% / -0.14
4531     in BP black (#171609). */
4532  .yotpo-widget-instance .yotpo-review-title,
4533  .yotpo-widget-instance .yotpo-comment-title {
4534    color: var(--bp-color-text, #171609) !important;
4535    font-family: var(--bp-font-body), 'Messina Sans VF', system-ui, sans-serif !important;
4536    font-size: 14px !important;
4537    font-style: normal !important;
4538    font-weight: 700 !important;
4539    line-height: 145% !important;
4540    letter-spacing: -0.14px !important;
4541  }
4542
4543  /* "With media" toggle — Yotpo renders a button > label > SVG-circle
4544     stack that flexes weirdly under the BP font override (label
4545     becomes block-level, SVG drops below the text). Pin the button
4546     to flex/row + 8px gap, keep the SVG inline. When aria-pressed,
4547     fill the circle so the selected state reads. */
4548  .yotpo-widget-instance .yotpo-media-select {
4549    display: inline-flex !important;
4550    flex-direction: row !important;
4551    align-items: center !important;
4552    gap: 8px !important;
4553    background: transparent !important;
4554    border: 1px solid rgba(23, 22, 9, 0.18) !important;
4555    border-radius: 0 !important;
4556    padding: 10px 12px !important;
4557    cursor: pointer !important;
4558    color: var(--bp-color-text, #171609) !important;
4559    font-family: var(--bp-font-body), 'Messina Sans VF', system-ui, sans-serif !important;
4560    font-size: 14px !important;
4561    font-weight: 500 !important;
4562    line-height: 145% !important;
4563    letter-spacing: -0.14px !important;
4564  }
4565  .yotpo-widget-instance .yotpo-media-select .yotpo-radio-base {
4566    display: inline-flex !important;
4567    align-items: center !important;
4568    flex: 1 1 auto !important;
4569    margin: 0 !important;
4570    padding: 0 !important;
4571    cursor: pointer !important;
4572  }
4573  .yotpo-widget-instance .yotpo-media-select .yotpo-selected-value {
4574    color: inherit !important;
4575    line-height: inherit !important;
4576  }
4577  .yotpo-widget-instance .yotpo-media-select .yotpo-radio-icon {
4578    flex: 0 0 auto !important;
4579    width: 16px !important;
4580    height: 16px !important;
4581    display: block !important;
4582  }
4583  .yotpo-widget-instance .yotpo-media-select[aria-pressed='true'] .yotpo-radio-icon circle {
4584    fill: var(--bp-color-text, #171609) !important;
4585    stroke: var(--bp-color-text, #171609) !important;
4586  }
4587
4588  /* ── Header scroll-logo swap ─────────────────────────────────────
4589     Swaps the header logo to the dedicated "scroll" variant
4590     (settings.logo_scroll, rendered in blocks/_header-logo.liquid)
4591     when the nav enters its compact state. Independent of Horizon's
4592     transparent/inverse logo system — only the logo mark swaps.
4593     Selectors carry #header-component so they outrank the existing
4594     `.header-logo:has(...)` / `.header-logo__image-container--inverse`
4595     display rules regardless of source order.
4596
4597     ── Why data-bp-nav and not data-sticky-state ──────────────────
4598     These rules used to key off Horizon's [data-sticky-state='active']
4599     (assets/header.js #observeStickyPosition). That flag is written by
4600     Horizon's IntersectionObserver from the header's own visibility —
4601     and the rules below CHANGE the header's height and position. Any
4602     state whose styles perturb the geometry that produces the state is
4603     a feedback loop: the observer writes a value, the header resizes /
4604     unpins, the observer re-fires, writes the opposite value. The
4605     header strobes between variants. (Measured 2026-07-14: with
4606     threshold: 1, isIntersecting is false at ratio 0.9888 and true at
4607     ratio 1, so Horizon's flag flips at exactly rect.top === 0 — the
4608     single offset where a header pinned at top: -1px hands off from
4609     in-flow to pinned. That is where the strobe appeared.)
4610
4611     data-bp-nav is owned solely by the scroll-threshold state machine
4612     in layout/theme.liquid, driven by scrollY — an input the header's
4613     own size cannot perturb. Horizon keeps writing data-sticky-state
4614     for its own purposes (opacity, view-transition-name); it no longer
4615     drives any geometry, so the two can never fight. */
4616  .header-logo__image-container--scroll {
4617    display: none;
4618  }
4619
4620  /* ── Positioning model ────────────────────────────────────────────
4621     Resting nav is IN FLOW and scrolls away with the page; only the
4622     compact bar is fixed. Cancels Horizon's `position: sticky;
4623     top: -1px` for sticky="always" (sections/header.liquid:553).
4624
4625     .header-section keeps the resting header's height via
4626     --bp-header-rest-h even while the child is fixed, so nothing below
4627     ever shifts when the compact bar engages. That reserved space is
4628     what makes scrollY a stable trigger: no reflow → no scroll
4629     anchoring → no feedback into the threshold. Without it, going
4630     fixed would pull ~70px of content up and move the very scroll
4631     offset the state machine reads.
4632
4633     !important + the body prefix because Horizon's rule is
4634     `.header-section:has(> #header-component[sticky='always'])`, whose
4635     :has() takes the specificity of its argument (an id + attr), and
4636     section stylesheet blocks are bundled separately from this inline
4637     style tag — source order isn't guaranteed.
4638
4639     NB: don't write Liquid tag delimiters in these comments, even
4640     inside a CSS comment. Liquid parses tags before CSS exists, so a
4641     literal stylesheet/style tag written here is read as a real tag
4642     nested inside this style block and throws at compile. */
4643  body .header-section:has(> #header-component[sticky='always']) {
4644    position: static !important;
4645    top: auto !important;
4646    min-height: var(--bp-header-rest-h, auto);
4647  }
4648
4649  #header-component[data-bp-nav='compact'] {
4650    position: fixed;
4651    top: 0;
4652    left: 0;
4653    right: 0;
4654    z-index: var(--layer-sticky);
4655  }
4656
4657  /* flex (not block) so the icon centers on both axes instead of
4658     sitting on the inline text baseline, which left descender
4659     whitespace below it and made it look pushed toward the top of
4660     the row. */
4661  #header-component[data-bp-nav='compact'] .header-logo__image-container--scroll {
4662    display: flex;
4663    align-items: center;
4664    justify-content: center;
4665  }
4666
4667  #header-component[data-bp-nav='compact'] .header-logo__image-container--original,
4668  #header-component[data-bp-nav='compact'] .header-logo__image-container--inverse {
4669    display: none;
4670  }
4671
4672  /* Design request: collapse header__columns vertical padding to 0
4673     the moment the header becomes sticky, so the sticky bar sits flush
4674     rather than keeping the resting-state --header-padding. Overrides
4675     header.liquid's `.header__columns { --padding-block-start/end }`
4676     (assets/base.css .spacing-style reads these into padding-block). */
4677  #header-component[data-bp-nav='compact'] .header__columns {
4678    --padding-block-start: 0px;
4679    --padding-block-end: 0px;
4680  }
4681
4682  /* Design request: once the logo has swapped to the compact scroll
4683     mark, let the left and right grid tracks (.header__column--left,
4684     .header__column--right) hug their content width instead of the
4685     resting-state 1fr / minmax(max-content, 1fr) tracks — frees up
4686     space for the center column while sticky. --header-left/-right
4687     feed --header-template-columns (grid-template-columns) above;
4688     the ID selector's specificity beats every non-sticky :has()-based
4689     --header-left/-right override in this file. */
4690  #header-component[data-bp-nav='compact'] .header__columns {
4691    --header-left: max-content;
4692    --header-right: max-content;
4693  }
4694
4695  /* ---------------------------------------------------------------
4696     Quick-view product template (?view=quickview) — Atlas parity.
4697
4698     The Publitas digital-catalog product modal loads
4699     /products/<handle>?view=quickview inside its #prod-frame iframe.
4700     That renders templates/product.quickview.json (the buy box only).
4701     Strip the site chrome so the iframe shows an optimized product
4702     view — no topnav, announcement bar, footer, sticky ATC, or chat —
4703     rather than the whole storefront.
4704
4705     Scoped with :has() off the <main data-template> attribute
4706     (theme.liquid emits data-template="product", which
4707     resolves to "product.quickview" here), so nothing leaks onto
4708     the normal PDP. Matches Atlas templates/product.quickview.liquid,
4709     which display:none's #shopify-section-header / -footer / etc.
4710     --------------------------------------------------------------- */
4711
4712  /* Hide all site chrome in the quickview modal. display:none is correct
4713     here: the cart drawer is removed from the iframe entirely (see
4714     bp-quickview-cart-bridge.liquid). The just-added item is shown by the
4715     PARENT catalog page's cart drawer instead — it runs in full page
4716     context (so its section-scoped line re-render works reliably) and
4717     opens in the top layer, above the Publitas modal. Trying to render the
4718     drawer inside the iframe was fragile: its syncItemsList() walks
4719     ancestor shopify-section wrappers and re-fetches sections against the
4720     iframe URL, which didn't repopulate the just-added line. */
4721  body:has(main[data-template='product.quickview']) #header-group,
4722  body:has(main[data-template='product.quickview']) > footer,
4723  body:has(main[data-template='product.quickview']) .bp-sticky-atc,
4724  body:has(main[data-template='product.quickview']) #chat-button {
4725    display: none !important;
4726  }
4727
4728  /* Same hides keyed off the BODY CLASS (layout/theme.liquid adds
4729     `template-quickview`) instead of `:has(main…)`. The `:has(main…)` form only
4730     matches AFTER <main> parses — which comes after the header — so on each
4731     product change the header / announcement bar / BP logo / top menu flashed
4732     visible for a frame before being hidden (Dragana QA 7/22). The body class
4733     is present at first paint, so these hide with no flash.
4734     This block ALSO strips the PDP-only buy-box extras the digital-catalog quick
4735     view shouldn't show (Dragana QA 7/22): the gallery breadcrumb + "How to Wear
4736     It" chip, the size-chart link, the TrueFit find-my-size widget, and the
4737     Product Detail / Size & Fit / Shipping & Returns accordions. */
4738  body.template-quickview #header-group,
4739  body.template-quickview > footer,
4740  body.template-quickview .bp-sticky-atc,
4741  body.template-quickview #chat-button,
4742  body.template-quickview .bp-pdp-gallery__crumbs,
4743  body.template-quickview .bp-pdp-gallery__htwi,
4744  body.template-quickview .bp-size-chart-link,
4745  body.template-quickview .tfc-fitrec-product,
4746  body.template-quickview .bp-acc {
4747    display: none !important;
4748  }
4749
4750  body:has(main[data-template='product.quickview']) main.content-for-layout {
4751    padding-top: 0;
4752    margin-top: 0;
4753  }
4754
4755  /* PDP sticky add-to-cart bar (.bp-sticky-atc, z-index: 100) sits above
4756     everything by design, but that also puts it above the mobile nav
4757     drawer (bp-mobile-drawer, z-index ~5-6 off --layer-heightened) —
4758     covering the bottom menu items when the drawer is open on a PDP.
4759     Hide it for the duration instead of escalating the drawer's z-index,
4760     which would ripple into every other component sharing that token. */
4761  body:has(bp-mobile-drawer .bp-mobile-drawer__details[open]) .bp-sticky-atc {
4762    display: none !important;
4763  }
4764
4765  /* ============================================================
4766     AB Tasty social-proof popup ("POPULAR! N views in the last N days",
4767     injected at runtime via GTM/AB Tasty — .ab_widget_container_social-proof_*).
4768     It was anchored to the left of the PDP gallery and overflowed the image
4769     frame / got clipped at the viewport's left edge on wide monitors (QA 7/21).
4770     Re-anchor it as a safe bottom-left toast so it stays fully on-screen at any
4771     width and can't overlap the gallery. NOTE: the auto-dismiss timing ("not
4772     gone in a few seconds") is an AB Tasty CAMPAIGN setting, not theme code.
4773     ============================================================ */
4774  .ab_widget_container_social-proof_content {
4775    position: fixed !important;
4776    left: 16px !important;
4777    right: auto !important;
4778    bottom: 16px !important;
4779    top: auto !important;
4780    transform: none !important;
4781    max-width: min(320px, calc(100vw - 32px)) !important;
4782    z-index: 30 !important;
4783  }
4784
4785  /* ============================================================
4786     Yotpo referral widget (instance 506320) — BP-controlled overrides.
4787     These previously lived only in Yotpo's dashboard Custom CSS; kept here
4788     so they're version-controlled and survive a Yotpo re-config. Renders on
4789     the refer-a-friend page and the Proper Insider rewards page. Class names
4790     are doubled to outrank Yotpo's runtime-injected single-class rules.
4791     ============================================================ */
4792  .yotpo-widget-referral-widget .yotpo-center-container.yotpo-center-container {
4793    height: 626px;
4794  }
4795  /* Don't force the copy-code text white — keep it readable (BP text color)
4796     against the widget's light surface. */
4797  .yotpo-widget-referral-widget .yotpo-copy-text-button .yotpo-copy-text.yotpo-copy-text {
4798    color: var(--bp-color-text) !important;
4799  }
4800
4801  /* ============================================================
4802     Cart-flyout (quick-add drawer) Add-to-bag button — match the PDP CTA.
4803     The drawer's buy button is redistributed into .bp-qd__cta-slot, OUTSIDE
4804     .product-information, so the PDP button rules (bp-pdp-styles) never reach
4805     it — it came out mis-sized / stretched with no bag icon (QA: Amber).
4806     Mirror the PDP spec: 17px / -0.17px / 500, filled black, 20px bag icon,
4807     hover inverts. Icon = shared assets/bp-bag-icon.svg (white); hover uses
4808     filter:brightness(0) to flip it black on the transparent button.
4809     ============================================================ */
4810  dialog.quick-add-modal.bp-qd add-to-cart-component button,
4811  dialog.quick-add-modal.bp-qd button[name="add"],
4812  dialog.quick-add-modal.bp-qd .buy-buttons button[type="submit"] {
4813    width: 100%;
4814    background: var(--bp-color-text, #171609) !important;
4815    color: var(--bp-color-cta-text, #FDFFFA) !important;
4816    border: 1px solid var(--bp-color-text, #171609) !important;
4817    border-radius: 0 !important;
4818    padding: 16px 24px !important;
4819    font-family: var(--bp-font-body) !important;
4820    font-size: 17px !important;
4821    font-weight: 500 !important;
4822    line-height: normal !important;
4823    letter-spacing: -0.17px !important;
4824    text-transform: none !important;
4825    display: inline-flex !important;
4826    align-items: center !important;
4827    justify-content: center !important;
4828    gap: 10px !important;
4829  }
4830  dialog.quick-add-modal.bp-qd add-to-cart-component button .svg-wrapper.add-to-cart-icon,
4831  dialog.quick-add-modal.bp-qd add-to-cart-component button .add-to-cart-icon,
4832  dialog.quick-add-modal.bp-qd button[name="add"] .svg-wrapper.add-to-cart-icon,
4833  dialog.quick-add-modal.bp-qd button[name="add"] .add-to-cart-icon {
4834    display: none !important;
4835  }
4836  dialog.quick-add-modal.bp-qd add-to-cart-component button::after,
4837  dialog.quick-add-modal.bp-qd button[name="add"]::after,
4838  dialog.quick-add-modal.bp-qd .buy-buttons button[type="submit"]::after {
4839    content: '' !important;
4840    display: inline-block !important;
4841    flex: 0 0 20px !important;
4842    width: 20px !important;
4843    height: 20px !important;
4844    background-repeat: no-repeat;
4845    background-position: center;
4846    background-size: contain;
4847    background-image: url(//www.bostonproper.com/cdn/shop/t/1521/assets/bp-bag-icon.svg?v=5174825450042497821790713714);
4848  }
4849  dialog.quick-add-modal.bp-qd add-to-cart-component button:hover,
4850  dialog.quick-add-modal.bp-qd button[name="add"]:hover,
4851  dialog.quick-add-modal.bp-qd .buy-buttons button[type="submit"]:hover,
4852  dialog.quick-add-modal.bp-qd add-to-cart-component button:hover .add-to-cart-text,
4853  dialog.quick-add-modal.bp-qd add-to-cart-component button:hover .add-to-cart-text *,
4854  dialog.quick-add-modal.bp-qd button[name="add"]:hover .add-to-cart-text,
4855  dialog.quick-add-modal.bp-qd button[name="add"]:hover .add-to-cart-text * {
4856    background: transparent !important;
4857    color: var(--bp-color-text, #171609) !important;
4858  }
4859  dialog.quick-add-modal.bp-qd add-to-cart-component button:hover::after,
4860  dialog.quick-add-modal.bp-qd button[name="add"]:hover::after,
4861  dialog.quick-add-modal.bp-qd .buy-buttons button[type="submit"]:hover::after {
4862    filter: brightness(0);
4863  }
4864
4865  /* ============================================================
4866     Cart Shop Pay Installments logo → black (QA: Amber). Shopify's
4867     native installments banner (the payment_terms filter in the
4868     Horizon snippet cart-summary.liquid) injects a purple Shop Pay
4869     wordmark as an img with id shoppay-installments-icon. BP wants it
4870     black in the cart. filter:brightness(0) flattens the artwork to
4871     solid black while preserving its transparency (same trick used on
4872     the cart-flyout bag icon above). Scoped to .cart-totals__installments
4873     so only the cart surfaces (drawer + cart page) are recoloured, not
4874     any other Shop Pay mark.
4875     ============================================================ */
4876  .cart-totals__installments #shoppay-installments-icon {
4877    filter: brightness(0) !important;
4878  }
4879
4880  /* ============================================================
4881     PLP Back-nav restore veil
4882     bp-bloomreach.js adds html.bp-plp-restoring while a saved scroll
4883     position is restored on a full-reload Back (PDP → Back → PLP), so the
4884     shopper sees a brief loader instead of the grid painting at the TOP and
4885     then jumping to their spot. Removed the instant the scroll lands (JS,
4886     with a safety timeout). A bfcache Back never sets it, so that stays
4887     instant. pointer-events:none so a real scroll/tap still passes through
4888     and cancels the restore. Global (targets <html>) so it covers both the
4889     /collections and /search PLPs, whose grid CSS lives in separate scoped
4890     stylesheets.
4891     ============================================================ */
4892  .bp-plp-restore-veil {
4893    position: fixed;
4894    inset: 0;
4895    z-index: 2147483000;
4896    background: var(--bp-color-bg-page, #FEFFFA);
4897    display: flex;
4898    align-items: center;
4899    justify-content: center;
4900    pointer-events: none;
4901    opacity: 1;
4902    transition: opacity 0.4s ease;
4903  }
4904  /* Kill smooth-scroll while we pin the restore offset — Safari will
4905     otherwise animate (and lose) competing scrollTo calls. */
4906  html.bp-plp-restoring {
4907    scroll-behavior: auto !important;
4908  }
4909  html.bp-plp-restoring body {
4910    scroll-behavior: auto !important;
4911  }
4912  /* JS adds .is-out to fade the veil to 0, then removes the element once
4913     faded — so it disappears SMOOTHLY, not "de golpe". */
4914  .bp-plp-restore-veil.is-out { opacity: 0; }
4915  .bp-plp-restore-veil__spin {
4916    width: 34px;
4917    height: 34px;
4918    border-radius: 50%;
4919    border: 3px solid rgba(23, 22, 9, 0.15);
4920    border-top-color: var(--bp-color-text, #171609);
4921    animation: bpPlpRestoreSpin 0.7s linear infinite;
4922  }
4923  @media (prefers-reduced-motion: reduce) {
4924    .bp-plp-restore-veil { transition: none; }
4925    .bp-plp-restore-veil__spin { animation: none; }
4926  }
4927  @keyframes bpPlpRestoreSpin { to { transform: rotate(360deg); } }
4928
4929  /* ============================================================
4930     PDP title de-flicker
4931     Each colourway is a separate product whose Shopify title carries the
4932     colour name; snippets/bp-pdp-title-color.liquid strips it (the colour is
4933     already shown by the swatch). Server-side stripping isn't possible — the
4934     title is a Text block bound to a  dynamic source — so hide the title
4935     until the snippet strips it and marks it [data-bp-title-ready], so the full
4936     "…Colour" title never flashes first. visibility:hidden keeps its box (no
4937     CLS). A pure-CSS animation reveals it after 1.2s as a fail-safe, so it can
4938     never get stuck hidden if the JS doesn't run.
4939     ============================================================ */
4940  .product-information h1:not([data-bp-title-ready]),
4941  .product-details h1:not([data-bp-title-ready]) {
4942    visibility: hidden;
4943    animation: bpTitleRevealSafety 0s linear 1.2s forwards;
4944  }
4945  @keyframes bpTitleRevealSafety { to { visibility: visible; } }
4946</style>
4947<link rel="stylesheet" href="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-fonts-deferred.css?v=138496893836640374981790713714" media="print" onload="this.media='all'">
4948    <noscript><link rel="stylesheet" href="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-fonts-deferred.css?v=138496893836640374981790713714"></noscript>
4948<script src="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-preorder-dates.js?v=90299843317653306041790713714"></script>
4948<style id="dg-consent-custom-style">
4949  :host(.dg-consent-banner) {--dg-primary-font: var(--bp-font-body, 'Messina Sans VF', system-ui, sans-serif);
4950    --dg-consent-background-border: #ffffff;
4951    --consent-border-radius: 0;--dg-heading-font-size: 20px;
4952    --dg-heading-font-weight: 500;--dg-explanation-font-size: 15px;
4953    --dg-explanation-font-weight: 400;--dg-policy-option-heading-size: 15px;
4954    --dg-policy-option-heading-weight: 500;
4955    --dg-policy-option-description-font-size: 15px;
4956    --dg-policy-option-description-font-wieght: 400; /* `wieght` is not a typo here — it is on DataGrail's side, and this must match their variable name */
4957    --dg-policy-option-essential-label-font-color: #666;
4958    --dg-policy-option-essential-label-font-wieght: 400; /* `wieght` — see above */--dg-slider-enabled-secondary: #CC0066 !important;--dg-button-color: var(--bp-color-cta-text, #FDFFFA) !important;
4959    --dg-button-background: var(--bp-color-text, #171609) !important;
4960    --dg-button-border: none !important;
4961    --dg-button-radius: 0 !important;letter-spacing: 0.25px !important;
4962    font-family: var(--bp-font-body, 'Messina Sans VF', system-ui, sans-serif) !important;
4963  }:host(.dg-consent-banner) * {
4964    letter-spacing: 0.25px !important;
4965    font-family: var(--bp-font-body, 'Messina Sans VF', system-ui, sans-serif) !important;
4966  }
4967
4968  :host(.dg-consent-banner) .dg-app {
4969    max-width: 501px !important;
4970  }
4971
4972  :host(.dg-consent-banner) h1.dg-header {
4973    border-bottom: none !important;
4974    line-height: 28px !important;
4975  }
4976
4977  :host(.dg-consent-banner) .dg-header-close {
4978    position: absolute !important;
4979    top: 12px !important;
4980    right: 12px !important;
4981    width: 18px !important;
4982    height: 18px !important;
4983    padding: 4px !important;
4984  }
4985
4986  :host(.dg-consent-banner) .dg-header-close svg {
4987    display: none !important;
4988  }:host(.dg-consent-banner) .dg-header-close::before {
4989    content: url("//www.bostonproper.com/cdn/shop/t/1521/assets/icon-close.svg?v=127645775129621355101790713714") !important;
4990    position: absolute !important;
4991    top: 0 !important;
4992    right: 0 !important;
4993    bottom: 0 !important;
4994    left: 0 !important;
4995    margin: auto !important;
4996    width: 18px !important;
4997    height: 18px !important;
4998  }
4999
5000  :host(.dg-consent-banner) .dg-main-content-explanation {
5001    padding-top: 0 !important;
5002    line-height: 20px !important;
5003  }
5004
5005  :host(.dg-consent-banner) .dg-main-actions {
5006    border-color: transparent !important;
5007  }
5008
5009  :host(.dg-consent-banner) .dg-main-content-policies {
5010    border-top: 1px solid #999 !important;
5011    margin: 0 32px !important;
5012    padding: 0 !important;
5013  }
5014
5015  :host(.dg-consent-banner) .dg-slider.essential-label {
5016    font-style: italic !important;
5017    font-size: 15px !important;
5018  }
5019
5020  :host(.dg-consent-banner) .dg-main-actions button {
5021    text-transform: uppercase !important;
5022    font-size: 15px !important;
5023    font-weight: 500 !important;
5024  }
5025
5026  :host(.dg-consent-banner) .dg-button.essential_only {
5027    display: none !important;
5028    visibility: hidden !important;
5029  }
5030
5031  .dg-main-content-policy-option-description p {
5032    margin-top: 0 !important;
5033  }
5034
5035  .dg-main-content-declaration {
5036    padding: 0 !important;
5037  }
5038
5039  :host(.dg-consent-banner) ._48mA0q_buttonUnstyled {
5040    color: #000000 !important;
5041  }
5042</style>
5043
5044<script>
5045  // Consent bridge — Atlas parity (site-datagrail-style-and-logs.liquid).
5046  // DataGrail calls back with the customer's cookie preferences; we hand
5047  // them to Shopify so its pixels/managed scripts honour the choice.
5048  window.dgEvent = window.dgEvent || [];
5049
5050  function bpSyncReceivePrefs(dgEventData) {
5051    const cookiePreferences =
5052      dgEventData && dgEventData.consentPreferences && dgEventData.consentPreferences.cookieOptions;
5053    // No preferences payload — nothing to sync. Bail rather than
5054    // asserting consent the customer never gave.
5055    if (!cookiePreferences || !cookiePreferences.find) return;
5056
5057    const enabled = (key) => {
5058      const opt = cookiePreferences.find((item) => item && item.gtm_key === key);
5059      return opt ? opt.isEnabled : false;
5060    };
5061
5062    window.Shopify.loadFeatures(
5063      [{ name: 'consent-tracking-api', version: '0.1' }],
5064      (error) => {
5065        if (error) {
5066          console.error('[bp-datagrail] Shopify Customer Privacy API failed to load', error);
5067          return;
5068        }
5069        window.Shopify.customerPrivacy.setTrackingConsent(
5070          {
5071            preferences: true,
5072            analytics: enabled('dg-category-performance'),
5073            marketing: enabled('dg-category-marketing'),
5074            sale_of_data: enabled('dg-category-marketing')
5075          },
5076          (arg) => {
5077            if (window.Shopify && window.Shopify.designMode) {
5078              console.log('[bp-datagrail] consent captured', arg);
5079            }
5080          }
5081        );
5082      }
5083    );
5084  }
5085
5086  window.dgEvent.push({ event: 'preference_callback', params: bpSyncReceivePrefs });
5087</script>
vendor: 1 bytes, line 5087
5087
5088<script>
5089  window.shop = {
5090    url: "https:\/\/www.bostonproper.com",
5091    template: "product",
5092    environment: "production",
5093    theme: (typeof Shopify !== 'undefined' && Shopify.theme) ? Shopify.theme : null,
5094    themeSettings: {
5095      amplience_cdn_base_url: "https:\/\/media.bostonproper.com"
5096    },
5097    br: {
5098      host:        "https:\/\/core.dxpapi.com\/api\/v1\/core\/",
5099      suggestHost: "https:\/\/suggest.dxpapi.com\/api\/v2\/suggest\/",
5100      accountId:   "8261",
5101      domainKey:   "bostonproper",
5102      authKey:     "xv7ok1fkm5gve1ms"
5103    },
5104    badges: {
5105      bestseller: {
5106        enabled: true,
5107        label:   "Best Seller"
5108      },
5109      trending: {
5110        enabled: true,
5111        label:   "Trending"
5112      }
5113    },
5114    methods: {}
5115  };
5116</script>
5116<script>
5117  window.bpColorSiblings = (function () {
5118    // Storefront token: the theme setting wins, but we fall back to the
5119    // known-good public token (recovered from Atlas's live theme.min.js
5120    // and verified against the Storefront API) so the GraphQL path works
5121    // even when config/settings_data.json isn't synced to the theme by
5122    // Shopify's GitHub integration. This is a PUBLIC unauthenticated
5123    // Storefront token — already exposed in Atlas's live JS — so it's
5124    // safe to embed client-side. NB: the older 23797… in Atlas's
5125    // .env.example is a stale placeholder and returns UNAUTHORIZED.
5126    var TOKEN = "04534ca2c4aa793f02c0c735d5d6160c";
5127    var AMPLIENCE = "https:\/\/media.bostonproper.com";
5128    var API_VERSION = '2024-07';
5129
5130    function apiUrl() {
5131      var root = (window.Shopify && Shopify.routes && Shopify.routes.root) ? Shopify.routes.root : '/';
5132      return root + 'api/' + API_VERSION + '/graphql.json';
5133    }
5134
5135    function swatchUrl(style) {
5136      if (!style) return '';
5137      return AMPLIENCE + '/i/bostonproper/' + style + '_2?$poiswatch$&img404=' + style + '_1';
5138    }
5139
5140    /* Batched fetch. handles: array of product handles. Resolves to
5141       { handle: { available, style, swatchUrl, goLiveDate, price, compareAt, discount, promo } | null }.
5142       null = the colour is listed in bp_stylecolorlist but no product
5143       exists at that handle (drop the swatch). Rejects on transport /
5144       API error so callers can fall back to the legacy per-sibling path. */
5145    function fetchSiblings(handles) {
5146      if (!handles || !handles.length) return Promise.resolve({});
5147      if (!TOKEN) return Promise.reject(new Error('bpColorSiblings: no storefront token configured'));
5148      var aliasToHandle = {};
5149      var parts = handles.map(function (h, i) {
5150        var alias = 'p' + i;
5151        aliasToHandle[alias] = h;
5152        return alias + ': product(handle: ' + JSON.stringify(h) + ') {' +
5153          ' availableForSale' +
5154          ' tags' +
5155          ' style: metafield(namespace: "BP_ProductAttributes", key: "bp_style") { value }' +
5156          ' goLive: metafield(namespace: "BP_ProductAttributes", key: "bp_golivedate") { value }' +
5157          ' colorList: metafield(namespace: "BP_ProductAttributes", key: "bp_stylecolorlist") { value }' +
5158          ' promo: metafield(namespace: "discounts", key: "discount_message") { value }' +
5159          ' priceRange { minVariantPrice { amount } }' +
5160          ' compareAtPriceRange { minVariantPrice { amount } }' +
5161          ' }';
5162      });
5163
5164      return fetch(apiUrl(), {
5165        method: 'POST',
5166        headers: {
5167          'Content-Type': 'application/json',
5168          'Accept': 'application/json',
5169          'X-Shopify-Storefront-Access-Token': TOKEN
5170        },
5171        body: JSON.stringify({ query: '{' + parts.join(' ') + '}' })
5172      }).then(function (r) {
5173        if (!r.ok) throw new Error('storefront HTTP ' + r.status);
5174        return r.json();
5175      }).then(function (res) {
5176        var data = res && res.data;
5177        if (!data) throw new Error('storefront: no data');
5178        var out = {};
5179        Object.keys(aliasToHandle).forEach(function (alias) {
5180          var handle = aliasToHandle[alias];
5181          var p = data[alias];
5182          if (!p) { out[handle] = null; return; }
5183          var style = (p.style && p.style.value) ? p.style.value : '';
5184          var price = (p.priceRange && p.priceRange.minVariantPrice) ? parseFloat(p.priceRange.minVariantPrice.amount) : null;
5185          var compareAt = (p.compareAtPriceRange && p.compareAtPriceRange.minVariantPrice) ? parseFloat(p.compareAtPriceRange.minVariantPrice.amount) : null;
5186          var discount = 0;
5187          if (price != null && compareAt != null && compareAt > price) {
5188            discount = Math.round(((compareAt - price) / compareAt) * 100);
5189          }
5190          var tags = Array.isArray(p.tags) ? p.tags : [];
5191          out[handle] = {
5192            available: p.availableForSale === true,
5193            style: style,
5194            swatchUrl: swatchUrl(style),
5195            goLiveDate: (p.goLive && p.goLive.value) ? p.goLive.value : '',
5196            // Sibling's own bp_stylecolorlist — the raw material for the PDP
5197            // swatch block's canonical-family union crawl. Each colour's list
5198            // drifts, so callers UNION them to reconstruct the full family.
5199            colorList: (p.colorList && p.colorList.value) ? p.colorList.value : '',
5200            price: price,
5201            compareAt: compareAt,
5202            discount: discount,
5203            // INV5/INV7 colour-family flag — the swatch row shows only for these
5204            // (matches the PDP + Liquid card gate), so bp-card-hydrate can hide
5205            // lone swatches on non-family products.
5206            isInv: tags.some(function (t) { return /INV5|INV7/i.test(t); }),
5207            // Red sale/promo line (Shopify-native discounts.discount_message,
5208            // same field the PDP + Liquid card read). PLP cards are BR-rendered
5209            // with no promo, so bp-card-hydrate injects it from here.
5210            promo: (p.promo && p.promo.value) ? p.promo.value : ''
5211          };
5212        });
5213        return out;
5214      });
5215    }
5216
5217    /* Group-tag family discovery — the ROBUST family source.
5218
5219       The composed-handle path (fetchSiblings + hydrateRoot's crawl) derives each
5220       sibling's handle as `master + '-' + handleize(colourName)`. That breaks on
5221       BAD DATA where a product's handle token doesn't match its Colour name /
5222       bp_stylecolorlist entry — e.g. 2DO2220 whose handle ends `-black` but whose
5223       Colour option is "Luxe Links" and whose list is "Blue Bell, Luxe Links".
5224       From the blue PDP the composed black handle resolves to `…-luxe-links`
5225       (does NOT exist; the real handle is `…-black`), so the black sibling is
5226       unreachable and the swatch disappears with no way back (Critical 2DO2220).
5227
5228       Every colourway of a family shares a GROUP TAG (`YGroup_*`, also
5229       `INV5_*`/`nvgroup_*`). Querying Storefront by that tag returns the REAL
5230       siblings with their REAL handles + Colour-option names regardless of any
5231       name/handle/list drift — so every colour is reachable from every colourway.
5232
5233       `tag` is the product's ACTUAL YGroup_* tag string, read verbatim from Liquid
5234       (its format is inconsistent across families: `YGroup_2DO22` bare code vs.
5235       `YGroup_2BK45 Marilyn Cowl-Neck Charmeuse Blouse` code+name), so we pass it
5236       through as a search phrase unchanged.
5237
5238       Resolves to { realHandle: { handle, color, available, style, swatchUrl,
5239       goLiveDate, discount, colorList, price, compareAt, promo, isInv } } — the
5240       same shape hydrateRoot's crawl consumes from fetchSiblings, plus `color`
5241       (the Colour option value) so callers can build nameByHandle from REAL
5242       handles instead of composed ones. Rejects on transport/API error so callers
5243       can fall back to the composed-handle crawl. */
5244    function fetchByGroup(tag) {
5245      if (!tag) return Promise.resolve({});
5246      if (!TOKEN) return Promise.reject(new Error('bpColorSiblings: no storefront token configured'));
5247      // Mirror the verified probe: tag:'<value>' phrase match. Escape any single
5248      // quote in the tag value so the search phrase stays well-formed.
5249      var q = "tag:'" + String(tag).replace(/'/g, "\\'") + "'";
5250      // first:100 covers large families (e.g. Marilyn = 24 colourways) in one
5251      // round-trip; families don't approach that ceiling in practice.
5252      var query = 'query($q:String!){products(first:100,query:$q){nodes{' +
5253        ' handle' +
5254        ' availableForSale' +
5255        ' tags' +
5256        ' options(first: 10) { name values }' +
5257        ' style: metafield(namespace: "BP_ProductAttributes", key: "bp_style") { value }' +
5258        ' goLive: metafield(namespace: "BP_ProductAttributes", key: "bp_golivedate") { value }' +
5259        ' colorList: metafield(namespace: "BP_ProductAttributes", key: "bp_stylecolorlist") { value }' +
5260        ' promo: metafield(namespace: "discounts", key: "discount_message") { value }' +
5261        ' priceRange { minVariantPrice { amount } }' +
5262        ' compareAtPriceRange { minVariantPrice { amount } }' +
5263        ' }}}';
5264      return fetch(apiUrl(), {
5265        method: 'POST',
5266        headers: {
5267          'Content-Type': 'application/json',
5268          'Accept': 'application/json',
5269          'X-Shopify-Storefront-Access-Token': TOKEN
5270        },
5271        body: JSON.stringify({ query: query, variables: { q: q } })
5272      }).then(function (r) {
5273        if (!r.ok) throw new Error('storefront HTTP ' + r.status);
5274        return r.json();
5275      }).then(function (res) {
5276        var nodes = res && res.data && res.data.products && res.data.products.nodes;
5277        if (!Array.isArray(nodes)) throw new Error('storefront: no group products');
5278        var out = {};
5279        nodes.forEach(function (p) {
5280          if (!p || !p.handle) return;
5281          var style = (p.style && p.style.value) ? p.style.value : '';
5282          var price = (p.priceRange && p.priceRange.minVariantPrice) ? parseFloat(p.priceRange.minVariantPrice.amount) : null;
5283          var compareAt = (p.compareAtPriceRange && p.compareAtPriceRange.minVariantPrice) ? parseFloat(p.compareAtPriceRange.minVariantPrice.amount) : null;
5284          var discount = 0;
5285          if (price != null && compareAt != null && compareAt > price) {
5286            discount = Math.round(((compareAt - price) / compareAt) * 100);
5287          }
5288          // Colour option value — each sibling is ONE colourway, so its "Color"
5289          // (or "Colour") option carries the single real Colour name. This is the
5290          // authoritative colour label, immune to handle/list drift.
5291          var color = '';
5292          var opts = Array.isArray(p.options) ? p.options : [];
5293          for (var i = 0; i < opts.length; i++) {
5294            var nm = (opts[i] && opts[i].name || '').toLowerCase();
5295            if (nm === 'color' || nm === 'colour') {
5296              color = (opts[i].values && opts[i].values[0]) || '';
5297              break;
5298            }
5299          }
5300          var tags = Array.isArray(p.tags) ? p.tags : [];
5301          out[p.handle] = {
5302            handle: p.handle,
5303            color: color,
5304            available: p.availableForSale === true,
5305            style: style,
5306            swatchUrl: swatchUrl(style),
5307            goLiveDate: (p.goLive && p.goLive.value) ? p.goLive.value : '',
5308            colorList: (p.colorList && p.colorList.value) ? p.colorList.value : '',
5309            price: price,
5310            compareAt: compareAt,
5311            discount: discount,
5312            isInv: tags.some(function (t) { return /INV5|INV7/i.test(t); }),
5313            promo: (p.promo && p.promo.value) ? p.promo.value : ''
5314          };
5315        });
5316        return out;
5317      });
5318    }
5319
5320    /* Batched live-inventory lookup for GA4 item_stock_qty. `variantIds` is an
5321       array of numeric variant ids (from cart.js line.variant_id) or gids.
5322       Resolves to { numericVariantId: quantityAvailable }. Uses the Storefront
5323       `quantityAvailable` field — requires the token's
5324       `unauthenticated_read_product_inventory` scope; if it's missing or the
5325       variant doesn't track inventory, that entry is simply omitted so callers
5326       leave item_stock_qty blank (graceful, never throws). */
5327    function fetchInventory(variantIds) {
5328      var ids = (variantIds || [])
5329        .filter(Boolean)
5330        .map(function (v) {
5331          var s = String(v);
5332          return s.indexOf('gid://') === 0 ? s : 'gid://shopify/ProductVariant/' + s;
5333        });
5334      if (!ids.length || !TOKEN) return Promise.resolve({});
5335      // qty + price + compareAtPrice per variant. price/compareAtPrice feed the
5336      // GA4 sale fields (item_category3 "Sale Price", item_original_price,
5337      // item_sale_discount) on cart events, which have no compare-at in cart.js.
5338      var query = 'query($ids:[ID!]!){nodes(ids:$ids){... on ProductVariant{id quantityAvailable price{amount} compareAtPrice{amount}}}}';
5339      return fetch(apiUrl(), {
5340        method: 'POST',
5341        headers: {
5342          'Content-Type': 'application/json',
5343          'Accept': 'application/json',
5344          'X-Shopify-Storefront-Access-Token': TOKEN
5345        },
5346        body: JSON.stringify({ query: query, variables: { ids: ids } })
5347      }).then(function (r) {
5348        return r.ok ? r.json() : null;
5349      }).then(function (res) {
5350        var out = {};
5351        var nodes = res && res.data && res.data.nodes;
5352        if (Array.isArray(nodes)) {
5353          nodes.forEach(function (n) {
5354            if (n && n.id) {
5355              out[n.id.replace(/^gid:\/\/shopify\/ProductVariant\//, '')] = {
5356                qty:       (n.quantityAvailable != null) ? n.quantityAvailable : null,
5357                price:     (n.price && n.price.amount != null) ? parseFloat(n.price.amount) : null,
5358                compareAt: (n.compareAtPrice && n.compareAtPrice.amount != null) ? parseFloat(n.compareAtPrice.amount) : null
5359              };
5360            }
5361          });
5362        }
5363        return out;
5364      }).catch(function () { return {}; });
5365    }
5366
5367    /* On-demand GA4 track enrichment for BR cards, which carry no variant id /
5368       department / inventory. Accepts a single handle OR an array (batched,
5369       aliased — one request for a whole PLP grid). Resolves to a map
5370       { handle: { variantId, department, quantityAvailable } } so callers fill
5371       item_shopify_variant + item_category + item_stock_qty. Never throws. */
5372    function fetchTrackData(handles) {
5373      var list = (Array.isArray(handles) ? handles : [handles]).filter(Boolean);
5374      // dedupe
5375      list = list.filter(function (h, i) { return list.indexOf(h) === i; });
5376      if (!list.length || !TOKEN) return Promise.resolve({});
5377      var aliasToHandle = {};
5378      var parts = list.map(function (h, i) {
5379        var a = 't' + i;
5380        aliasToHandle[a] = h;
5381        return a + ': product(handle: ' + JSON.stringify(h) + ') {' +
5382          ' variants(first: 1) { nodes { id quantityAvailable selectedOptions { name value } } }' +
5383          ' dept: metafield(namespace: "BP_ProductAttributes", key: "bp_department") { value }' +
5384          ' }';
5385      });
5386      return fetch(apiUrl(), {
5387        method: 'POST',
5388        headers: {
5389          'Content-Type': 'application/json',
5390          'Accept': 'application/json',
5391          'X-Shopify-Storefront-Access-Token': TOKEN
5392        },
5393        body: JSON.stringify({ query: '{' + parts.join(' ') + '}' })
5394      }).then(function (r) {
5395        return r.ok ? r.json() : null;
5396      }).then(function (res) {
5397        var out = {};
5398        var data = res && res.data;
5399        if (data) {
5400          Object.keys(aliasToHandle).forEach(function (a) {
5401            var p = data[a];
5402            if (!p) return;
5403            var v = p.variants && p.variants.nodes && p.variants.nodes[0];
5404            // Colour (option "Color") + size (option "Size") from the first
5405            // variant, so GA4 cards can fill item_category4 (colour) /
5406            // item_category5 (size). Size is the first variant's = the smallest
5407            // (matches the product id), per the GA4 QA.
5408            var so = (v && v.selectedOptions) || [];
5409            var color = '', size = '';
5410            so.forEach(function (o) {
5411              var n = (o && o.name || '').toLowerCase();
5412              if (n === 'color' || n === 'colour') color = o.value;
5413              else if (n === 'size') size = o.value;
5414            });
5415            out[aliasToHandle[a]] = {
5416              variantId: (v && v.id) ? v.id.replace(/^gid:\/\/shopify\/ProductVariant\//, '') : '',
5417              quantityAvailable: (v && v.quantityAvailable != null) ? v.quantityAvailable : null,
5418              department: (p.dept && p.dept.value) || '',
5419              color: color,
5420              size: size
5421            };
5422          });
5423        }
5424        return out;
5425      }).catch(function () { return {}; });
5426    }
5427
5428    /* ── Canonical colour-family hydrator (shared: PDP swatch block + the
5429       quick-add / quick-view drawer) ──────────────────────────────────────
5430       Rebuilds the drift-free colour family for ONE [data-bp-colors] root via
5431       a bounded UNION crawl of every sibling's bp_stylecolorlist, then renders
5432       in canonical bp_style-ascending order. Because no single colour's own
5433       list is authoritative (each drifts), the union is identical on every
5434       colourway — so the swatch set + order never changes as the shopper
5435       switches colour.
5436
5437       Reads ALL its config from the root's own DOM + this module's AMPLIENCE
5438       base, so it works on any root: the PDP (where blocks/bp-color-siblings's
5439       inline script tag calls it) AND the drawer (where the morphed block's
5440       inline script tag NEVER executes — Horizon's morph only re-runs
5441       .shopify-app-block script[src], not theme-block inline scripts — so the
5442       drawer controller invokes this same shared function instead of forking
5443       the logic). See blocks/bp-color-siblings.liquid (PDP) and
5444       sections/bp-quick-drawer.liquid hydrateColorSiblings (drawer) for the two
5445       callers. Idempotent per root element. */
5446    function hydrateRoot(root, opts) {
5447      opts = opts || {};
5448      if (!root || root.__bpColorsHydrated) return;
5449      root.__bpColorsHydrated = true;
5450      var ul = root.querySelector('.bp-colors__swatches');
5451      if (!ul) return;
5452      var labelName = root.querySelector('[data-bp-active-color]');
5453      var activeItem = ul.querySelector('.bp-colors__item.is-active');
5454
5455      var INV5 = root.getAttribute('data-bp-inv5-handle') || '';
5456      var GROUP_TAG = root.getAttribute('data-bp-group-tag') || '';
5457      var CURRENT_HANDLE = root.getAttribute('data-bp-current-handle') || '';
5458      var CURRENT_COLOR = (activeItem && activeItem.getAttribute('data-bp-color-name'))
5459        || (labelName && (labelName.textContent || '').replace(/^\s+|\s+$/g, '')) || '';
5460      var CURRENT_STYLE = (activeItem && activeItem.getAttribute('data-bp-color-style')) || '';
5461      var QV = opts.qv || '';
5462
5463      function handleize(s) {
5464        return String(s || '').toLowerCase().replace(/^\s+|\s+$/g, '')
5465          .replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
5466      }
5467      function composeHandle(name) { return INV5 + '-' + handleize(name); }
5468      function poiswatch(style) {
5469        return AMPLIENCE + '/i/bostonproper/' + style + '_2?$poiswatch$&img404=' + style + '_1';
5470      }
5471      function styleFromImage(src) {
5472        if (!src) return '';
5473        var file = src.split('/').pop().split('?')[0];
5474        var m = file.match(/^([A-Za-z0-9]+)_/);
5475        return m ? m[1] : '';
5476      }
5477      // Parse bp_golivedate robustly across formats so a backend/feed format
5478      // change can't break the go-live window. Handles the current US
5479      // M/D/YYYY, ISO (YYYY-MM-DD / full ISO datetime), and epoch (seconds or
5480      // milliseconds). `new Date()` alone mis-reads epoch-seconds (as ms) and
5481      // is locale-dependent on M/D/YYYY, so we normalize first.
5482      function parseGoLive(v) {
5483        if (v == null || v === '') return null;
5484        var s = String(v).trim();
5485        if (/^\d+$/.test(s)) {
5486          var n = Number(s);
5487          if (!isFinite(n)) return null;
5488          return new Date(n < 1e12 ? n * 1000 : n); // <1e12 → seconds
5489        }
5490        var m = s.match(/^(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})$/); // M/D/YYYY
5491        if (m) return new Date(Number(m[3]), Number(m[1]) - 1, Number(m[2]));
5492        var d = new Date(s); // ISO (YYYY-MM-DD / full ISO) + anything else
5493        return isNaN(d.getTime()) ? null : d;
5494      }
5495      function withinGoLiveWindow(goLiveDate) {
5496        var d = parseGoLive(goLiveDate);
5497        if (!d || isNaN(d.getTime())) return false;
5498        var now = new Date();
5499        if (d > now) return true;
5500        var days = Math.round((now.getTime() - d.getTime()) / 86400000);
5501        return days <= 45;
5502      }
5503      function paintDiscount(item, pct) {
5504        if (pct > 0 && !item.querySelector('[data-bp-color-discount]')) {
5505          var badge = document.createElement('span');
5506          badge.className = 'bp-colors__discount';
5507          badge.dataset.bpColorDiscount = '';
5508          badge.setAttribute('aria-label', pct + '% off');
5509          badge.textContent = '-' + pct + '%';
5510          item.appendChild(badge);
5511        }
5512      }
5513      function wireName(item) {
5514        if (item.dataset.bpNameWired) return;
5515        item.dataset.bpNameWired = '1';
5516        var show = function () { if (labelName && item.dataset.bpColorName) labelName.textContent = item.dataset.bpColorName; };
5517        var reset = function () { if (labelName) labelName.textContent = CURRENT_COLOR; };
5518        item.addEventListener('mouseenter', show);
5519        item.addEventListener('mouseleave', reset);
5520        item.addEventListener('focusin', show);
5521        item.addEventListener('focusout', reset);
5522      }
5523      function swatchOf(item) { return item.querySelector('[data-bp-swatch]'); }
5524      function paintCrop(item, style) {
5525        if (!style) return;
5526        var sw = swatchOf(item);
5527        if (sw && !sw.style.backgroundImage) sw.style.backgroundImage = "url('" + poiswatch(style) + "')";
5528        item.dataset.bpColorStyle = style;
5529      }
5530
5531      var nameByHandle = {};
5532      Array.prototype.forEach.call(ul.querySelectorAll('.bp-colors__item'), function (li) {
5533        var h = li.dataset.bpColorHandle;
5534        if (h && !(h in nameByHandle)) nameByHandle[h] = li.dataset.bpColorName || '';
5535      });
5536      if (CURRENT_HANDLE) nameByHandle[CURRENT_HANDLE] = CURRENT_COLOR;
5537
5538      var fetched = {}; // handle -> info | null (null = no product at that handle)
5539
5540      function unionFromFetched() {
5541        Object.keys(fetched).forEach(function (h) {
5542          var info = fetched[h];
5543          if (info && info.colorList) {
5544            info.colorList.split(',').forEach(function (raw) {
5545              var name = raw.replace(/^\s+|\s+$/g, '');
5546              if (!name) return;
5547              var sh = composeHandle(name);
5548              if (!(sh in nameByHandle)) nameByHandle[sh] = name;
5549            });
5550          }
5551        });
5552      }
5553
5554      /* PRIMARY family source: the group tag. Returns the REAL siblings with
5555         REAL handles + Colour-option names, so nameByHandle is the true family
5556         and every colour is reachable from every colourway — no composed-handle
5557         guessing. We pre-populate `fetched` from the same response (it carries
5558         style/available/goLive/discount/colorList) so render() needs no extra
5559         round-trip, and we DELIBERATELY skip the colorList→composeHandle union
5560         here: on bad-data families (2DO2220) that union would re-introduce the
5561         bogus composed handles this path exists to avoid. Resolves true on
5562         success, false when the group query yields nothing (caller falls back to
5563         the composed-handle crawl). */
5564      function groupCrawl() {
5565        return fetchByGroup(GROUP_TAG).then(function (byHandle) {
5566          var handles = Object.keys(byHandle || {});
5567          if (!handles.length) return false;
5568          handles.forEach(function (h) {
5569            fetched[h] = byHandle[h];
5570            if (byHandle[h] && !(h in nameByHandle)) nameByHandle[h] = byHandle[h].color || '';
5571          });
5572          // Keep the current colourway's server-rendered label to avoid a flash;
5573          // only fill from the group colour when the seed had none.
5574          if (CURRENT_HANDLE) nameByHandle[CURRENT_HANDLE] = CURRENT_COLOR || nameByHandle[CURRENT_HANDLE] || '';
5575          return true;
5576        });
5577      }
5578
5579      function crawl() {
5580        var MAX_ROUNDS = 3;
5581        var round = 0;
5582        function nextBatch() {
5583          var toFetch = Object.keys(nameByHandle).filter(function (h) { return !(h in fetched); });
5584          if (!toFetch.length || round >= MAX_ROUNDS) return Promise.resolve();
5585          round++;
5586          return fetchSiblings(toFetch).then(function (byHandle) {
5587            toFetch.forEach(function (h) { fetched[h] = byHandle[h] || null; });
5588            unionFromFetched();
5589            return nextBatch();
5590          });
5591        }
5592        return nextBatch();
5593      }
5594
5595      function makeItem(handle, name) {
5596        var li = document.createElement('li');
5597        li.className = 'bp-colors__item bp-colors__item--pending';
5598        li.setAttribute('data-bp-color-name', name || '');
5599        li.setAttribute('data-bp-color-handle', handle);
5600        li.setAttribute('data-bp-color-style', '');
5601        var a = document.createElement('a');
5602        a.className = 'bp-colors__swatch';
5603        a.href = '/products/' + handle + QV;
5604        a.setAttribute('data-bp-swatch', '');
5605        a.setAttribute('aria-label', name || '');
5606        li.appendChild(a);
5607        return li;
5608      }
5609
5610      // Reconcile the whole row to canonical order in ONE pass, then reveal.
5611      // Every item stays hidden (--pending) while the crawl runs, so moving
5612      // nodes into sorted position causes NO visible movement; a single reveal
5613      // at the end drops each swatch straight into its final place. Canonical
5614      // order = ascending bp_style code (the merchandised sequence), identical
5615      // on every colourway.
5616      function render() {
5617        var existing = {};
5618        Array.prototype.forEach.call(ul.querySelectorAll('.bp-colors__item'), function (li) {
5619          if (li.dataset.bpColorHandle) existing[li.dataset.bpColorHandle] = li;
5620        });
5621        var entries = Object.keys(nameByHandle).map(function (h) {
5622          var info = fetched[h];
5623          var isCurrent = (h === CURRENT_HANDLE);
5624          var visible;
5625          if (isCurrent) visible = true;
5626          else if (!info) visible = false;
5627          else if (info.available) visible = true;
5628          else visible = withinGoLiveWindow(info.goLiveDate);
5629          var li = existing[h];
5630          var style = (info && info.style) ? info.style
5631            : ((li && li.dataset.bpColorStyle) ? li.dataset.bpColorStyle : (isCurrent ? CURRENT_STYLE : ''));
5632          return { h: h, info: info, isCurrent: isCurrent, visible: visible, style: style || '', li: li };
5633        });
5634        entries.sort(function (a, b) {
5635          if (a.style !== b.style) return a.style < b.style ? -1 : 1;
5636          return a.h < b.h ? -1 : (a.h > b.h ? 1 : 0);
5637        });
5638        entries.forEach(function (e) {
5639          if (e.visible && !e.li) { e.li = makeItem(e.h, nameByHandle[e.h]); existing[e.h] = e.li; }
5640          if (!e.li) return;
5641          if (e.visible) {
5642            paintCrop(e.li, e.style);
5643            if (e.info) paintDiscount(e.li, e.info.discount);
5644            if (!e.isCurrent) wireName(e.li);
5645          } else {
5646            e.li.classList.add('bp-colors__item--pending');
5647          }
5648          ul.appendChild(e.li);
5649        });
5650        entries.forEach(function (e) {
5651          if (e.visible && e.li) e.li.classList.remove('bp-colors__item--pending');
5652        });
5653      }
5654
5655      function paintActive() {
5656        var active = ul.querySelector('.bp-colors__item.is-active');
5657        if (!active) return;
5658        var sw = swatchOf(active);
5659        if (!sw || sw.style.backgroundImage) return;
5660        var info = fetched[CURRENT_HANDLE];
5661        var style = (info && info.style) ? info.style : CURRENT_STYLE;
5662        if (style) { sw.style.backgroundImage = "url('" + poiswatch(style) + "')"; active.dataset.bpColorStyle = style; }
5663      }
5664      function revealActive() {
5665        var active = ul.querySelector('.bp-colors__item.is-active');
5666        if (active) active.classList.remove('bp-colors__item--pending');
5667        paintActive();
5668      }
5669
5670      // Fallback (Storefront token/API unavailable): reveal in-stock seed items
5671      // and paint their crop from /products/{handle}.js filenames. Can't build
5672      // the union without metafields, so it degrades to the seed list only.
5673      function legacyFallback() {
5674        Array.prototype.forEach.call(ul.querySelectorAll('.bp-colors__item:not(.is-active)'), function (item) {
5675          var handle = item.dataset.bpColorHandle;
5676          if (!handle) return;
5677          wireName(item);
5678          var sw = swatchOf(item);
5679          var style = item.dataset.bpColorStyle || '';
5680          fetch('/products/' + handle + '.js', { credentials: 'same-origin' })
5681            .then(function (r) { return r.ok ? r.json() : null; })
5682            .then(function (data) {
5683              if (!data || data.available === false) { item.classList.add('bp-colors__item--pending'); return; }
5684              if (!style && data.featured_image) style = styleFromImage(data.featured_image);
5685              if (!style) { item.classList.add('bp-colors__item--pending'); return; }
5686              if (sw && !sw.style.backgroundImage) { sw.style.backgroundImage = "url('" + poiswatch(style) + "')"; item.dataset.bpColorStyle = style; }
5687              if (data.compare_at_price && data.price && data.compare_at_price > data.price) {
5688                paintDiscount(item, Math.round(((data.compare_at_price - data.price) / data.compare_at_price) * 100));
5689              }
5690              item.classList.remove('bp-colors__item--pending');
5691            })
5692            .catch(function () { item.classList.add('bp-colors__item--pending'); });
5693        });
5694      }
5695
5696      if (TOKEN) {
5697        // Hide EVERY item (incl. the active swatch) up front so the single
5698        // ordered reveal after the crawl has zero visible reflow.
5699        Array.prototype.forEach.call(ul.querySelectorAll('.bp-colors__item'), function (li) {
5700          li.classList.add('bp-colors__item--pending');
5701        });
5702        // Prefer group-tag discovery (drift-proof). Fall back to the composed-
5703        // handle union crawl when there's no group tag or the group query is
5704        // empty/errors, then to the legacy per-sibling .js path.
5705        var primary;
5706        if (GROUP_TAG) {
5707          primary = groupCrawl()
5708            .then(function (ok) { return ok ? true : crawl(); })
5709            .catch(function () { return crawl(); });
5710        } else {
5711          primary = crawl();
5712        }
5713        primary
5714          .then(function () { render(); })
5715          .catch(function () { revealActive(); legacyFallback(); });
5716      } else {
5717        legacyFallback();
5718        paintActive();
5719      }
5720    }
5721
5722    return {
5723      fetch: fetchSiblings,
5724      fetchByGroup: fetchByGroup,
5725      fetchInventory: fetchInventory,
5726      fetchTrackData: fetchTrackData,
5727      swatchUrl: swatchUrl,
5728      hydrateRoot: hydrateRoot,
5729      amplience: AMPLIENCE
5730    };
5731  })();
5732</script>
5732<script>
5733  window.bpColorSwatches = (function () {
5734    var TOKEN = "04534ca2c4aa793f02c0c735d5d6160c";
5735    var API_VERSION = '2024-07';
5736    var CACHE_KEY = 'bp_color_swatches_v1';
5737    var map = {};
5738    var ready = false;
5739
5740    function apiUrl() {
5741      var root = (window.Shopify && Shopify.routes && Shopify.routes.root) ? Shopify.routes.root : '/';
5742      return root + 'api/' + API_VERSION + '/graphql.json';
5743    }
5744    // MUST match bp-bloomreach.js handleize() so facet-value lookups line up:
5745    // lowercase, non-alphanumeric runs -> '-', trim leading/trailing dashes.
5746    function key(name) {
5747      return String(name == null ? '' : name)
5748        .toLowerCase().trim()
5749        .replace(/[^a-z0-9]+/g, '-')
5750        .replace(/^-+|-+$/g, '');
5751    }
5752    function get(name) { return map[key(name)] || ''; }
5753
5754    // 1) hydrate synchronously from cache (removes the first-paint race on
5755    //    every PLP view after the first in a session).
5756    try {
5757      var cached = sessionStorage.getItem(CACHE_KEY);
5758      if (cached) { map = JSON.parse(cached) || {}; ready = true; }
5759    } catch (_) {}
5760
5761    // 2) fetch fresh (paginated) and refresh the cache.
5762    function page(after) {
5763      var q = '{ metaobjects(type: "product_color_swatches", first: 250' +
5764        (after ? ', after: ' + JSON.stringify(after) : '') +
5765        ') { pageInfo { hasNextPage endCursor } edges { node { fields { key value } } } } }';
5766      return fetch(apiUrl(), {
5767        method: 'POST',
5768        headers: {
5769          'Content-Type': 'application/json',
5770          'Accept': 'application/json',
5771          'X-Shopify-Storefront-Access-Token': TOKEN
5772        },
5773        body: JSON.stringify({ query: q })
5774      }).then(function (r) {
5775        if (!r.ok) throw new Error('storefront HTTP ' + r.status);
5776        return r.json();
5777      });
5778    }
5779    function load() {
5780      if (!TOKEN) return;
5781      var acc = {};
5782      function walk(after) {
5783        return page(after).then(function (res) {
5784          var mo = res && res.data && res.data.metaobjects;
5785          if (!mo) return;
5786          (mo.edges || []).forEach(function (e) {
5787            var f = {};
5788            (e.node.fields || []).forEach(function (x) { f[x.key] = x.value; });
5789            // Prefer an optional `css_background` TEXT field (holds a full CSS
5790            // background — a hex OR a linear-gradient for a shimmer), falling
5791            // back to the existing `css_color` Color field (single hex only —
5792            // a Color metafield can't store a gradient). Applied via
5793            // `background:` so either renders. Add a single-line text field
5794            // named `css_background` to the metaobject to enable gradients.
5795            var val = f.css_background || f.css_color;
5796            if (f.name && val) acc[key(f.name)] = val;
5797          });
5798          if (mo.pageInfo && mo.pageInfo.hasNextPage) return walk(mo.pageInfo.endCursor);
5799        });
5800      }
5801      walk(null).then(function () {
5802        if (!Object.keys(acc).length) return; // empty response → keep cache/fallback
5803        map = acc;
5804        ready = true;
5805        try { sessionStorage.setItem(CACHE_KEY, JSON.stringify(acc)); } catch (_) {}
5806        try { window.dispatchEvent(new CustomEvent('bp:color-swatches-ready')); } catch (_) {}
5807      }).catch(function () { /* keep cache; fall back to raw CSS colour names */ });
5808    }
5809    load();
5810
5811    return { get: get, key: key, isReady: function () { return ready; } };
5812  })();
5813</script>
vendor: 1 bytes, line 5813
5813
5814<script type="application/ld+json">
5815{
5816  "@context": "https://schema.org",
5817  "@graph": [
5818    {
5819      "@type": "Organization",
5820      "@id": "https:\/\/www.bostonproper.com\/#organization",
5821      "name": "Boston Proper",
5822      "url": "https:\/\/www.bostonproper.com\/",
5823      "logo": "https:\/\/www.bostonproper.com\/cdn\/shop\/files\/BOS-Logotype-Charcoal_1.png?v=1785187523\u0026width=500",
5824      "description": "Shop women's dresses, statement tops, polished pants, shoes, accessories, and travel-ready styles designed to fit beautifully and own every room. ",
5825      "parentOrganization": {
5826        "@type": "Organization",
5827        "name": "Brentwood Associates"
5828      },
5829      "founder": { "@type": "Person", "name": "Sheryl Clark" },
5830      "foundingDate": "1992",
5831      "sameAs": [
5832        "https:\/\/www.facebook.com\/bostonproper",
5833        "https:\/\/www.instagram.com\/bostonproperofficial\/",
5834        "https:\/\/www.pinterest.com\/bostonproper\/",
5835        "https:\/\/www.youtube.com\/@bostonproper",
5836        "https:\/\/x.com\/bostonproper",
5837        "https:\/\/www.tiktok.com\/@bostonproperofficial",
5838        "https:\/\/www.bostonproper.com\/pages\/about-us"
5839      ],
5840      "contactPoint": [
5841        {
5842          "@type": "ContactPoint",
5843          "telephone": "+1-800-243-4300",
5844          "contactType": "customer service",
5845          "contactOption": "TollFree",
5846          "areaServed": "US",
5847          "availableLanguage": "en"
5848        }
5849      ],
5850      "hasMerchantReturnPolicy": {
5851        "@type": "MerchantReturnPolicy",
5852        "applicableCountry": "US",
5853        "returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
5854        "merchantReturnDays": 30,
5855        "returnMethod": "https://schema.org/ReturnByMail",
5856        "returnFees": "https://schema.org/ReturnShippingFees",
5857        "returnShippingFeesAmount": {
5858          "@type": "MonetaryAmount",
5859          "value": "6.95",
5860          "currency": "USD"
5861        }
5862      }
5863    },
5864    {
5865      "@type": "WebSite",
5866      "@id": "https:\/\/www.bostonproper.com\/#website",
5867      "url": "https:\/\/www.bostonproper.com\/",
5868      "name": "Boston Proper",
5869      "publisher": { "@id": "https:\/\/www.bostonproper.com\/#organization" },
5870      "inLanguage": "en-US",
5871      "potentialAction": {
5872        "@type": "SearchAction",
5873        "target": {
5874          "@type": "EntryPoint",
5875          "urlTemplate": "https://www.bostonproper.com/search?q={search_term_string}"
5876        },
5877        "query-input": "required name=search_term_string"
5878      }
5879    }
5880  ]
5881}
5882</script>
vendor: 1 bytes, line 5882
5882
5883<script>
5884  (function () {
5885    // ----- Customer + order state (Liquid-emitted, no extra fetch) -----
5886    window.__customer_id__   = "";
5887    window.__customer_type__ = "new";
5888    window.__orders_count__  = 0;
5889
5890    // ----- Plain-text PII (Enhanced Conversions / vendor pixels) -----
5891    // Nested-object shape + key names match Atlas's ga4_globals.js.liquid
5892    // (email / phone_number / first_name / last_name / street / city /
5893    // state / zip_code / country) so the GTM-NS3X79G container variables
5894    // resolve.
5895    // Absent fields are emitted as `undefined` (not ''), matching Atlas's
5896    // ga4_globals.js.liquid and __user_hashed_data__ below: a field that
5897    // does not exist should read undefined, never an empty string.
5898    window.__enhanced_conversion_data__ = {
5899      email:        undefined,
5900      phone_number: undefined,
5901      first_name:   undefined,
5902      last_name:    undefined,
5903      street:       undefined,
5904      city:         undefined,
5905      state:        undefined,
5906      zip_code:     undefined,
5907      country:      undefined
5908    };
5909
5910    // ----- SHA-256 hashed PII for GA4 Enhanced Conversions -----
5911    // Hashed SERVER-SIDE via Liquid `| sha256` (exactly like Atlas), so
5912    // it's available SYNCHRONOUSLY at the first event push. The previous
5913    // client-side SubtleCrypto version resolved async, so early events
5914    // (view_item / page_loaded) shipped empty hashes. undefined when
5915    // absent (Atlas parity — never '').
5916    window.__user_hashed_data__ = {
5917      email:        undefined,
5918      phone_number: undefined,
5919      first_name:   undefined,
5920      last_name:    undefined,
5921      street:       undefined,
5922      city:         undefined,
5923      state:        undefined,
5924      zip_code:     undefined,
5925      country:      undefined
5926    };
5927
5928    // ----- user_details (spec: localStorage gtm_user_data backup) -----
5929    // The GA4/GTM analytics team's spec: every event's user_details is
5930    // built from the logged-in customer (Liquid globals above) with the
5931    // checkout-captured localStorage `gtm_user_data` key as a BACKUP for
5932    // guests. Plain text → enhanced_conversion_data; SHA-256(plain) →
5933    // user_hashed_data (hashed client-side here, since the localStorage
5934    // backup has no server-side hashes). Built ONCE and cached in
5935    // window.__bp_user_details__ so per-event pushes stay synchronous;
5936    // bpUserDetailsSync() is the interim shape used before the async
5937    // hashing settles (page_loaded fires at DOMContentLoaded).
5938    //
5939    // Shape follows the spec exactly: user_id is the (future) Peak id,
5940    // null until that integration lands; the Shopify customer id now
5941    // lives on customer_id. NOTE: the GTM-NS3X79G container must be
5942    // remapped to read customer_id for GA4 User-ID (it previously read
5943    // user_id).
5944    function bpGtmUserData() {
5945      try { return JSON.parse(localStorage.getItem('gtm_user_data')) || null; }
5946      catch (_) { return null; }
5947    }
5948
5949    // First non-empty of the args (null/undefined/'' are "empty").
5950    function bpCoalesce() {
5951      for (var i = 0; i < arguments.length; i++) {
5952        var v = arguments[i];
5953        if (v != null && v !== '') return v;
5954      }
5955      return null;
5956    }
5957
5958    function bpUserDetailsSync() {
5959      var ls  = bpGtmUserData() || {};
5960      var ecd = window.__enhanced_conversion_data__ || {};
5961      // gtm_user_data field names → enhanced_conversion_data key names.
5962      var lsm = {
5963        email:        ls.em,   phone_number: ls.ph,   first_name: ls.fn,
5964        last_name:    ls.ln,   street:       ls.street, city:     ls.ct,
5965        state:        ls.st,   zip_code:     ls.zp,   country:    ls.country
5966      };
5967      var loggedIn = !!(window.__customer_id__ && String(window.__customer_id__) !== '');
5968      // Logged-in → Liquid customer is authoritative, localStorage backfills.
5969      // Guest → localStorage (checkout capture) is authoritative.
5970      var primary = loggedIn ? ecd : lsm;
5971      var backup  = loggedIn ? lsm : ecd;
5972      function P(k) { return bpCoalesce(primary[k], backup[k]); }
5973
5974      var ordersCount = loggedIn
5975        ? bpCoalesce(window.__orders_count__, ls.ordersCount)
5976        : bpCoalesce(ls.ordersCount, window.__orders_count__);
5977      if (ordersCount != null) ordersCount = Number(ordersCount);
5978      var customerId = bpCoalesce(window.__customer_id__, ls.userId);
5979
5980      return {
5981        log_state:     customerId ? 'Logged In' : 'Logged Out',
5982        user_id:       null,                       // Peak/Shopify user id — wired later
5983        customer_id:   customerId,
5984        customer_type: (ordersCount != null && ordersCount >= 1) ? 'returning' : 'new',
5985        orders_count:  ordersCount,
5986        is_first_order: ordersCount != null ? (ordersCount < 1) : null,
5987        enhanced_conversion_data: {
5988          email:        P('email'),
5989          phone_number: P('phone_number'),
5990          first_name:   P('first_name'),
5991          last_name:    P('last_name'),
5992          street:       P('street'),
5993          city:         P('city'),
5994          state:        P('state'),
5995          zip_code:     P('zip_code'),
5996          country:      P('country')
5997        },
5998        // Interim: Liquid server-side hashes (logged-in) until the async
5999        // client-side hash of the merged plain text overwrites this.
6000        user_hashed_data: window.__user_hashed_data__ || {}
6001      };
6002    }
6003
6004    // SHA-256 → lowercase hex (spec: trim + lowercase normalization).
6005    function bpSha256(value) {
6006      if (value == null || value === '') return Promise.resolve(null);
6007      try {
6008        var norm = String(value).trim().toLowerCase();
6009        var data = new TextEncoder().encode(norm);
6010        return crypto.subtle.digest('SHA-256', data).then(function (buf) {
6011          var arr = Array.prototype.slice.call(new Uint8Array(buf));
6012          return arr.map(function (b) { return ('0' + b.toString(16)).slice(-2); }).join('');
6013        });
6014      } catch (_) { return Promise.resolve(null); }
6015    }
6016
6017    function bpBuildUserDetails() {
6018      var ud   = bpUserDetailsSync();
6019      var e    = ud.enhanced_conversion_data;
6020      var keys = ['email','phone_number','first_name','last_name','street','city','state','zip_code','country'];
6021      return Promise.all(keys.map(function (k) { return bpSha256(e[k]); }))
6022        .then(function (hashes) {
6023          var hashed = {};
6024          keys.forEach(function (k, i) { hashed[k] = hashes[i]; });
6025          ud.user_hashed_data = hashed;
6026          return ud;
6027        });
6028    }
6029
6030    window.bpUserDetailsSync = bpUserDetailsSync;
6031    window.__bp_user_details__ = null;   // populated async, read synchronously by events
6032    try {
6033      if (window.crypto && window.crypto.subtle && window.TextEncoder) {
6034        bpBuildUserDetails().then(function (ud) { window.__bp_user_details__ = ud; });
6035      }
6036    } catch (_) { /* insecure context / no subtle — sync fallback covers it */ }
6037
6038    // ----- First-touch attribution (session-scoped) -----
6039    // Persists the FIRST page of the user's session so every later
6040    // event can attribute back to landing context. Mirrors Atlas's
6041    // sessionStorage usage in ga4.js.liquid.
6042    try {
6043      var STORAGE_KEY = 'bp_first_touch';
6044      var stored = sessionStorage.getItem(STORAGE_KEY);
6045      if (stored) {
6046        window.__first_touch__ = JSON.parse(stored);
6047      } else {
6048        window.__first_touch__ = {
6049          page:      window.location.pathname,
6050          full_url:  window.location.href,
6051          template:  "product",
6052          referrer:  document.referrer || '',
6053          timestamp: Date.now()
6054        };
6055        sessionStorage.setItem(STORAGE_KEY, JSON.stringify(window.__first_touch__));
6056      }
6057    } catch (_) {
6058      window.__first_touch__ = {
6059        page: window.location.pathname,
6060        template: "product"
6061      };
6062    }
6063
6064    // ----- Global DataLayer config — debug flag + shared shape -----
6065    window.__DL__ = window.__DL__ || {
6066      debug:    false,
6067      cart:     null,    // populated by view_cart / cart change events
6068      lastEvent: null    // last event name pushed (for dedupe / tests)
6069    };
6070
6071    // ----- Ensure dataLayer exists even if GTM hasn't booted yet -----
6072    window.dataLayer = window.dataLayer || [];
6073  })();
6074</script>
vendor: 1 bytes, line 6074
6074
6075<script>window.__pageType__ = "product";</script>
6075<script src="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-track-gtm.js?v=183060181947548063931790713714" defer></script>
6075
6076    
6076<script src="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-track-page.js?v=89286407019962503341790713714" defer></script>
6076
6077    
6077<script src="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-track-cards.js?v=119320205335911998891790713714" defer></script>
6077<script src="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-badges.js?v=45136502598786020341790713714" defer></script>
6077<script src="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-card-hydrate.js?v=169242559010489351881790713714" defer></script>
6077<script src="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-line-item-props.js?v=113126442776160060221790713714" defer></script>
6077<script>
6078  (function () {
6079    'use strict';
6080    if (window.__bpTrackCartWired) return;
6081    window.__bpTrackCartWired = true;
6082
6083    var lastCartSnapshot = null; // for remove diff detection
6084
6085    function snapshotCart(cart) {
6086      if (!cart || !cart.items) return null;
6087      var map = {};
6088      cart.items.forEach(function (line) {
6089        map[String(line.id || line.key)] = {
6090          key:           line.key,
6091          id:            line.id,
6092          variant_id:    line.variant_id || line.id,   // → item_shopify_variant
6093          product_id:    line.product_id,
6094          product_title: line.product_title || line.title,
6095          vendor:        line.vendor,
6096          product_type: line.product_type,
6097          sku:           line.sku,
6098          price:         line.price,
6099          quantity:      line.quantity,
6100          handle:        line.handle,
6101          url:           line.url,
6102          featured_image: line.featured_image,
6103          image:         line.image,
6104          options_with_values: line.options_with_values || []
6105        };
6106      });
6107      return map;
6108    }
6109
6110    function detectRemovedLines(prev, next) {
6111      if (!prev) return [];
6112      var removed = [];
6113      Object.keys(prev).forEach(function (k) {
6114        if (!next || !next[k]) {
6115          removed.push(prev[k]);
6116        } else if (next[k].quantity < prev[k].quantity) {
6117          var line = Object.assign({}, prev[k]);
6118          line.quantity = prev[k].quantity - next[k].quantity;
6119          removed.push(line);
6120        }
6121      });
6122      return removed;
6123    }
6124
6125    function detectAddedLines(prev, next) {
6126      if (!next) return [];
6127      var added = [];
6128      Object.keys(next).forEach(function (k) {
6129        if (!prev || !prev[k]) {
6130          added.push(next[k]);
6131        } else if (next[k].quantity > prev[k].quantity) {
6132          var line = Object.assign({}, next[k]);
6133          line.quantity = next[k].quantity - prev[k].quantity;
6134          added.push(line);
6135        }
6136      });
6137      return added;
6138    }
6139
6140    // Where a cart mutation happened: the /cart page ("Cart") vs the
6141    // slide-out flyout drawer ("Cart Flyout"). Used for in-cart qty
6142    // changes + removals.
6143    function cartMutationLocation() {
6144      // The visible SURFACE wins over the path: if the flyout drawer is open,
6145      // a qty change / removal is "Cart Flyout" even on the /cart page (QA —
6146      // a flyout remove was reporting "Cart" because the path check beat the
6147      // actual surface).
6148      var dlg = document.querySelector('[data-bp-cart-dialog]');
6149      if (dlg && dlg.open) return 'Cart Flyout';
6150      var p = window.location.pathname;
6151      if (p === '/cart' || p.indexOf('/cart?') === 0) return 'Cart';
6152      return 'Cart Flyout';
6153    }
6154
6155    // Where an INITIAL add-to-cart happened. When a Quickview drawer is the
6156    // source, attribute to the SAME surface the view_item used: "Quickview"
6157    // for the PLP quickview, "Cart Quickview" for the cart flyout / cart-page
6158    // upsell (complete-the-look) modal. window.__bpQuickviewLoc is set on open
6159    // by bp-track-cards.js (fireQuickview / bpTrackCartQuickview); reading it
6160    // here — instead of hardcoding "Quickview" — makes the add_to_cart
6161    // event_location/item_list_id/location_id match the view_item, so GA4 can
6162    // compute an Add-to-Cart Rate for Cart Quickview and tell it apart from the
6163    // PLP Quickview (GA4 QA). Falls back to "Quickview" if the surface is
6164    // somehow unset. Otherwise let add_to_cart resolve from the path (PDP).
6165    function initialAddLocation() {
6166      return window.__bpQuickviewActive ? (window.__bpQuickviewLoc || 'Quickview') : undefined;
6167    }
6168
6169    // Normalize a cart-line snapshot into the (variant, product) tuple
6170    // bpTrack.add_to_cart expects, then fire it with the given location.
6171    function fireAddLine(line, location) {
6172      if (!window.bpTrack || !window.bpTrack.add_to_cart) return;
6173      var product = {
6174        id:           line.product_id,
6175        title:        line.product_title,
6176        vendor:       line.vendor,
6177        product_type: line.product_type,
6178        handle:       line.handle,
6179        url:          line.url,
6180        // cart.js gives featured_image as an object; fall back to the
6181        // legacy line.image string. Feeds the Klaviyo Added to Cart
6182        // ImageURL / URL / Categories (GA4 items[] don't read these).
6183        featured_image: (line.featured_image && line.featured_image.url) || line.image || ''
6184      };
6185      var variant = {
6186        id:         line.variant_id || line.id,   // → item_shopify_variant
6187        sku:        line.sku,
6188        price:      line.price,
6189        compare_at_price: null,
6190        // A line in the cart is purchasable → "In Stock". Without this,
6191        // _itemFromProduct defaults undefined-available to "Out of Stock".
6192        available:  true,
6193        option1:    line.options_with_values && line.options_with_values[0] && line.options_with_values[0].value,
6194        option2:    line.options_with_values && line.options_with_values[1] && line.options_with_values[1].value,
6195        product_id: line.product_id
6196      };
6197      window.bpTrack.add_to_cart(variant, product, true, location, line.product_id);
6198    }
6199
6200    // Initial add-to-cart (product:added / cart:update) — diff for ADDED
6201    // lines only and fire add_to_cart with the source-surface location.
6202    function fireAddedToCart(cart, location) {
6203      var next = snapshotCart(cart);
6204      if (lastCartSnapshot) {
6205        detectAddedLines(lastCartSnapshot, next).forEach(function (line) {
6206          fireAddLine(line, location);
6207        });
6208      }
6209      lastCartSnapshot = next;
6210    }
6211
6212    // In-cart mutation (cart:updated from the qty stepper / remove) — diff
6213    // BOTH directions against the SAME prior snapshot so a qty increase
6214    // fires add_to_cart ("Cart Flyout"/"Cart") and a decrease/remove fires
6215    // remove_from_cart. Computed before the snapshot is replaced so the two
6216    // diffs don't race each other.
6217    function fireCartMutation(cart) {
6218      var next = snapshotCart(cart);
6219      var loc = cartMutationLocation();
6220      if (lastCartSnapshot) {
6221        detectRemovedLines(lastCartSnapshot, next).forEach(function (line) {
6222          if (window.bpTrack && window.bpTrack.remove_from_cart) {
6223            window.bpTrack.remove_from_cart(line, loc);
6224          }
6225        });
6226        detectAddedLines(lastCartSnapshot, next).forEach(function (line) {
6227          fireAddLine(line, loc);
6228        });
6229      }
6230      lastCartSnapshot = next;
6231    }
6232
6233    function fireViewCart(location) {
6234      if (window.bpTrack && window.bpTrack.view_cart) {
6235        window.bpTrack.view_cart(location);
6236      }
6237    }
6238
6239    document.addEventListener('DOMContentLoaded', function () {
6240      // Seed snapshot from the initial /cart.js (so the first remove
6241      // detected by the diff has a baseline to compare against).
6242      fetch('/cart.js', { credentials: 'same-origin' })
6243        .then(function (r) { return r.json(); })
6244        .then(function (cart) { lastCartSnapshot = snapshotCart(cart); })
6245        .catch(function () { /* silent */ });
6246
6247      // bp:cart-drawer:opened → view_cart from the flyout ("Cart Flyout").
6248      // NOTE: do NOT clear __bpQuickviewActive here. A Quickview add opens the
6249      // cart drawer, so clearing on drawer-open wiped the "Quickview"
6250      // attribution before the add_to_cart (from product:added) could read it
6251      // — the QA "Quickview ATC reports Site Browse" bug. The quick-add modal's
6252      // own `close` event + the 30s safety timeout (bp-track-cards.js) clear it,
6253      // and later in-cart qty edits use cartMutationLocation(), not this flag.
6254      document.addEventListener('bp:cart-drawer:opened', function () {
6255        fireViewCart('Cart Flyout');
6256      });
6257
6258      // cart:updated comes from bpCartChange (the qty stepper / remove) —
6259      // diff BOTH directions: qty up → add_to_cart, qty down/remove →
6260      // remove_from_cart, both located "Cart"/"Cart Flyout".
6261      document.addEventListener('cart:updated', function (e) {
6262        if (e && e.detail && e.detail.cart) {
6263          fireCartMutation(e.detail.cart);
6264        }
6265      });
6266
6267      // product:added (Horizon / bp-cart-drawer / bp-swym) +
6268      // cart:update (Horizon stock event) — fired on PDP, quick-add,
6269      // wishlist→cart, and any other ATC path. Diff the cart against
6270      // the last snapshot to detect ADDED lines and fire add_to_cart
6271      // for each one. Universal coverage; per-source helpers can fire
6272      // add_to_cart ahead of this if they have richer attribution
6273      // (the GA4 events will deduplicate on event_id at the GTM side
6274      // if that ever becomes an issue).
6275      document.addEventListener('product:added', function (e) {
6276        var loc = initialAddLocation();
6277        if (e && e.detail && e.detail.cart) {
6278          fireAddedToCart(e.detail.cart, loc);
6279        } else {
6280          fetch('/cart.js', { credentials: 'same-origin' })
6281            .then(function (r) { return r.json(); })
6282            .then(function (cart) { fireAddedToCart(cart, loc); })
6283            .catch(function () {});
6284        }
6285      });
6286      document.addEventListener('cart:update', function () {
6287        var loc = initialAddLocation();
6288        fetch('/cart.js', { credentials: 'same-origin' })
6289          .then(function (r) { return r.json(); })
6290          .then(function (cart) { fireAddedToCart(cart, loc); })
6291          .catch(function () {});
6292      });
6293
6294      // On the /cart page load, fire view_cart immediately too ("Cart").
6295      if (window.location.pathname === '/cart' || window.location.pathname.indexOf('/cart?') === 0) {
6296        fireViewCart('Cart');
6297      }
6298    });
6299  })();
6300</script>
vendor: 1 bytes, line 6300
6300
6301<script>
6302    (function () {
6303      'use strict';
6304      window.__bpPdpProduct = {
6305        id:           15286962618534,
6306        title:        "Boston Proper Printed Scarf With Love BP",
6307        vendor:       "Boston Proper",
6308        handle:       "boston-proper-printed-scarf-with-love-bp",
6309        url:          "\/products\/boston-proper-printed-scarf-with-love-bp",
6310        image:        "\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198\u0026width=720",
6311        product_type: null,
6312        metafields: { BP_ProductAttributes: { bp_department: "Promotions" } },
6313        variants: [56389031657638]
6314      };
6315      window.__bpPdpVariant = {
6316        id:                 56389031657638,
6317        sku:                "2CT8071000",
6318        price:              50.0,
6319        compare_at_price:   50.0,
6320        option1:            "With Love BP",
6321        option2:            "One Size",
6322        product_id:         15286962618534,
6323        available:          true,
6324        inventory_quantity: 2617
6325      };
6326
6327      function fireViewItem(variant) {
6328        if (!window.bpTrack || !window.bpTrack.view_item) {
6329          // bpTrack not loaded yet — retry shortly. Defer-loaded JS
6330          // tends to finish parsing on the next macrotask.
6331          setTimeout(function () { fireViewItem(variant); }, 100);
6332          return;
6333        }
6334        window.bpTrack.view_item(variant || window.__bpPdpVariant, window.__bpPdpProduct, 'Product Detail');
6335      }
6336
6337      // Initial PDP view.
6338      if (document.readyState === 'loading') {
6339        document.addEventListener('DOMContentLoaded', function () { fireViewItem(); }, { once: true });
6340      } else {
6341        fireViewItem();
6342      }
6343
6344      // Re-fire on variant change. Horizon dispatches `variant:update`
6345      // on the document with detail.variant when the user picks a size
6346      // or color; size_change / color_change are fired off the same hook.
6347      document.addEventListener('variant:update', function (e) {
6348        var v = (e && e.detail && e.detail.variant) || null;
6349        if (!v) return;
6350        var nextVariant = {
6351          id:                 v.id,
6352          sku:                v.sku || '',
6353          price:              (v.price || 0) / 100,
6354          compare_at_price:   v.compare_at_price ? v.compare_at_price / 100 : null,
6355          option1:            v.option1 || '',
6356          option2:            v.option2 || '',
6357          product_id:         window.__bpPdpProduct.id,
6358          available:          v.available,
6359          inventory_quantity: (v.inventory_quantity != null ? v.inventory_quantity : null)
6360        };
6361        // Fire micro-events for option change.
6362        var colorChanged = nextVariant.option1 && nextVariant.option1 !== window.__bpPdpVariant.option1;
6363        if (window.bpTrack) {
6364          if (colorChanged) {
6365            window.bpTrack.color_change && window.bpTrack.color_change(nextVariant.option1, 'Product Detail');
6366          }
6367          // NOTE: size_change is deliberately NOT fired from this hook. It
6368          // assumed Size == option2 (fragile — some products have Size as
6369          // option1), and in current Horizon the variant rides on
6370          // detail.resource, not detail.variant. Size is tracked by the
6371          // dedicated, option-NAME based `change` listener in the GLOBAL
6372          // snippets/bp-track-size.liquid (so it also covers the flyout).
6373        }
6374        window.__bpPdpVariant = nextVariant;
6375        // Spec: re-fire view_item ONLY on color-swatch change, not on size.
6376        if (colorChanged) fireViewItem(nextVariant);
6377      });
6378
6379
6380      // BP colour swatches are CROSS-PRODUCT — each colourway is a separate
6381      // Shopify product, so picking a colour is an in-place product swap
6382      // handled by bp-pdp-swap.liquid, NOT a Horizon `variant:update` (that
6383      // hook only fires for size within one product). The swap dispatches
6384      // `bp:pdp:swapped` with the new handle; this listener is why the
6385      // colour-change view_item was never firing (QA — "not implemented").
6386      // Refresh the PDP globals from the new product and re-fire view_item.
6387      // Spec: colour change re-fires view_item; size change does not.
6388      document.addEventListener('bp:pdp:swapped', function (e) {
6389        var handle = e && e.detail && e.detail.handle;
6390        if (!handle) return;
6391        fetch('/products/' + handle + '.js', { headers: { Accept: 'application/json' } })
6392          .then(function (r) { return r.ok ? r.json() : null; })
6393          .then(function (pj) {
6394            if (!pj) return;
6395            var variants = pj.variants || [];
6396            // Prefer the variant matching the size the shopper had selected
6397            // (the swap re-applies it); else the first available variant.
6398            var prevSize = window.__bpPdpVariant && window.__bpPdpVariant.option2;
6399            var v = null, i;
6400            if (prevSize) {
6401              for (i = 0; i < variants.length; i += 1) {
6402                if (variants[i].option2 === prevSize && variants[i].available) { v = variants[i]; break; }
6403              }
6404            }
6405            if (!v) { for (i = 0; i < variants.length; i += 1) { if (variants[i].available) { v = variants[i]; break; } } }
6406            if (!v) v = variants[0] || {};
6407            // Colourways share a style → same bp_department; carry the
6408            // category metafield forward (not in /products/{handle}.js).
6409            var mf = (window.__bpPdpProduct && window.__bpPdpProduct.metafields) ||
6410                     { BP_ProductAttributes: { bp_department: '' } };
6411            window.__bpPdpProduct = {
6412              id:           pj.id,
6413              title:        pj.title,
6414              vendor:       pj.vendor || 'Boston Proper',
6415              handle:       pj.handle,
6416              url:          '/products/' + pj.handle,
6417              // Keep ImageURL populated on the colour-swap Viewed Product event.
6418              image:        (v.featured_image && v.featured_image.src) || pj.featured_image || (pj.images && pj.images[0]) || '',
6419              product_type: pj.type || '',
6420              metafields:   mf,
6421              variants:     variants.map(function (x) { return x.id; })
6422            };
6423            window.__bpPdpVariant = {
6424              id:                 v.id,
6425              sku:                v.sku || '',
6426              price:              (v.price || 0) / 100,      // .js prices are cents
6427              compare_at_price:   v.compare_at_price ? v.compare_at_price / 100 : null,
6428              option1:            v.option1 || '',
6429              option2:            v.option2 || '',
6430              product_id:         pj.id,
6431              available:          v.available,
6432              // /products/{handle}.js omits inventory_quantity → item_stock_qty
6433              // may be blank on the colour-swap event (accepted limitation).
6434              inventory_quantity: (v.inventory_quantity != null ? v.inventory_quantity : null)
6435            };
6436            fireViewItem(window.__bpPdpVariant);
6437          })
6438          .catch(function () { /* best-effort — never break the colour swap */ });
6439      });
6440    })();
6441  </script>
6441<script>
6442  (function () {
6443    var suppressUntil = 0; // colour-swap synthetic re-select window (ms epoch)
6444
6445    // Resolve the option's display name for a picker control.
6446    function sizeOptionName(el) {
6447      var fs = el.closest ? el.closest('fieldset') : null;
6448      if (fs) {
6449        var pfx = fs.querySelector('.variant-option__swatch-prefix') || fs.querySelector('legend');
6450        if (pfx) return (pfx.textContent || '').trim();
6451      }
6452      var nm = el.getAttribute ? el.getAttribute('name') : '';
6453      var m = nm && nm.match(/options\[(.+?)\]/);
6454      if (m) return m[1];
6455      if (el.id) {
6456        var lbl = document.querySelector('label[for="' + el.id + '"]');
6457        if (lbl) return (lbl.textContent || '').trim();
6458      }
6459      return '';
6460    }
6461
6462    document.addEventListener('change', function (e) {
6463      var el = e.target;
6464      if (!el || !el.closest) return;
6465      var picker = el.closest('variant-picker');
6466      if (!picker) return;                                 // only variant pickers
6467      if (el.tagName !== 'SELECT' && el.type !== 'radio') return;
6468      if (el.type === 'radio' && !el.checked) return;
6469      if (!/size/i.test(sizeOptionName(el))) return;        // SIZE option only
6470      var val = el.value;
6471      if (!val) return;
6472      // Colour-swap synthetic re-select → baseline it, don't report it.
6473      if (Date.now() < suppressUntil) { picker.__bpSize = val; return; }
6474      if (val === picker.__bpSize) return;                  // per-picker dedup / no-op
6475      picker.__bpSize = val;
6476      if (window.bpTrack && window.bpTrack.size_change) {
6477        window.bpTrack.size_change(val);                    // location auto (page type)
6478      }
6479    }, true);
6480
6481    // A colour swap re-selects the shopper's size on the swapped-in product via
6482    // SYNTHETIC change events — suppress briefly so it isn't a "size change".
6483    document.addEventListener('bp:pdp:swapped', function () {
6484      suppressUntil = Date.now() + 500;
6485    });
6486  })();
6487</script>
vendor: 1 bytes, line 6487
6487
6488<script>
6489  (function () {
6490    'use strict';
6491    if (window.__bpTrackWishlistWired) return;
6492    window.__bpTrackWishlistWired = true;
6493
6494    function fire(eventName, line) {
6495      if (!window.bpTrack || !window.bpTrack[eventName] || !line) return;
6496
6497      // `line` is the `cartItemData` object dispatched by every save path
6498      // (bp-swym-helpers handleSaveForLater + the two PDP heart blocks). Its
6499      // field names are NOT the cart-line names the old code read
6500      // (product_id / sku / price / compare_at_price / options_with_values —
6501      // none of which exist here, which is why item_id / value / color / size /
6502      // stock / both Shopify ids all came back empty). The real shape is:
6503      //   id                       → Shopify PARENT (product) id
6504      //   variant_id               → Shopify VARIANT id
6505      //   variant_sku              → full SKU (drives item_id inv7 / item_variant / item_parent_id inv5)
6506      //   variant_price            → selling price (cents; _itemFromProduct /100s it)
6507      //   variant_compare_at_price → original / compare-at price
6508      //   variant_title            → "Color / Size" (option1 / option2)
6509      var price   = parseFloat(line.variant_price);
6510      var compare = parseFloat(line.variant_compare_at_price);
6511      // variant_title is "<Color> / <Size>" (BP option1 / option2) — split so
6512      // item_category4 (Color) + item_category5 (Size) populate.
6513      var opts  = String(line.variant_title || '').split(' / ');
6514      var color = (opts[0] || '').trim();
6515      var size  = (opts[1] || '').trim();
6516
6517      var product = {
6518        id:     line.id,                                     // → item_shopify_id (parent product id)
6519        title:  line.title,
6520        handle: line.handle,
6521        url:    line.handle ? '/products/' + line.handle : '',
6522        metafields: { BP_ProductAttributes: { bp_department: '' } },
6523        selected_variant: {
6524          id:               line.variant_id,                 // → item_shopify_variant (variant id)
6525          sku:              line.variant_sku || '',          // → item_id (inv7) / item_variant / item_parent_id (inv5)
6526          price:            isNaN(price)   ? 0    : price,    // → price + event_details.value (selling price)
6527          compare_at_price: isNaN(compare) ? null : compare, // → item_original_price when > selling price
6528          option1:          color || null,                   // → item_category4 (Color)
6529          option2:          size  || null,                   // → item_category5 (Size)
6530          // A saved variant is a real, purchasable variant → "In Stock" (same
6531          // as cart-sourced events); _pushWithInventory fills item_stock_qty
6532          // from the live Storefront lookup.
6533          available:        true,
6534          product_id:       line.id
6535        }
6536      };
6537      // eventLocation omitted on purpose — the helper resolves the Page Type
6538      // from the path (Product Detail / Site Browse / Homepage / Cart / …),
6539      // the same event_location scheme every other BP event uses.
6540      window.bpTrack[eventName](product);
6541    }
6542
6543    document.addEventListener('wishlist:item-saved', function (e) {
6544      var line = e && e.detail && e.detail.item;
6545      fire('add_to_wishlist', line);
6546    });
6547
6548    document.addEventListener('wishlist:item-removed', function (e) {
6549      var line = e && e.detail && e.detail.item;
6550      fire('remove_from_wishlist', line);
6551    });
6552  })();
6553</script>
vendor: 1 bytes, line 6553
6553
6554<script>
6555  (function () {
6556    'use strict';
6557    if (window.__bpTrackAccountWired) return;
6558    window.__bpTrackAccountWired = true;
6559
6560    function isLoginForm(form) {
6561      var action = form.getAttribute('action') || '';
6562      var inner = form.querySelector('input[name="customer[email]"]');
6563      var pwd   = form.querySelector('input[name="customer[password]"]');
6564      return /\/account\/login/.test(action) && inner && pwd;
6565    }
6566
6567    function isRegisterForm(form) {
6568      var action = form.getAttribute('action') || '';
6569      var first  = form.querySelector('input[name="customer[first_name]"]');
6570      var email  = form.querySelector('input[name="customer[email]"]');
6571      var pwd    = form.querySelector('input[name="customer[password]"]');
6572      return /\/account/.test(action) && !!first && !!email && !!pwd;
6573    }
6574
6575    function isNewsletterForm(form) {
6576      var action = form.getAttribute('action') || '';
6577      var typeAttr = form.getAttribute('id') || '';
6578      var contact = form.querySelector('input[name="form_type"][value="customer"], input[name="contact[tags]"]');
6579      return /\/contact/.test(action) && !!contact;
6580    }
6581
6582    document.addEventListener('submit', function (e) {
6583      var form = e.target;
6584      if (!(form instanceof HTMLFormElement)) return;
6585
6586      try {
6587        if (isLoginForm(form)) {
6588          // Atlas's flag pattern — bp-track-page.js reads + fires
6589          // bpTrack.login() on the next pageview.
6590          localStorage.setItem('login_GA4', 'true');
6591        }
6592        if (isRegisterForm(form)) {
6593          // Fire sign_up immediately — Shopify-customer flow
6594          // typically posts and stays on the same response page
6595          // when registration succeeds (no GET redirect).
6596          if (window.bpTrack && window.bpTrack.sign_up) {
6597            window.bpTrack.sign_up('email');
6598          }
6599        }
6600        if (isNewsletterForm(form)) {
6601          // Legacy Atlas-shape event (no GA4 standard counterpart)
6602          // for marketing's existing GTM tags.
6603          window.dataLayer = window.dataLayer || [];
6604          window.dataLayer.push({ event: 'Newsletter Subscription' });
6605          // Also fire GA4 sign_up with method='newsletter' for the
6606          // standard ecommerce stream.
6607          if (window.bpTrack && window.bpTrack.sign_up) {
6608            window.bpTrack.sign_up('newsletter');
6609          }
6610        }
6611      } catch (_) { /* analytics never blocks form submit */ }
6612    }, true);
6613  })();
6614</script>
vendor: 1 bytes, line 6614
6614
6615<script>
6616  (function () {
6617    'use strict';
6618
6619    const LOCAL_STORAGE_KEY = 'save-for-later-items';
6620    const AMPLIENCE_BASE =
6621      (window.shop && window.shop.themeSettings && window.shop.themeSettings.amplience_cdn_base_url) ||
6622      "https:\/\/media.bostonproper.com";
6623
6624    // ---------- Customer / wishlist id ----------
6625    function getCustomerId() {
6626      try {
6627        return (window.ShopifyAnalytics &&
6628                window.ShopifyAnalytics.meta &&
6629                window.ShopifyAnalytics.meta.page &&
6630                window.ShopifyAnalytics.meta.page.customerId) || 'guest';
6631      } catch (_) {
6632        return 'guest';
6633      }
6634    }
6635
6636    // ---------- Storage layer: in-memory cache + localStorage mirror ----------
6637    //
6638    // The wishlist needs to keep working even when localStorage is full
6639    // (third-party apps on this domain — Klaviyo, Yotpo cache,
6640    // BlackCrow, GTM dataLayer — routinely fill the 5MB per-origin
6641    // budget). The in-memory cache becomes the source of truth for the
6642    // session; localStorage is a write-through mirror so the state
6643    // survives a reload when it can fit.
6644    //
6645    // The Swym server-side wishlist is the cross-session source of
6646    // truth — checkWishlistSync() pulls from there on `wishlistloaded`
6647    // and seeds both layers, so an in-memory-only session is recovered
6648    // on the next visit.
6649
6650    let memoryState = null;          // { [customerId]: { items, count } }
6651    let lsAvailable = true;          // false after a quota failure this session
6652    const MAX_ITEMS_PER_CUSTOMER = 50;
6653
6654    function readLocalStorageRaw() {
6655      try {
6656        const raw = window.localStorage.getItem(LOCAL_STORAGE_KEY);
6657        return raw ? JSON.parse(raw) : null;
6658      } catch (_) { return null; }
6659    }
6660
6661    function isQuotaError(err) {
6662      if (!err) return false;
6663      return err.name === 'QuotaExceededError' ||
6664             err.code === 22 ||
6665             err.code === 1014 ||
6666             /quota/i.test(String(err.message || err));
6667    }
6668
6669    function tryWrite(data) {
6670      try {
6671        window.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(data));
6672        return null;
6673      } catch (e) { return e; }
6674    }
6675
6676    // Diagnostic — when localStorage is full, name the offender so we
6677    // can target a fix in a follow-up (clear the right vendor cache,
6678    // ask the app to roll over, etc.). Logged once per session.
6679    let quotaDiagLogged = false;
6680    function logQuotaDiagnostics() {
6681      if (quotaDiagLogged) return;
6682      quotaDiagLogged = true;
6683      try {
6684        const sizes = [];
6685        for (let i = 0; i < window.localStorage.length; i++) {
6686          const k = window.localStorage.key(i);
6687          const v = window.localStorage.getItem(k) || '';
6688          sizes.push({ key: k, kb: Math.round((k.length + v.length) / 1024) });
6689        }
6690        sizes.sort((a, b) => b.kb - a.kb);
6691        const top = sizes.slice(0, 5).map((s) => `${s.key} (${s.kb}KB)`).join(', ');
6692        console.warn('[bp-swym] localStorage full. Top 5 keys: ' + top);
6693      } catch (_) {}
6694    }
6695
6696    function getSavedItemsLocalStorage() {
6697      // Memory wins when present (set by any successful seed / write).
6698      if (memoryState) return JSON.parse(JSON.stringify(memoryState));
6699      const fromLs = readLocalStorageRaw();
6700      if (fromLs) memoryState = JSON.parse(JSON.stringify(fromLs));
6701      return fromLs;
6702    }
6703
6704    // Cascade of size-reduction strategies. Each step mutates `data`
6705    // in-place and returns the most recent write error (or null on success).
6706    //   1. Try as-is.
6707    //   2. Drop `image` from every saved item (largest field — a CDN
6708    //      URL adds 100-300 bytes per row; the saved drawer can
6709    //      re-derive the image from the product handle on demand).
6710    //   3. Cap each customer's items at MAX_ITEMS_PER_CUSTOMER, oldest
6711    //      first.
6712    //   4. Drop the orphan "guest" bucket when a logged-in customerId
6713    //      bucket also exists (after-login carryover).
6714    function storeSavedItemsLocalStorage(data) {
6715      if (!data) return;
6716
6717      // Memory state ALWAYS updates — that's the in-session source of
6718      // truth so the drawer, bubble, and PDP heart always reflect the
6719      // latest save, even when localStorage rejects the write.
6720      memoryState = JSON.parse(JSON.stringify(data));
6721
6722      let err = null;
6723      if (lsAvailable) {
6724        err = tryWrite(data);
6725
6726        if (err && isQuotaError(err)) {
6727          // Strategy 2 — strip images.
6728          Object.keys(data).forEach((cid) => {
6729            const items = (data[cid] && data[cid].items) || [];
6730            items.forEach((it) => { delete it.image; });
6731          });
6732          err = tryWrite(data);
6733        }
6734
6735        if (err && isQuotaError(err)) {
6736          // Strategy 3 — cap item count.
6737          Object.keys(data).forEach((cid) => {
6738            const bucket = data[cid] || {};
6739            const items = bucket.items || [];
6740            if (items.length > MAX_ITEMS_PER_CUSTOMER) {
6741              bucket.items = items.slice(items.length - MAX_ITEMS_PER_CUSTOMER);
6742              bucket.count = bucket.items.length;
6743              data[cid] = bucket;
6744            }
6745          });
6746          err = tryWrite(data);
6747        }
6748
6749        if (err && isQuotaError(err)) {
6750          // Strategy 4 — drop the orphan "guest" bucket if a real
6751          // customerId bucket exists.
6752          const keys = Object.keys(data);
6753          if (keys.length > 1 && data.guest) {
6754            delete data.guest;
6755            err = tryWrite(data);
6756          }
6757        }
6758      }
6759
6760      if (err) {
6761        if (isQuotaError(err)) {
6762          lsAvailable = false;
6763          logQuotaDiagnostics();
6764        } else {
6765          console.warn('[bp-swym] storage write failed', err);
6766        }
6767        // Fall through — fire the change events anyway so UI updates
6768        // from the memory state.
6769      }
6770
6771      // ALWAYS dispatch — memory has the new state. Without this,
6772      // saving an item when localStorage is full leaves the drawer +
6773      // bubble stale (the user thinks the click didn't register).
6774      document.dispatchEvent(new CustomEvent('wishlist:updated', { detail: { wishlist: memoryState } }));
6775      document.dispatchEvent(new CustomEvent('bp:saved:updated'));
6776    }
6777    function getLocalWishlist() {
6778      const all = getSavedItemsLocalStorage();
6779      const customerId = getCustomerId();
6780      return (all && all[customerId]) || { items: [], count: 0 };
6781    }
6782
6783    // ---------- Cart helpers (Atlas's updateCart + updateCartElements) ----------
6784    async function updateCart(payload, action) {
6785      const map = { UPDATE: 'cart/update.js', CHANGE: 'cart/change.js', ADD: 'cart/add.js', REMOVE: 'cart/remove.js' };
6786      const endpoint = map[action];
6787      if (!endpoint) throw new Error('updateCart: unknown action ' + action);
6788      const root = (window.Shopify && window.Shopify.routes && window.Shopify.routes.root) || '/';
6789      const res = await fetch(root + endpoint, {
6790        method: 'POST',
6791        headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
6792        body: JSON.stringify(payload),
6793        credentials: 'same-origin'
6794      });
6795      if (!res.ok) {
6796        // Shopify returns a JSON body on 4xx with the actual reason
6797        // ("You can only add N of that item...", "The product is sold
6798        // out", etc.). Surface it — a bare "HTTP 422" tells the shopper
6799        // and the next dev nothing, and Move-to-Bag now shows this.
6800        let description = '';
6801        try {
6802          const body = await res.json();
6803          description = body.description || body.message || '';
6804        } catch (_) { /* non-JSON error body */ }
6805        const err = new Error(action + ' HTTP ' + res.status + (description ? ': ' + description : ''));
6806        err.status = res.status;
6807        err.description = description;
6808        throw err;
6809      }
6810      return res.json();
6811    }
6812    function updateCartElements(cart) {
6813      document.dispatchEvent(new CustomEvent('cart:change', { detail: { cart } }));
6814      document.dispatchEvent(new CustomEvent('cart:updated', { detail: { cart } })); // BP drawer listens here
6815      document.dispatchEvent(new CustomEvent('product:added', { detail: { cart } }));
6816    }
6817
6818    // ---------- Swym proxy fetch ----------
6819    async function getWishlist() {
6820      if (typeof window.SWGetExpressWishlistId !== 'function') return null;
6821      const wishlistId = window.SWGetExpressWishlistId();
6822      if (wishlistId === 0 || wishlistId == null) return null;
6823      const customerId = getCustomerId();
6824      const path = customerId && customerId !== 'guest'
6825        ? `/a/wishlist?type=api&customerid=${encodeURIComponent(customerId)}&version=1`
6826        : `/a/wishlist?type=api&wishlistid=${encodeURIComponent(wishlistId)}&version=1`;
6827      try {
6828        const res = await fetch(path, { credentials: 'same-origin' });
6829        if (!res.ok) return null;
6830        return await res.json();
6831      } catch (e) {
6832        console.warn('[bp-swym] proxy fetch failed', e);
6833        return null;
6834      }
6835    }
6836
6837    // ---------- Save the cart line to wishlist ----------
6838    // Mirror of Atlas's handleSaveForLater(e, product) — `product` is
6839    // the cart line item (BP cart drawer passes a structured object).
6840    async function handleSaveForLater(e, product) {
6841      if (e && typeof e.preventDefault === 'function') e.preventDefault();
6842      if (!product) return;
6843
6844      const customerId = getCustomerId();
6845      const isCollectiveProduct =
6846        Array.isArray(product.tags) &&
6847        (product.tags.indexOf('Shopify Collective') >= 0 || product.tags.indexOf('Collective') >= 0);
6848
6849      // Snapshot matches Atlas's cartItemData shape verbatim.
6850      const sku = (product.sku || product.variant_sku || '').toString();
6851      const skuPrefix = sku.slice(0, 7);
6852      const cartItemData = {
6853        id: (product.product_id != null ? product.product_id : product.id) + '',
6854        handle: product.handle || '',
6855        variant_price: (product.variant_price != null
6856          ? product.variant_price
6857          : (product.variant && product.variant.price)) + '',
6858        variant_compare_at_price: (product.variant_compare_at_price != null
6859          ? product.variant_compare_at_price
6860          : (product.variant && product.variant.compareAtPrice)) + '',
6861        variant_title: (product.variant_title
6862          || (product.variant && product.variant.title)
6863          || '') + '',
6864        variant_id: (product.variant_id != null
6865          ? product.variant_id
6866          : (product.variant && product.variant.id)) + '',
6867        title: product.title || '',
6868        image:
6869          isCollectiveProduct || !skuPrefix
6870            ? (product.image || '')
6871            : `${AMPLIENCE_BASE}/s/bostonproper/${skuPrefix}_SET/1?fmt=auto&w=484`,
6872        quantity: ((product.quantity != null ? product.quantity : 1) + ''),
6873        variant_sku: sku,
6874        // Client save timestamp — the saved drawer sorts newest-first by this,
6875        // so a fresh save stays on top regardless of the mirror/Swym array
6876        // order (QA 7/27, Dragana: item landed at the bottom in-session).
6877        savedAt: Date.now()
6878      };
6879
6880      const lineKey = product.line_key || product.key || (e && e.target && (function () {
6881        const li = e.target.closest('[data-bp-cart-line], [data-line-key], .cart-item');
6882        return li && (li.dataset.lineKey || li.getAttribute('data-line-key'));
6883      })());
6884
6885      // 1) Add to Swym (silent if app not loaded).
6886      try {
6887        if (typeof window.AddToSmartWishlist === 'function') {
6888          window.AddToSmartWishlist(cartItemData.id, cartItemData.variant_id);
6889        }
6890      } catch (err) { console.warn('[bp-swym] AddToSmartWishlist failed', err); }
6891
6892      // 2) Remove from cart.
6893      let cart = null;
6894      if (lineKey) {
6895        try {
6896          cart = await updateCart({ id: lineKey, quantity: 0 }, 'CHANGE');
6897          updateCartElements(cart);
6898        } catch (err) { console.warn('[bp-swym] cart change failed', err); }
6899      }
6900
6901      // 3) Update local mirror.
6902      const all = getSavedItemsLocalStorage() || {};
6903      const current = all[customerId] || { items: [], count: 0 };
6904      // Prepend (newest first) so the optimistic in-session order matches the
6905      // order after reload (the saved list renders newest-first). Appending put
6906      // a fresh save at the BOTTOM in-session but the TOP after refresh
6907      // (QA 7/22, Dragana).
6908      const nextItems = [cartItemData].concat(
6909        current.items.filter((it) => it.variant_id !== cartItemData.variant_id)
6910      );
6911      all[customerId] = { ...current, items: nextItems, count: nextItems.length };
6912      storeSavedItemsLocalStorage(all);
6913      // Record the authoritative newest-first order (Swym-proof).
6914      stampSavedOrder(cartItemData.variant_id);
6915
6916      document.dispatchEvent(new CustomEvent('wishlist:item-saved', { detail: { item: cartItemData } }));
6917      return cart;
6918    }
6919
6920    // ---------- Remove from Swym + local mirror ----------
6921    function removeWishlistItem(productId, variantId) {
6922      const customerId = getCustomerId();
6923      const all = getSavedItemsLocalStorage() || {};
6924      const current = all[customerId] || { items: [], count: 0 };
6925      const removed = current.items.find((it) => String(it.variant_id) === String(variantId)) || null;
6926      const nextItems = current.items.filter((it) => String(it.variant_id) !== String(variantId));
6927      all[customerId] = { ...current, items: nextItems, count: nextItems.length };
6928      storeSavedItemsLocalStorage(all);
6929      clearSavedOrder(variantId);
6930
6931      try {
6932        if (typeof window.RemoveFromSmartWishlist === 'function') {
6933          window.RemoveFromSmartWishlist(productId, variantId);
6934        }
6935      } catch (err) { console.warn('[bp-swym] RemoveFromSmartWishlist failed', err); }
6936
6937      // Dispatched so analytics (bp-track-wishlist) can fire GA4
6938      // remove_from_wishlist. Detail carries the removed cart-line-
6939      // shaped object so the listener has enough to build the
6940      // GA4 items[] entry.
6941      if (removed) {
6942        document.dispatchEvent(new CustomEvent('wishlist:item-removed', { detail: { item: removed } }));
6943      }
6944    }
6945
6946    // ---------- Build BP Line Item Properties for Move-to-Bag ----------
6947    // Port of Atlas's updateLineItemProperties() — preserves the LIPs
6948    // BP uses on every cart line so they survive the save/restore.
6949    function updateLineItemProperties(variant, inventoryAvailable) {
6950      const props = {};
6951      try {
6952        const attrs = (variant && variant.BP_ProductAttributes) || {};
6953        // Atlas reads both spellings (updateLineItemProperties.js:41-45);
6954        // existing ERP values aren't being converted, so a product
6955        // written at either spelling has to keep working.
6956        const catalogId = attrs.BP_CurrentEventID || attrs.bp_currenteventid;
6957        if (catalogId) props._catalog_id = catalogId;
6958        const priceStatus = attrs.BP_PriceStatus || attrs.bp_pricestatus;
6959        if (priceStatus) props._price_status = priceStatus;
6960
6961        const hasFinalSale = attrs.has_final_sale === 'yes';
6962        if (hasFinalSale) props._final_sale = 'yes';
6963
6964        // Pre-order date. Match the value union Atlas accepts rather
6965        // than case-sensitive 'T' — Atlas's React paths lower-case
6966        // first (ProductMain.js:67), so variants stored as "t"/"true"/
6967        // "yes"/"1" are live pre-orders today and must stay that way.
6968        const rawPreorder = variant && variant.bp_preorder
6969          ? (variant.bp_preorder.value !== undefined ? variant.bp_preorder.value : variant.bp_preorder)
6970          : '';
6971        const isPreorder = rawPreorder === true ||
6972          ['t', 'true', 'yes', '1'].includes(String(rawPreorder).toLowerCase().trim());
6973        const rawShipDate = variant && variant.expectedShipDate_Inbound && variant.expectedShipDate_Inbound[0]
6974          ? variant.expectedShipDate_Inbound[0].value
6975          : (variant && variant.expectedShipDate && variant.expectedShipDate.value);
6976        if (isPreorder && rawShipDate) {
6977          // No +13 offset — Atlas shows the raw DC-arrival date with only
6978          // weekend/holiday skipping applied (dateHelpers.skipWeekendsHol);
6979          // the earlier +13 here made a restored-from-save item's LIP ~2
6980          // weeks later than the cart's live recompute. Prefer the shared
6981          // window.bpPreorder helper (the Atlas-verbatim port used by the
6982          // PDP + cart) so all surfaces agree; fall back to a local
6983          // weekend-skip if it hasn't loaded.
6984          try {
6985            let formatted = null;
6986            if (window.bpPreorder && window.bpPreorder.formatDate) {
6987              formatted = window.bpPreorder.formatDate(rawShipDate);
6988            } else {
6989              const d = new Date(rawShipDate);
6990              if (!isNaN(d.getTime()) && d >= new Date()) {
6991                const day = d.getDay();
6992                if (day === 6) d.setDate(d.getDate() + 2);
6993                else if (day === 0) d.setDate(d.getDate() + 1);
6994                formatted = d.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: '2-digit' });
6995              }
6996            }
6997            if (formatted) props._expected_ship_date = formatted;
6998          } catch (_) {}
6999        }
7000      } catch (e) { console.warn('[bp-swym] LIP build failed', e); }
7001      return props;
7002    }
7003
7004    // ---------- Move saved item back to the cart ----------
7005    // Throws if the line could not be added. Callers MUST let that
7006    // propagate to the UI: the saved entry is the only record of the
7007    // item, so a swallowed failure loses it (see the ordering note
7008    // below).
7009    async function handleMoveToBag(id, variantId, quantity, isWishlistItemProductLevel, item, variant) {
7010      // Fetch master product to validate inventory + carry BP attrs.
7011      let inventoryAvailable = 0;
7012      let resolvedVariant = variant || {};
7013      // The id we actually post to /cart/add.js. Starts as the saved
7014      // variant_id but is replaced by the resolved variant below —
7015      // a product-level save (isWishlistItemProductLevel: variant_id
7016      // === product_id, no variant ever chosen) stores a PRODUCT id
7017      // here, and /cart/add.js 422s on those every time.
7018      let addVariantId = variantId;
7019      try {
7020        if (item && item.handle) {
7021          const res = await fetch(`/products/${item.handle}.js`, { credentials: 'same-origin' });
7022          if (res.ok) {
7023            const product = await res.json();
7024            const variants = product.variants || [];
7025            // Exact variant first; otherwise fall back to a sellable
7026            // one (product-level saves, or a variant retired since it
7027            // was saved). Prefer `available` over variants[0] so we
7028            // don't resolve straight onto a sold-out variant.
7029            let v = variants.find((vv) => String(vv.id) === String(variantId));
7030            if (!v) v = variants.find((vv) => vv.available) || variants[0];
7031            if (v) {
7032              addVariantId = v.id;
7033              inventoryAvailable = (v.inventory_quantity != null) ? v.inventory_quantity : 0;
7034              resolvedVariant = { ...v, ...resolvedVariant };
7035              // BP_ProductAttributes (Atlas pulls from getMasterProduct's colorProduct.BP_ProductAttributes)
7036              const tags = product.tags || [];
7037              const hasFinalSale = tags.some((t) => String(t).toLowerCase().trim() === 'final sale');
7038              resolvedVariant.BP_ProductAttributes = Object.assign(
7039                {},
7040                resolvedVariant.BP_ProductAttributes || {},
7041                { has_final_sale: hasFinalSale ? 'yes' : 'no' }
7042              );
7043            }
7044          }
7045        }
7046      } catch (err) { /* non-fatal — push to cart with the saved id */ }
7047
7048      let properties = updateLineItemProperties(resolvedVariant, inventoryAvailable) || {};
7049      // The metafield-derived LIPs (_catalog_id, _price_status, _final_sale,
7050      // _compare_at_price, _price) can't be computed client-side — they aren't
7051      // on the /products/<handle>.js variant JSON. Pull them from the canonical
7052      // ?view=lips endpoint so Move-to-Bag carries the SAME LIPs as add-to-cart
7053      // (QA 7/16 — they were missing). Then the saved line's own stored
7054      // properties win, preserving whatever LIP state it had when saved.
7055      if (window.bpLips && item && item.handle) {
7056        try {
7057          const canonical = await window.bpLips.forVariant(item.handle, addVariantId);
7058          if (canonical) properties = Object.assign({}, canonical, properties);
7059        } catch (_) { /* keep the computed set */ }
7060      }
7061      if (item && item.properties && Object.keys(item.properties).length) {
7062        properties = Object.assign(properties, item.properties);
7063      }
7064      const itemToAdd = {
7065        id: addVariantId,
7066        quantity: quantity != null ? quantity : 1
7067      };
7068      if (Object.keys(properties).length) itemToAdd.properties = properties;
7069
7070      // Add FIRST, and let a failure throw.
7071      //
7072      // This used to remove from the wishlist optimistically and then
7073      // swallow any add error in a console.warn. That combination is
7074      // unrecoverable data loss rather than a cosmetic bug: the saved
7075      // entry is the item's only record, so any 422 (sold out, retired
7076      // variant, product-level id) silently destroyed it — the item
7077      // vanished from Saved for Later and never reached the cart. There
7078      // is nothing to be optimistic about here; the wishlist row costs
7079      // nothing to keep for the extra round trip.
7080      const cart = await updateCart({ items: [itemToAdd] }, 'ADD');
7081      updateCartElements(cart);
7082
7083      // Only now that the line is really in the cart is it safe to drop
7084      // the save. Remove by the SAVED variantId (what the local mirror
7085      // and Swym are keyed on), not the resolved addVariantId — those
7086      // differ for product-level saves.
7087      if (isWishlistItemProductLevel) removeWishlistItem(id, id);
7088      else removeWishlistItem(id, variantId);
7089
7090      document.dispatchEvent(new CustomEvent('wishlist:item-saved'));
7091      return cart;
7092    }
7093
7094    // ---------- Sync local mirror with Swym ----------
7095    // Readiness signal for consumers (the saved drawer): flips true the first
7096    // time checkWishlistSync reconciles against a real Swym response. Lets the
7097    // drawer WAIT for Swym and show a loading state instead of rendering
7098    // localStorage first and flashing when Swym replaces it. If Swym never
7099    // responds the consumer falls back to localStorage on its own timeout.
7100    let swymSynced = false;
7101    function isSynced() { return swymSynced; }
7102    function markSynced() {
7103      if (swymSynced) return;
7104      swymSynced = true;
7105      document.dispatchEvent(new CustomEvent('bp:saved:synced'));
7106    }
7107
7108    async function checkWishlistSync() {
7109      const local = getLocalWishlist();
7110      let remote = null;
7111      try { remote = await getWishlist(); } catch (_) { remote = null; }
7112      if (!remote) return; // Swym not ready yet — a later `wishlistloaded` retries.
7113      const customerId = getCustomerId();
7114      const all = getSavedItemsLocalStorage() || {};
7115      // If counts differ, remote is the source of truth — EXCEPT when the
7116      // remote reads empty while local has items. Swym's API returns count 0
7117      // before it finishes hydrating the customer's wishlist, and treating that
7118      // as truth overwrote the local mirror with nothing: the saved drawer
7119      // showed the items on open, then blanked to "empty" and stayed empty until
7120      // a reopen re-synced. Keep local in that case (a genuine cross-device
7121      // clear is far rarer than this hydration race, and local edits already
7122      // update the mirror directly).
7123      if ((remote.count || 0) === 0 && (local.count || 0) > 0) {
7124        all[customerId] = local;
7125        storeSavedItemsLocalStorage(all);
7126        markSynced();
7127        return;
7128      }
7129      if ((remote.count || 0) !== (local.count || 0)) {
7130        // Carry the client save timestamps over from the local mirror so a
7131        // freshly-saved item keeps sorting to the top even after the server
7132        // (whose item order lags/varies) becomes source of truth — otherwise
7133        // the sort key is lost and the item drops down the list (QA 7/27).
7134        const localByVariant = {};
7135        (local.items || []).forEach((it) => { if (it && it.savedAt) localByVariant[String(it.variant_id)] = it.savedAt; });
7136        const remoteItems = (remote.items || []).map((it) => {
7137          const ts = localByVariant[String(it.variant_id)];
7138          return (ts && !it.savedAt) ? Object.assign({}, it, { savedAt: ts }) : it;
7139        });
7140        all[customerId] = Object.assign({}, remote, { items: remoteItems });
7141        storeSavedItemsLocalStorage(all);
7142      } else {
7143        // Counts match — keep the merged shape so newly-saved local
7144        // items remain even if Swym has caught up.
7145        all[customerId] = local;
7146        storeSavedItemsLocalStorage(all);
7147      }
7148      markSynced();
7149    }
7150
7151    // ---------- Swym ready bridge (Atlas: wishlist-load-event.js) ----------
7152    const WishlistLoadedEvent = new Event('wishlistloaded');
7153    window.SWCallbackWishlistButtonLoaded = function () {
7154      window.dispatchEvent(WishlistLoadedEvent);
7155    };
7156    // When Swym is ready, sync. Also try once after DOM ready in case
7157    // Swym already loaded.
7158    window.addEventListener('wishlistloaded', checkWishlistSync);
7159    document.addEventListener('DOMContentLoaded', () => {
7160      // Defer a tick so other listeners attach first.
7161      setTimeout(checkWishlistSync, 50);
7162    });
7163
7164    // ---------- Cross-context cache invalidation ----------
7165    // getLocalWishlist prefers the in-memory `memoryState` over localStorage
7166    // for speed. When ANOTHER same-origin document writes the shared key —
7167    // e.g. a save made inside the Publitas digital-catalog quickview iframe —
7168    // THIS window's memoryState is stale, so the saved drawer + top-nav count
7169    // didn't update until a reload (QA 7/27, Dragana). Re-seed memoryState from
7170    // localStorage so consumers read the fresh state.
7171    function reloadFromStorage() {
7172      const fresh = readLocalStorageRaw();
7173      if (fresh) memoryState = fresh;
7174      return fresh;
7175    }
7176    // A localStorage write in a different same-origin document (the quickview
7177    // iframe) fires `storage` HERE (never in the writing document). Re-seed and
7178    // notify the drawer / bubble to re-render live.
7179    window.addEventListener('storage', (e) => {
7180      if (!e || e.key !== LOCAL_STORAGE_KEY) return;
7181      reloadFromStorage();
7182      document.dispatchEvent(new CustomEvent('bp:saved:updated'));
7183      document.dispatchEvent(new CustomEvent('wishlist:updated'));
7184    });
7185
7186    // ---------- Save-order map (Swym-proof newest-first ordering) ----------
7187    // Per-item `savedAt` isn't reliable for "newest on top": Swym's async sync
7188    // rewrites the item objects (dropping our timestamp) and reorders them, so
7189    // a fresh save kept landing at the bottom. Keep an authoritative
7190    // variant_id → timestamp map in a SEPARATE localStorage key Swym never
7191    // manages; the saved drawer sorts by it. Survives every Swym sync/reorder.
7192    const ORDER_KEY = 'bp.saved_order';
7193    function getSavedOrder() {
7194      try { return JSON.parse(window.localStorage.getItem(ORDER_KEY) || '{}') || {}; }
7195      catch (_) { return {}; }
7196    }
7197    function stampSavedOrder(variantId) {
7198      if (variantId == null || variantId === '') return;
7199      try {
7200        const m = getSavedOrder();
7201        m[String(variantId)] = Date.now();
7202        window.localStorage.setItem(ORDER_KEY, JSON.stringify(m));
7203      } catch (_) { /* storage full — ordering falls back to savedAt */ }
7204    }
7205    function clearSavedOrder(variantId) {
7206      try {
7207        const m = getSavedOrder();
7208        if (delete m[String(variantId)]) window.localStorage.setItem(ORDER_KEY, JSON.stringify(m));
7209      } catch (_) {}
7210    }
7211
7212    // ---------- Expose globals (Atlas parity) ----------
7213    window.bpSavedForLater = {
7214      LOCAL_STORAGE_KEY: LOCAL_STORAGE_KEY,
7215      getSavedItemsLocalStorage: getSavedItemsLocalStorage,
7216      storeSavedItemsLocalStorage: storeSavedItemsLocalStorage,
7217      getLocalWishlist: getLocalWishlist,
7218      getWishlist: getWishlist,
7219      removeWishlistItem: removeWishlistItem,
7220      updateLineItemProperties: updateLineItemProperties,
7221      checkWishlistSync: checkWishlistSync,
7222      isSynced: isSynced,
7223      reloadFromStorage: reloadFromStorage,
7224      getCustomerId: getCustomerId,
7225      getSavedOrder: getSavedOrder,
7226      stampSavedOrder: stampSavedOrder,
7227      clearSavedOrder: clearSavedOrder
7228    };
7229    window.handleSaveForLater = handleSaveForLater;
7230    window.handleMoveToBag = handleMoveToBag;
7231  })();
7232</script>
vendor: 1 bytes, line 7232
7232
7233<script
7234    src="https://cdn-widgetsrepository.yotpo.com/v1/loader/l9OjGj5YqKVR9PFonEHJc4ms9HXq9RV8dOWnI8LL?languageCode=en"
7235    async
7236  ></script>
7236<script>
7237(function () {
7238  if (window.__bpYotpoStarsQvNav) return;
7239  window.__bpYotpoStarsQvNav = true;
7240
7241  var MODAL_SEL = 'dialog.quick-add-modal, .quick-add-modal, #quick-add-modal-content, .quick-add-modal__content';
7242  var DEBUG = false; // flip via window.bpYotpoQvNavDebug = true
7243  function log() {
7244    if (!DEBUG && !window.bpYotpoQvNavDebug) return;
7245    var args = ['[bp-yotpo-qv-nav]'].concat(Array.prototype.slice.call(arguments));
7246    console.log.apply(console, args);
7247  }
7248
7249  function navigateFromHost(host, e) {
7250    var url = host.getAttribute('data-bp-product-url');
7251    if (!url) {
7252      log('no data-bp-product-url on host', host);
7253      return false;
7254    }
7255    if (e) {
7256      e.preventDefault();
7257      e.stopPropagation();
7258      if (e.stopImmediatePropagation) e.stopImmediatePropagation();
7259    }
7260    log('navigating →', url + '#bp-pdp-reviews');
7261    window.location.href = url + '#bp-pdp-reviews';
7262    return true;
7263  }
7264
7265  // 1) Document-level delegated fallback (capture phase). Handles the
7266  //    case where Yotpo's own handlers haven't yet stopped propagation.
7267  ['pointerdown', 'mousedown', 'click'].forEach(function (evt) {
7268    document.addEventListener(evt, function (e) {
7269      var host = e.target.closest && e.target.closest('.bp-yotpo-stars');
7270      if (!host) return;
7271      if (!host.closest(MODAL_SEL)) return;
7272      if (evt === 'click') navigateFromHost(host, e);
7273    }, true);
7274  });
7275
7276  // 2) Direct-attach listener on any `.bp-yotpo-stars` that shows up
7277  //    inside the drawer — belt-and-suspenders in case Yotpo's Vue
7278  //    stops propagation before it reaches document. A MutationObserver
7279  //    watches the whole drawer subtree; when the widget hydrates it
7280  //    also gets the same click handler.
7281  function wireDrawerStars(root) {
7282    root.querySelectorAll('.bp-yotpo-stars').forEach(function (host) {
7283      if (host.__bpYotpoQvWired) return;
7284      host.__bpYotpoQvWired = true;
7285      host.style.cursor = 'pointer';
7286      host.addEventListener('click', function (e) { navigateFromHost(host, e); }, true);
7287      // Yotpo's own summary sometimes eats the click — also listen on
7288      // pointerdown/mousedown which fire earlier in the event sequence.
7289      host.addEventListener('mousedown', function () { log('mousedown on stars'); }, true);
7290      log('wired stars host', host);
7291    });
7292  }
7293
7294  function observeAll() {
7295    document.querySelectorAll(MODAL_SEL).forEach(function (drawer) {
7296      if (drawer.__bpYotpoQvObserved) return;
7297      drawer.__bpYotpoQvObserved = true;
7298      wireDrawerStars(drawer);
7299      var mo = new MutationObserver(function () { wireDrawerStars(drawer); });
7300      mo.observe(drawer, { childList: true, subtree: true });
7301      log('observing drawer', drawer);
7302    });
7303  }
7304
7305  if (document.readyState === 'loading') {
7306    document.addEventListener('DOMContentLoaded', observeAll);
7307  } else {
7308    observeAll();
7309  }
7310  // Drawers might mount after initial load — watch the body for the
7311  // dialog itself appearing.
7312  new MutationObserver(observeAll).observe(document.documentElement, { childList: true, subtree: true });
7313})();
7314</script>
vendor: 1 bytes, line 7314
7314
7315<script>
7316  !function(){if(!window.klaviyo){window._klOnsite=window._klOnsite||[];try{window.klaviyo=new Proxy({},{get:function(n,i){return"push"===i?function(){var n;(n=window._klOnsite).push.apply(n,arguments)}:function(){for(var n=arguments.length,o=new Array(n),w=0;w<n;w++)o[w]=arguments[w];var t="function"==typeof o[o.length-1]?o.pop():void 0,e=new Promise((function(n){window._klOnsite.push([i].concat(o,[function(i){t&&t(i),n(i)}]))}));return e}}})}catch(n){window.klaviyo=window.klaviyo||[],window.klaviyo.push=function(){var n;(n=window._klOnsite).push.apply(n,arguments)}}}}();
7317</script>
7317<script>
7318    (function () {
7319      'use strict';
7320      var ACCOUNT = "\/account";
7321      var HASH = '#k-hub';
7322
7323      function hubHref(href) {
7324        href = String(href || '');
7325        if (href.indexOf(HASH) !== -1) return href;
7326        return href.split('#')[0] + HASH;
7327      }
7328
7329      // Open the hub WITHOUT navigating. Klaviyo's onsite runtime opens
7330      // Customer Hub by intercepting clicks on `#k-hub` anchors (it calls
7331      // preventDefault, so the page never navigates). A programmatic
7332      // `location.assign('/account#k-hub')` is NOT a click, so Klaviyo
7333      // can't intercept it — the browser really does load /account (a
7334      // "not found" under the new customer-accounts setup) and only then
7335      // does the hub open on the hash. Instead, synthesize a real click
7336      // on a bare `#k-hub` anchor: Klaviyo's delegated handler catches it
7337      // and slides the hub in place. If the hub isn't Live, a bare
7338      // `#k-hub` just sets the current-page hash — no navigation, no
7339      // not-found page (unlike the old /account#k-hub assign).
7340      function openHub() {
7341        var a = document.createElement('a');
7342        a.setAttribute('href', HASH);
7343        a.setAttribute('aria-hidden', 'true');
7344        a.style.cssText = 'position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);';
7345        (document.body || document.documentElement).appendChild(a);
7346        a.click();
7347        setTimeout(function () { if (a.parentNode) a.parentNode.removeChild(a); }, 0);
7348      }
7349
7350      // Rewrite standalone account anchors (mobile nav, footer, etc.) —
7351      // the same rewrite Klaviyo does automatically on standard themes.
7352      function rewriteAnchors() {
7353        var links = document.querySelectorAll(
7354          'a[href="' + ACCOUNT + '"], a[href^="' + ACCOUNT + '?"], a[href$="/account"], a[href*="/account?"]'
7355        );
7356        for (var i = 0; i < links.length; i++) {
7357          var a = links[i];
7358          if (a.__kHub || a.hasAttribute('data-k-hub-ignore')) continue;
7359          a.setAttribute('href', hubHref(a.getAttribute('href')));
7360          a.__kHub = 1;
7361        }
7362      }
7363
7364      // The desktop header account control is a <shopify-account> web
7365      // component with no plain /account anchor for Klaviyo to rewrite.
7366      // Intercept clicks on it (capture phase, so we beat the component's
7367      // own navigation handler) and open the hub in place via openHub().
7368      // When Customer Hub is Live, Klaviyo slides the hub in; otherwise
7369      // the bare `#k-hub` hash is a no-op — the icon simply does nothing
7370      // rather than navigating to a not-found account page.
7371      document.addEventListener('click', function (e) {
7372        var scope = e.target.closest && e.target.closest('shopify-account, .account-button');
7373        if (!scope || scope.hasAttribute('data-k-hub-ignore')) return;
7374        // If the click is already on a #k-hub anchor, let it through.
7375        var a = e.target.closest('a[href]');
7376        if (a && a.getAttribute('href').indexOf(HASH) !== -1) return;
7377        e.preventDefault();
7378        e.stopPropagation();
7379        openHub();
7380      }, true);
7381
7382      // Rewrite now and again as Horizon hydrates / injects account links
7383      // (short-lived — the anchors settle early).
7384      rewriteAnchors();
7385      var runs = 0;
7386      var timer = setInterval(function () {
7387        rewriteAnchors();
7388        if (++runs >= 6) clearInterval(timer); // ~3s of catch-up
7389      }, 500);
7390      window.addEventListener('load', rewriteAnchors);
7391    })();
7392  </script>
7392<script>
7393  /* BP Stylitics outfit provider — sources outfits from the Composer SDK's
7394     single /api/orchestrator call instead of a second /api/outfits request.
7395     Loaded on product templates only (see theme.liquid), so the fetch wrap
7396     below is PDP-scoped. Public API:
7397       window.bpStyliticsOutfits(style) -> Promise<Array>  (always resolves)
7398       window.bpRegisterStyliticsTrigger(style, fn)         (How-To-Wear-It)
7399       window.bpPublishStyliticsOutfits(style, outfits)     (manual publish) */
7400  (function () {
7401    if (window.bpStyliticsOutfits) return;
7402    var store = {};     // item_number -> outfits array (from the orchestrator response)
7403    var waiters = {};   // item_number -> [resolve, ...]
7404    var net = {};       // item_number -> fallback /api/outfits promise
7405    var triggers = {};  // item_number -> fn that forces the Composer to init
7406
7407    function norm(s) { return String(s == null ? '' : s).trim(); }
7408
7409    // Publish the outfit array captured from the Composer's orchestrator call.
7410    function publish(style, outfits) {
7411      style = norm(style);
7412      if (!style || !Array.isArray(outfits)) return;
7413      store[style] = outfits;
7414      var w = waiters[style] || [];
7415      waiters[style] = [];
7416      w.forEach(function (fn) { try { fn(outfits); } catch (e) {} });
7417    }
7418    window.bpPublishStyliticsOutfits = publish;
7419
7420    // Let How-To-Wear-It register a way to force its (lazy) Composer to init,
7421    // so a consumer that needs outfits before the section scrolls into view
7422    // (Complete-the-look) still resolves from the single orchestrator call
7423    // instead of firing its own fetch.
7424    window.bpRegisterStyliticsTrigger = function (style, fn) {
7425      style = norm(style);
7426      if (style && typeof fn === 'function') triggers[style] = fn;
7427    };
7428
7429    // Capture the Composer SDK's orchestrator response (its single outfits call)
7430    // and publish outfits per item_number. Wrapping fetch is the most robust
7431    // hook — it reads the actual API response (stable modules[].data.outfits
7432    // shape), not SDK internals; it only acts on orchestrator URLs and always
7433    // returns the original promise, so it composes with other fetch wrappers.
7434    if (!window.__bpStyliticsFetchHooked && window.fetch) {
7435      window.__bpStyliticsFetchHooked = true;
7436      var origFetch = window.fetch;
7437      window.fetch = function (input) {
7438        var url = '';
7439        try { url = typeof input === 'string' ? input : (input && input.url) || ''; } catch (e) {}
7440        var p = origFetch.apply(this, arguments);
7441        if (url && url.indexOf('widget-api.stylitics.com/api/orchestrator') !== -1) {
7442          p.then(function (res) { return res && res.clone ? res.clone().json() : null; })
7443            .then(function (data) {
7444              try {
7445                var u = new URL(url);
7446                var cfg = JSON.parse(u.searchParams.get('config') || '{}');
7447                var mods = (data && data.modules) || [];
7448                (cfg.modules || []).forEach(function (m, i) {
7449                  var style = norm(m && (m.item_number || (m.params && m.params.item_number)));
7450                  var outfits = mods[i] && mods[i].data && mods[i].data.outfits;
7451                  if (style && Array.isArray(outfits)) publish(style, outfits);
7452                });
7453              } catch (e) {}
7454            })
7455            .catch(function () {});
7456        }
7457        return p;
7458      };
7459    }
7460
7461    // Fallback: a direct /api/outfits fetch, used ONLY when the Composer never
7462    // produces data for this style (section absent / SDK failed). In that case
7463    // no orchestrator call was made either, so it is still a single request.
7464    function fallback(style) {
7465      if (net[style]) return net[style];
7466      var url = 'https://widget-api.stylitics.com/api/outfits?username=bostonproper&item_number=' +
7467        encodeURIComponent(style);
7468      net[style] = fetch(url, { cache: 'force-cache' })
7469        .then(function (r) { return r.ok ? r.json() : []; })
7470        .then(function (d) { return Array.isArray(d) ? d : []; })
7471        .catch(function () { delete net[style]; return []; });
7472      return net[style];
7473    }
7474
7475    // Resolve outfits for a style. Prefers the Composer's captured orchestrator
7476    // data (no extra request); forces the Composer to init when a trigger is
7477    // registered; falls back to a single /api/outfits fetch only if the Composer
7478    // never yields data within the wait window.
7479    window.bpStyliticsOutfits = function (style, opts) {
7480      style = norm(style);
7481      if (!style) return Promise.resolve([]);
7482      if (store[style]) return Promise.resolve(store[style]);
7483      var waitMs = (opts && opts.waitMs) || 6000;
7484      if (triggers[style]) { try { triggers[style](); } catch (e) {} }
7485      return new Promise(function (resolve) {
7486        var settled = false;
7487        var done = function (v) { if (!settled) { settled = true; resolve(v); } };
7488        (waiters[style] = waiters[style] || []).push(done);
7489        setTimeout(function () { if (!settled) fallback(style).then(done); }, waitMs);
7490      });
7491    };
7492  })();
7493</script>
7493
7494
7495<link
7496  rel="stylesheet"
7497  href="https://web-assets.stylitics.com/v3-classic/latest/classic.css"
7498  media="print"
7499  onload="this.media='all'"
7500>
7501<script
7502  src="//web-assets.stylitics.com/v3-classic/latest/classic.release.js"
7503  async
7504></script>
vendor: 1 bytes, line 7504
7504
7505<script
7506  src="https://web-assets.stylitics.com/loader/latest/composer.js"
7507  async
7508></script>
7508
7509
7510  
7510<script>
7511    (function (r, e, o) {
7512      var w = window,
7513        d = document,
7514        t,
7515        s,
7516        x;
7517      w.tfcapi = t =
7518        w.tfcapi ||
7519        function () {
7520          t.q = t.q || [];
7521          t.q.push(arguments);
7522        };
7523      t('init', { storeKey: r, environment: e, ...o });
7524      x = d.getElementsByTagName('script')[0];
7525      s = d.createElement('script');
7526      s.type = 'text/javascript';
7527      s.async = true;
7528      s.crossorigin = 'anonymous';
7529      s.src = 'https://cdn.truefitcorp.com/fitrec/global/js/tf-integration.js?storeKey=' + r;
7530      x.parentNode.insertBefore(s, x);
7531      // Don't change anything above this line
7532    })("bog", "prod");
7533
7534    if (window.Shopify && Shopify.designMode) {
7535      document.addEventListener('DOMContentLoaded', () => {
7536        new MutationObserver(() => tfcapi('calculate')).observe(document.body, {
7537          childList: true,
7538          subtree: true,
7539        });
7540      });
7541    }
7542
7543    // Stamp `attributes[_tfcToken]` on every cart-add for True Fit
7544    // purchase attribution. Verbatim port of Atlas's
7545    // observeCartChanges() block (layout/theme.liquid:185-224).
7546    // Without this, True Fit can't match purchases back to size
7547    // recommendations — their merchant dashboard shows incomplete
7548    // accuracy + ROI data.
7549    function observeCartChanges() {
7550      const cartObserver = new PerformanceObserver((list) => {
7551        list.getEntries().forEach((entry) => {
7552          const isValidRequestType = ['xmlhttprequest', 'fetch'].includes(entry.initiatorType);
7553          const isCartChangeRequest = /\/cart\/add/.test(entry.name);
7554          if (isValidRequestType && isCartChangeRequest) {
7555            tfcapi('getToken', async (token) => {
7556              if (!token) {
7557                // Atlas also fires an "emptyTfcToken" diagnostic ping
7558                // here to setup.truefit.com. Skipped in the BP port —
7559                // the metric is internal to True Fit and adds a
7560                // network call on every cart-add. Re-add if True Fit
7561                // support flags missing data.
7562                return;
7563              }
7564              const formData = new FormData();
7565              formData.append('attributes[_tfcToken]', token);
7566              await fetch(window.Shopify.routes.root + 'cart/update.js', {
7567                method: 'POST',
7568                keepalive: true,
7569                body: formData,
7570              });
7571            });
7572          }
7573        });
7574      });
7575      cartObserver.observe({ entryTypes: ['resource'] });
7576    }
7577    observeCartChanges();
7578  </script>
7578<style>
7579  /* ---- Wrapper polish + typography baseline ------------------------ */
7580  body[data-template="product"] {
7581    --bp-pdp-text: var(--bp-color-text, #171609);
7582    --bp-pdp-body: var(--bp-color-body-copy, #74736B);
7583    --bp-pdp-border: rgba(23, 22, 9, 0.18);
7584    --bp-pdp-border-soft: rgba(23, 22, 9, 0.10);
7585  }
7586
7587  /* ---- Force light background on the PDP wrapper -------------------
7588     Horizon's default color scheme (scheme-1) is dark on this store —
7589     and inherit_color_scheme would propagate it through every nested
7590     block. We force a light bg + dark text on the entire PDP section
7591     so the variant buttons, prices, accordions, etc. read correctly.
7592     The product.json color_scheme is also cleared. */
7593  body[data-template="product"],
7594  body[data-template="product"] .product-information,
7595  body[data-template="product"] .product-information .product-information,
7596  body[data-template="product"] .product-information .product-information__main,
7597  body[data-template="product"] .product-information .product-information__details {
7598    background: var(--bp-color-bg-cream, #F7F6EA);
7599    color: var(--bp-pdp-text);
7600    --color-background: var(--bp-color-bg-cream, #F7F6EA);
7601    --color-foreground: var(--bp-pdp-text);
7602  }
7603  body[data-template="product"] main#MainContent {
7604    background: var(--bp-color-bg-cream, #F7F6EA);
7605  }
7606
7607  /* ---- Product title — Heading/H4 -----------------------------------
7608     #171609 · Signifier · 24 / 300 / 120% / -0.48.
7609
7610     Horizon's actual rule that styles the H1 reads from CSS variables:
7611
7612       .text-block.h3 :is(h1, h2, h3, h4, h5, h6) {
7613         font-family: var(--font-h3--family);
7614         font-size: var(--font-h3--size);
7615         …
7616       }
7617
7618     LAYER 1 — Redefine the variables Horizon's rule reads from. This
7619     makes the existing Horizon rule resolve to BP values without
7620     having to win the specificity fight at the rule level. */
7621  html body[data-template="product"],
7622  html body[data-template="product"] .product-information,
7623  html body[data-template="product"] .product-information__details,
7624  html body[data-template="product"] .text-block,
7625  html body[data-template="product"] .text-block.h3,
7626  html body[data-template="product"] [class*="text-block"] {
7627    --font-h3--family: 'Signifier', 'Times New Roman', serif !important;
7628    --font-h3--size: 24px !important;
7629    --font-h3--weight: 300 !important;
7630    --font-h3--style: normal !important;
7631    --font-h3--line-height: 120% !important;
7632    --font-h3--letter-spacing: -0.48px !important;
7633    --font-h3--case: none !important;
7634    --font-h3-color: var(--bp-color-text, #171609) !important;
7635  }
7636
7637  /* LAYER 2 — Direct property override. Selectors target the actual
7638     Horizon class structure (.product-information, not the
7639     .product-information I had wrong earlier) AND mirror
7640     Horizon's `.text-block.h3 :is(h1,...)` selector with an extra
7641     `.product-information` ancestor to outrank it. */
7642  html body .product-information h1,
7643  html body .product-information__details h1,
7644  html body .product-information .text-block h1,
7645  html body .product-information .text-block.h3 :is(h1, h2, h3, h4, h5, h6),
7646  html body .product-information [class*="text-block"] h1,
7647  html body[data-template="product"] h1.h1,
7648  html body[data-template="product"] h1.h2,
7649  html body[data-template="product"] h1.h3,
7650  html body[data-template="product"] h1.h4 {
7651    margin: 0 !important;
7652    color: var(--bp-color-text, #171609) !important;
7653    font-family: 'Signifier', 'Times New Roman', serif !important;
7654    font-size: 24px !important;
7655    font-style: normal !important;
7656    font-weight: 300 !important;
7657    line-height: 120% !important;
7658    letter-spacing: -0.48px !important;
7659    text-transform: none !important;
7660  }
7661  /* ---- COLLECTION / BRAND eyebrow — Body/Regular/Eyebrow ----------
7662     #74736B · Messina · 14 / 500 / 110% / -0.14 · UPPERCASE.
7663     Targets Horizon's product-vendor surfaces. Breadcrumbs are
7664     handled separately by blocks/bp-pdp-media-gallery.liquid's own
7665     stylesheet (Body/Tiny spec, smaller and not uppercase) — they
7666     used to be in this selector list and were getting the wrong
7667     typography when moved to the gallery overlay. */
7668  .product-information .product-vendor,
7669  .product-information [data-product-vendor],
7670  .product-information [data-bp-eyebrow] {
7671    color: var(--bp-color-body-copy, #74736B) !important;
7672    font-family: var(--bp-font-body), 'Messina Sans VF', system-ui, sans-serif !important;
7673    font-size: 14px !important;
7674    font-style: normal !important;
7675    font-weight: 500 !important;
7676    line-height: 110% !important;
7677    letter-spacing: -0.14px !important;
7678    text-transform: uppercase !important;
7679    text-decoration: none !important;
7680  }
7681
7682  /* ---- Yotpo bottomline "X Reviews" — Body/Tiny -------------------
7683     #74736B · Messina · 10 / 400 / 145% / -0.1.
7684
7685     Yotpo's widget injects `font-family: Futura-PT-Regular` (+ a
7686     bunch of other inline style) at runtime, so this override pairs
7687     `html body` to outrank the inline declarations and uses `!important`
7688     on every property. Targets both the bp-yotpo-stars wrapper
7689     (top-of-PDP rating row) AND raw Yotpo containers anywhere on
7690     the page (reviews list, badge, etc.) — Yotpo renders this label
7691     in multiple places. */
7692  /* Yotpo ships an upstream rule with FIVE chained classes — specificity
7693     (0,5,0) — for `.yotpo-sr-bottom-line-text` inside the bottom-line
7694     widget that pins 13px / Futura PT. To beat it we mirror their
7695     5-class chain AND add `html body` to push specificity to (0,5,2),
7696     plus !important on every prop. Three selectors below cover the
7697     widget's three rendering paths (right-panel, summary-only, and
7698     bare bottom-line). The short selector list at the bottom keeps
7699     the broader-but-lower-specificity safety net for any other Yotpo
7700     surface (reviews list, badge, etc.) where the upstream override
7701     isn't applied. */
7702  html body .yotpo-reviews-star-ratings-widget .yotpo-bottom-line-scroll-panel .yotpo-sr-bottom-line-summary .yotpo-sr-bottom-line-right-panel .yotpo-sr-bottom-line-text,
7703  html body .yotpo-reviews-star-ratings-widget .yotpo-bottom-line-scroll-panel .yotpo-sr-bottom-line-summary .yotpo-sr-bottom-line-text,
7704  html body .yotpo-reviews-star-ratings-widget .yotpo-bottom-line-scroll-panel .yotpo-sr-bottom-line-text,
7705  html body .yotpo-sr-bottom-line-text,
7706  html body .yotpo-sr-bottom-line-text--right-panel,
7707  html body .yotpo-sr-bottom-line-summary [class*="text"],
7708  html body [class*="reviews-count"],
7709  html body [class*="bottom-line-text"] {
7710    color: var(--bp-color-body-copy, #74736B) !important;
7711    font-family: var(--bp-font-body), 'Messina Sans VF', system-ui, sans-serif !important;
7712    font-size: 10px !important;
7713    font-style: normal !important;
7714    font-weight: 400 !important;
7715    line-height: 145% !important;
7716    letter-spacing: -0.1px !important;
7717    text-transform: none !important;
7718  }
7719
7720  /* ---- Price ------------------------------------------------------
7721     Markup (snippets/price.liquid): a `.price__regular` block holds the
7722     default price; a `.price__sale` block holds `.price-item--sale` (the
7723     NEW price) + `.price-item--regular.compare-at-price` (the struck OLD
7724     price). `.price__hidden` toggles which block shows. Note the `price`
7725     class is reused on the container AND the leaf spans, so we key colors
7726     off the specific leaf classes, not bare `.price`. */
7727
7728  /* Default (non-sale) price — Body/Regular/Medium: #171609 · 17/500/-0.17. */
7729  .product-information .price,
7730  .product-information [data-block-type="price"],
7731  .product-information .price__regular,
7732  .product-information .price__regular .price {
7733    color: var(--bp-color-text, #171609) !important;
7734    font-family: var(--bp-font-body) !important;
7735    font-size: 17px !important;
7736    font-style: normal !important;
7737    font-weight: 500 !important;
7738    line-height: 145% !important;
7739    letter-spacing: -0.17px !important;
7740  }
7741  /* NEW / sale price — Sales-Red · Body/Regular/Small (14 / 500 / -0.14). */
7742  .product-information .price__sale .price-item--sale,
7743  .product-information .price__sale .price-item--sale.price {
7744    color: var(--bp-color-sales-red, #CA3D3D) !important;
7745    font-family: var(--bp-font-body) !important;
7746    font-size: 14px !important;
7747    font-style: normal !important;
7748    font-weight: 500 !important;
7749    line-height: 145% !important;
7750    letter-spacing: -0.14px !important;
7751  }
7752  /* OLD / compare price — Body-Copy grey (#74736B) · Body/Body Small
7753     (14 / 500 / -0.14) · strikethrough. Per Figma the struck price is
7754     grey, NOT Sales-Red. */
7755  .product-information .compare-at-price,
7756  .product-information .price__sale .price-item--regular {
7757    color: #74736B !important;
7758    font-family: var(--bp-font-body) !important;
7759    font-size: 14px !important;
7760    font-style: normal !important;
7761    font-weight: 500 !important;
7762    line-height: 145% !important;
7763    letter-spacing: -0.14px !important;
7764    text-decoration: line-through;
7765    margin-left: 6px;
7766  }
7767  /* Right-of-price promo text — Sales-Red · Body/Book/Small
7768     (14 / 400 / -0.14). Lighter (400) than the sale price (500). */
7769  .product-information .bp-promo-line {
7770    color: var(--bp-color-sales-red, #CA3D3D) !important;
7771    font-family: var(--bp-font-body) !important;
7772    font-size: 14px !important;
7773    font-style: normal !important;
7774    font-weight: 400 !important;
7775    line-height: 145% !important;
7776    letter-spacing: -0.14px !important;
7777  }
7778
7779  /* ---- Tag pills below pricing — Heading/H6 (Signifier) -----------
7780     #171609 · Signifier · 14 / 300 / 120% / -0.28. The pills already
7781     get their cream background from bp-tag-pills.liquid; here we
7782     just lock typography on the label text inside each pill. */
7783  .product-information .bp-pills__item {
7784    color: var(--bp-color-text, #171609) !important;
7785    font-family: var(--bp-font-display) !important;
7786    font-size: 14px !important;
7787    font-style: normal !important;
7788    font-weight: 300 !important;
7789    line-height: 120% !important;
7790    letter-spacing: -0.28px !important;
7791    text-transform: none !important;
7792  }
7793
7794  /* ---- Variant picker label "Color" / "Size" — Body/XSmall Book ----
7795     #171609 · Messina · 12 / 400 / 145% / -0.12. The selected-value
7796     ("Olive Night" / "XXS") shares the same spec but in body-copy
7797     grey. Targets Horizon's variant-picker legend/label + the
7798     bp-color-siblings inline label.
7799
7800     `.variant-option__swatch-prefix` is the wrapper around the option
7801     name in the legend ("Size:"); see the BP edit in
7802     snippets/variant-main-picker.liquid that makes Size match the
7803     bp-colors__label structure. */
7804  .product-information variant-picker .option__name,
7805  .product-information variant-picker .option-label,
7806  .product-information variant-picker label[for],
7807  .product-information variant-picker legend,
7808  .product-information variant-picker .variant-option__swatch-prefix,
7809  .product-information variant-picker .product-form__option-name,
7810  .product-information .bp-colors__label,
7811  .product-information .bp-colors__label-prefix {
7812    color: var(--bp-color-text, #171609) !important;
7813    font-family: var(--bp-font-body) !important;
7814    font-size: 12px !important;
7815    font-style: normal !important;
7816    font-weight: 600 !important;
7817    line-height: 145% !important;
7818    letter-spacing: -0.12px !important;
7819    text-transform: none !important;
7820    margin-bottom: 0 !important;
7821  }
7822  /* Selected-value text (Olive Night / XXS) — same size, body-copy grey */
7823  .product-information variant-picker .selected-value,
7824  .product-information variant-picker [class*="selected-value"],
7825  .product-information variant-picker .variant-option__swatch-value,
7826  .product-information variant-picker .product-form__selected-value,
7827  .product-information .bp-colors__label-name {
7828    color: var(--bp-color-body-copy, #74736B) !important;
7829    font-family: var(--bp-font-body) !important;
7830    font-size: 12px !important;
7831    font-style: normal !important;
7832    font-weight: 400 !important;
7833    line-height: 145% !important;
7834    letter-spacing: -0.12px !important;
7835    text-transform: none !important;
7836    margin-left: 8px !important;
7837  }
7838  /* Legend = "Size XXS" row. Render the label + value side-by-side. */
7839  .product-information variant-picker fieldset.variant-option > legend {
7840    display: inline-flex !important;
7841    align-items: baseline !important;
7842    gap: 8px !important;
7843    padding: 0 !important;
7844    margin-bottom: 8px !important;
7845  }
7846
7847  /* Hide Horizon's Color option row — bp-color-siblings owns the
7848     colour swatch UI, so the variant-picker Color row would render a
7849     duplicate "Color: Tomato Red" stacked below the BP swatches.
7850     Horizon renders this two different ways depending on how many
7851     values the option has:
7852       1. Multi-value: <fieldset class="variant-option"> with radio inputs.
7853       2. Single-value (one color attached to the product):
7854          <div class="variant-option" data-testid="variant-option-single">
7855            Color <span class="variant-option__swatch-value">Tomato Red</span>
7856          </div>
7857     Hide both — unscoped selectors so they work even if the markup
7858     isn't inside .product-information for some reason. */
7859  html body[data-template="product"] [data-testid="variant-option-single"],
7860  html body[data-template="product"] div.variant-option[data-testid="variant-option-single"],
7861  html body[data-template="product"] variant-picker [data-testid="variant-option-single"],
7862  html body[data-template="product"] .variant-picker__form > [data-testid="variant-option-single"],
7863  .product-information variant-picker fieldset.variant-option:has(input[name^="Color-"]),
7864  .product-information variant-picker fieldset.variant-option:has(input[name^="color-"]),
7865  .product-information variant-picker [data-testid="variant-option-single"],
7866  .product-information [data-testid="variant-option-single"],
7867  [data-testid="variant-option-single"] {
7868    display: none !important;
7869    visibility: hidden !important;
7870    height: 0 !important;
7871    overflow: hidden !important;
7872    margin: 0 !important;
7873    padding: 0 !important;
7874  }
7875
7876  /* The theme setting variant_button_width = "equal-width-buttons" makes
7877     the fieldset a GRID of equal 1fr tracks (base.css:2179), which stretches
7878     every size chip to the same width and ignores the labels' flex. Figma
7879     wants padding-hugged chips, so lay the row out as wrapping flex instead
7880     — this is what actually kills the equal width (label flex alone can't,
7881     because grid items don't honor flex). */
7882  .product-information variant-picker .variant-option--equal-width-buttons {
7883    display: flex !important;
7884    flex-wrap: wrap !important;
7885    grid-template-columns: none !important;
7886    gap: 8px !important;
7887  }
7888
7889  /* ---- Variant picker: button row ----------------------------------
7890     Per Figma: size chips are padding-sized (13px x / 16px y), NOT
7891     fixed-width — the chip hugs its label. White bg, black CTA/CTA
7892     Small text (#171609 · Messina · 12 / 500 / 145% / -0.12). Squared
7893     corners, 1px outline border. */
7894  .product-information variant-picker .variant-option__button-label,
7895  .product-information variant-picker label[role="radio"],
7896  .product-information variant-picker input[type="radio"] + label,
7897  .product-information .variant-option__button,
7898  .product-information .variant-picker__option-value {
7899    /* Kill Horizon's fixed flex-basis (base.css: flex 0 0 3.25em) +
7900       equal-width-buttons min-width so each chip hugs its label
7901       instead of all rendering the same width. */
7902    flex: 0 0 auto !important;
7903    min-width: 0 !important;
7904    width: auto !important;
7905    min-height: 0 !important;
7906    padding: 16px 13px !important;
7907    display: inline-flex !important;
7908    align-items: center !important;
7909    justify-content: center !important;
7910    border: 1px solid #E1E0D4 !important;
7911    background: #FDFFFA !important;
7912    color: var(--bp-color-text, #171609) !important;
7913    font-family: var(--bp-font-body) !important;
7914    font-size: 12px !important;
7915    font-style: normal !important;
7916    font-weight: 500 !important;
7917    line-height: 145% !important;
7918    letter-spacing: -0.12px !important;
7919    text-transform: none !important;
7920    border-radius: 0 !important;
7921    cursor: pointer;
7922    transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
7923  }
7924  /* Hover (available, non-selected) — invert to the selected look:
7925     black bg, white text. Per Figma hover === selected. Disabled chips
7926     are protected by the higher-specificity :has(input[...]) rule below. */
7927  .product-information variant-picker .variant-option__button-label:hover,
7928  .product-information variant-picker label[role="radio"]:hover,
7929  .product-information .variant-option__button:hover,
7930  .product-information .variant-picker__option-value:hover {
7931    background: var(--bp-color-text, #171609) !important;
7932    color: var(--bp-color-cta-text, #FDFFFA) !important;
7933    border-color: var(--bp-color-text, #171609) !important;
7934  }
7935  .product-information variant-picker .variant-option__button-label:hover .variant-option__button-label__text {
7936    color: var(--bp-color-cta-text, #FDFFFA) !important;
7937  }
7938  /* Selected — black background, white text.
7939     Uses data-current-checked as the sole source of truth. morph.js's
7940     onBeforeUpdate hook preserves this attribute through every async
7941     variant fetch, so the dark highlight never snaps back to the default
7942     variant during the ~1 s network round-trip.
7943     input:checked is intentionally excluded here: morph resets it from
7944     the server HTML (always the default variant) before the request
7945     resolves, which would cause two buttons to appear dark simultaneously
7946     if we used both selectors. */
7947  .product-information variant-picker .variant-option__button-label:has(input[data-current-checked="true"]) {
7948    background: var(--bp-color-text, #171609) !important;
7949    color: var(--bp-color-cta-text, #FDFFFA) !important;
7950    border-color: var(--bp-color-text, #171609) !important;
7951  }
7952  /* Selected text span — force white regardless of inherited color. */
7953  .product-information variant-picker .variant-option__button-label:has(input[data-current-checked="true"]) .variant-option__button-label__text {
7954    color: var(--bp-color-cta-text, #FDFFFA) !important;
7955  }
7956
7957  /* ---- Pill animation position — use data-current-checked, not :checked ---
7958     Horizon's base.css positions the sliding pill using :checked-based selectors.
7959     morph.js resets input.checked from the server HTML after each fetch, which
7960     causes the pill to snap to the server-default variant (XXS) for ~1 frame
7961     — visible to the user as a square "jumping back". data-current-checked is
7962     preserved by morph.js so these overrides keep the pill on the user's actual
7963     selection throughout the morph cycle.
7964
7965     Pattern mirrors Horizon's base.css lines ~2095–2160 with :checked → data-current-checked. */
7966
7967  /* Reset any pill offset inherited from Horizon's ~ label rule on the
7968     selected label itself (the rule below would otherwise assign a -100%-1px
7969     offset when the checked input is to the left of another checked label). */
7970  .product-information variant-picker .variant-option__button-label:has(input[data-current-checked="true"]) {
7971    --pill-offset: 0;
7972  }
7973  /* Labels BEFORE the selected: shift their pill RIGHT (off-screen). */
7974  .product-information variant-picker .variant-option__button-label:not(:has(input[data-current-checked="true"])):has(~ label > input[data-current-checked="true"]) {
7975    --pill-offset: calc(100% + 1px);
7976  }
7977  /* Labels AFTER the selected: shift their pill LEFT (off-screen). */
7978  .product-information variant-picker .variant-option__button-label:has(input[data-current-checked="true"]) ~ label {
7979    --pill-offset: calc(-100% - 1px);
7980  }
7981  /* Anchor the pill to the right edge in labels that precede the selection. */
7982  .product-information variant-picker .variant-option__button-label:not(:has(input[data-current-checked="true"])):h
7982as(~ label > input[data-current-checked="true"]) .variant-option__button-label__pill {
7983    right: 0;
7984    left: unset;
7985  }
7986  /* Anchor the pill to the left edge in labels that follow the selection. */
7987  .product-information variant-picker .variant-option__button-label:has(input[data-current-checked="true"]) ~ label .variant-option__button-label__pill {
7988    left: 0;
7989    right: unset;
7990  }
7991  /* Wrap-around case (3+ variants): first→last direction. */
7992  .product-information variant-picker .variant-option--buttons:has(:nth-of-type(3)) .variant-option__button-label:not(:has(input[data-current-checked="true"])):first-of-type:has(~ label:last-of-type > input[data-current-checked="true"]) {
7993    --pill-offset: calc(-100% - 1px);
7994  }
7995  /* No size pre-selected (fix/pdp-no-default-size): Horizon's pill defaults
7996     to visible (offset 0) and relies on ONE selected sibling to push the
7997     others off-screen. With zero selection nothing pushes them, so every
7998     pill showed and painted all buttons black. Hide all pills while the
7999     fieldset has no selection; the data-current-checked rules above re-reveal
8000     the chosen one once a size is picked. */
8001  .product-information variant-picker .variant-option--buttons:not(:has(input[data-current-checked="true"])) .variant-option__button-label__pill {
8002    opacity: 0 !important;
8003  }
8004  /* Disabled (unavailable / OOS) variants — Figma CTA/CTA Small spec:
8005       border 1px #E1E0D4 · bg #F7F6EA · color #74736B
8006       Messina Sans 12px / 500 / 145% / -0.12px
8007     Horizon paints a diagonal SVG strikethrough
8008     (.variant-option__strikethrough) for sold-out items, so no
8009     text-decoration: line-through here — that would double-stroke. */
8010  .product-information .variant-option__button[disabled],
8011  .product-information .variant-option__button[aria-disabled="true"],
8012  .product-information variant-picker .variant-option__button-label:has(input[disabled]),
8013  .product-information variant-picker .variant-option__button-label:has(input[aria-disabled="true"]),
8014  .product-information variant-picker .variant-option__button-label:has(input[data-option-available="false"]),
8015  .product-information input[type="radio"]:disabled + label {
8016    border: 1px solid #E1E0D4 !important;
8017    background: #F7F6EA !important;
8018    /* #74736B on #F7F6EA is 4.38:1 (just under AA). #666559 = 5.5:1. These
8019       unavailable sizes are interactive (they route to Notify Me), so they are
8020       NOT WCAG-exempt disabled controls — must pass AA (QA 7/27, contrast). */
8021    color: #666559 !important;
8022    font-family: var(--bp-font-body) !important;
8023    font-size: 12px !important;
8024    font-weight: 500 !important;
8025    line-height: 145% !important;
8026    letter-spacing: -0.12px !important;
8027    cursor: not-allowed;
8028    opacity: 1 !important;
8029    text-decoration: none !important;
8030  }
8031  /* Force the inner text element to inherit the OOS color so it
8032     doesn't fall back to the selected/available text color. */
8033  .product-information variant-picker .variant-option__button-label:has(input[disabled]) .variant-option__button-label__text,
8034  .product-information variant-picker .variant-option__button-label:has(input[aria-disabled="true"]) .variant-option__button-label__text,
8035  .product-information variant-picker .variant-option__button-label:has(input[data-option-available="false"]) .variant-option__button-label__text {
8036    /* Match the button rule above — #666559 for AA on the cream chip. */
8037    color: #666559 !important;
8038  }
8039
8040  /* ---- Add to Bag button — CTA/CTA Regular --------------------------
8041     #FDFFFA on #171609 · Messina · 17 / 500 / normal / -0.17 ·
8042     normal-case. No icon — text only. 20px gap above so the button
8043     sits clearly below the labels/links row. */
8044  .product-information buy-buttons-component,
8045  .product-information .buy-buttons {
8046    display: flex;
8047    flex-direction: column;
8048    gap: 12px;
8049    margin-top: 20px !important;
8050  }
8051  .product-information add-to-cart-component button,
8052  .product-information button[name="add"],
8053  .product-information .buy-buttons button[type="submit"] {
8054    width: 100%;
8055    background: var(--bp-color-text, #171609) !important;
8056    color: var(--bp-color-cta-text, #FDFFFA) !important;
8057    border: 1px solid var(--bp-color-text, #171609) !important;
8058    border-radius: 0 !important;
8059    padding: 16px 24px !important;
8060    font-family: var(--bp-font-body) !important;
8061    font-size: 17px !important;
8062    font-style: normal !important;
8063    font-weight: 500 !important;
8064    line-height: normal !important;
8065    letter-spacing: -0.17px !important;
8066    text-transform: none !important;
8067    cursor: pointer;
8068    display: inline-flex !important;
8069    align-items: center !important;
8070    justify-content: center !important;
8071    gap: 10px !important;
8072    transition: background-color 0.12s ease, color 0.12s ease;
8073  }
8074  /* Hide Horizon's default cart icon (the .svg-wrapper.add-to-cart-icon
8075     span baked into add-to-cart-component) so only the BP bag SVG
8076     from the ::after pseudo-element renders. */
8077  .product-information add-to-cart-component button .svg-wrapper.add-to-cart-icon,
8078  .product-information add-to-cart-component button .add-to-cart-icon,
8079  .product-information button[name="add"] .svg-wrapper.add-to-cart-icon,
8080  .product-information button[name="add"] .add-to-cart-icon {
8081    display: none !important;
8082  }
8083
8084  /* BP bag icon appended via ::after — the SVG path from the design
8085     spec, fill=#FDFFFA so it reads as a white outline on the
8086     filled-black button. URL-encoded data URI. */
8087  .product-information add-to-cart-component button::after,
8088  .product-information button[name="add"]::after,
8089  .product-information .buy-buttons button[type="submit"]::after {
8090    content: '' !important;
8091    display: inline-block !important;
8092    flex: 0 0 20px !important;
8093    width: 20px !important;
8094    height: 20px !important;
8095    background-repeat: no-repeat;
8096    background-position: center;
8097    background-size: contain;
8098    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20' fill='none'><path d='M4.18929 5.74443H16.5343H16.6292L16.6729 5.74559C16.9007 5.75108 17.1328 5.87813 17.2448 6.08099C17.3145 6.20166 17.3382 6.30382 17.3547 6.43057C17.6354 9.18815 17.9008 11.9961 18.3051 14.7357C18.3771 15.2468 18.4466 15.7581 18.5137 16.2698C18.5163 16.2918 18.5195 16.336 18.5207 16.3583C18.5378 16.6194 18.4156 16.9264 18.1508 17.0688C17.9651 17.1753 17.7807 17.1764 17.5845 17.1756C16.1978 17.1756 4.69428 17.1756 3.34023 17.1756C3.20422 17.1727 3.01496 17.1863 2.86505 17.1452C2.45036 17.0407 2.25213 16.6561 2.31666 16.2446C2.41071 15.5272 2.58579 14.249 2.68621 13.5186C2.95476 11.54 3.15849 9.46683 3.35962 7.47468C3.37582 7.35719 3.44296 6.63748 3.45714 6.52896L3.46698 6.43433L3.46814 6.42246C3.46814 6.41957 3.46901 6.41349 3.47045 6.40568C3.5156 6.02427 3.79254 5.74038 4.18929 5.74443ZM4.18929 6.61259C4.2136 6.61259 4.24804 6.5961 4.27872 6.57353C4.30302 6.555 4.3201 6.53099 4.32704 6.51854C4.33457 6.5061 4.33486 6.50147 4.33399 6.50436C4.33341 6.50812 4.33225 6.51362 4.33138 6.51767C4.33138 6.51767 4.33081 6.51941 4.33052 6.52433L4.32936 6.53619L4.31923 6.63053C4.132 8.41519 3.9054 10.3182 3.74624 12.1017C3.63685 13.4482 3.56103 15.0257 3.46727 16.3754L3.46582 16.3916V16.3962C3.46582 16.3962 3.46611 16.3974 3.4664 16.3916C3.4664 16.3873 3.4664 16.3751 3.46351 16.3589C3.45396 16.2909 3.41721 16.2162 3.3602 16.1508C3.29306 16.0799 3.20422 16.0247 3.12319 16.0163C3.11856 16.0163 3.13361 16.0174 3.15647 16.0177C4.67199 16.0183 16.0117 16.0177 17.5848 16.0177H17.6719C17.6823 16.0171 17.6916 16.0168 17.6962 16.0166C17.7014 16.0163 17.7034 16.016 17.6991 16.0163C17.5752 16.0287 17.4268 16.1592 17.3857 16.2796C17.3576 16.3557 17.3617 16.3789 17.362 16.3942C17.362 16.3922 17.362 16.3931 17.362 16.3887L17.3605 16.3725C17.254 14.8544 17.1872 13.3293 17.0509 11.8149C16.8906 10.0896 16.6752 8.23172 16.4883 6.50465C16.495 6.52028 16.5161 6.55443 16.5468 6.57584C16.5714 6.59494 16.5989 6.60594 16.6145 6.6097L16.6243 6.61201H16.6284C16.6284 6.61201 16.6298 6.61288 16.6304 6.61288C16.6318 6.61288 16.6336 6.61288 16.633 6.61288C16.6324 6.61288 16.635 6.61288 16.6292 6.61288C16.5783 6.6123 16.4 6.61346 16.3445 6.61288H4.18929V6.61259Z' fill='%23FDFFFA'/><path d='M6.08276 8.7807C6.17855 7.51897 6.20633 6.21411 6.58514 4.98913C7.15408 3.11013 8.44186 2.11637 10.4138 2.12679C13.7999 2.13345 14.5028 4.88003 14.6718 7.71401C14.6961 8.07459 14.7155 8.43459 14.7447 8.78041L13.5872 8.77491C13.617 8.46064 13.6572 8.02655 13.6752 7.71864C13.8008 5.83357 13.5973 3.34135 11.3985 2.81611C10.7573 2.66766 10.07 2.66766 9.42867 2.81611C7.61479 3.24817 7.15119 5.03746 7.12659 6.68726C7.11096 7.36935 7.17521 8.09138 7.24032 8.77491L6.08276 8.78041V8.7807Z' fill='%23FDFFFA'/></svg>");
8099  }
8100  .product-information add-to-cart-component button:hover,
8101  .product-information button[name="add"]:hover,
8102  .product-information .buy-buttons button[type="submit"]:hover {
8103    background: transparent !important;
8104    color: var(--bp-color-text, #171609) !important;
8105  }
8106  /* Hover state — re-encode the SVG with fill='#171609' so the icon
8107     inverts to black on the now-transparent button. */
8108  .product-information add-to-cart-component button:hover::after,
8109  .product-information button[name="add"]:hover::after,
8110  .product-information .buy-buttons button[type="submit"]:hover::after {
8111    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20' fill='none'><path d='M4.18929 5.74443H16.5343H16.6292L16.6729 5.74559C16.9007 5.75108 17.1328 5.87813 17.2448 6.08099C17.3145 6.20166 17.3382 6.30382 17.3547 6.43057C17.6354 9.18815 17.9008 11.9961 18.3051 14.7357C18.3771 15.2468 18.4466 15.7581 18.5137 16.2698C18.5163 16.2918 18.5195 16.336 18.5207 16.3583C18.5378 16.6194 
811118.4156 16.9264 18.1508 17.0688C17.9651 17.1753 17.7807 17.1764 17.5845 17.1756C16.1978 17.1756 4.69428 17.1756 3.34023 17.1756C3.20422 17.1727 3.01496 17.1863 2.86505 17.1452C2.45036 17.0407 2.25213 16.6561 2.31666 16.2446C2.41071 15.5272 2.58579 14.249 2.68621 13.5186C2.95476 11.54 3.15849 9.46683 3.35962 7.47468C3.37582 7.35719 3.44296 6.63748 3.45714 6.52896L3.46698 6.43433L3.46814 6.42246C3.46814 6.41957 3.46901 6.41349 3.47045 6.40568C3.5156 6.02427 3.79254 5.74038 4.18929 5.74443ZM4.18929 6.61259C4.2136 6.61259 4.24804 6.5961 4.27872 6.57353C4.30302 6.555 4.3201 6.53099 4.32704 6.51854C4.33457 6.5061 4.33486 6.50147 4.33399 6.50436C4.33341 6.50812 4.33225 6.51362 4.33138 6.51767C4.33138 6.51767 4.33081 6.51941 4.33052 6.52433L4.32936 6.53619L4.31923 6.63053C4.132 8.41519 3.9054 10.3182 3.74624 12.1017C3.63685 13.4482 3.56103 15.0257 3.46727 16.3754L3.46582 16.3916V16.3962C3.46582 16.3962 3.46611 16.3974 3.4664 16.3916C3.4664 16.3873 3.4664 16.3751 3.46351 16.3589C3.45396 16.2909 3.41721 16.2162 3.3602 16.1508C3.29306 16.0799 3.20422 16.0247 3.12319 16.0163C3.11856 16.0163 3.13361 16.0174 3.15647 16.0177C4.67199 16.0183 16.0117 16.0177 17.5848 16.0177H17.6719C17.6823 16.0171 17.6916 16.0168 17.6962 16.0166C17.7014 16.0163 17.7034 16.016 17.6991 16.0163C17.5752 16.0287 17.4268 16.1592 17.3857 16.2796C17.3576 16.3557 17.3617 16.3789 17.362 16.3942C17.362 16.3922 17.362 16.3931 17.362 16.3887L17.3605 16.3725C17.254 14.8544 17.1872 13.3293 17.0509 11.8149C16.8906 10.0896 16.6752 8.23172 16.4883 6.50465C16.495 6.52028 16.5161 6.55443 16.5468 6.57584C16.5714 6.59494 16.5989 6.60594 16.6145 6.6097L16.6243 6.61201H16.6284C16.6284 6.61201 16.6298 6.61288 16.6304 6.61288C16.6318 6.61288 16.6336 6.61288 16.633 6.61288C16.6324 6.61288 16.635 6.61288 16.6292 6.61288C16.5783 6.6123 16.4 6.61346 16.3445 6.61288H4.18929V6.61259Z' fill='%23171609'/><path d='M6.08276 8.7807C6.17855 7.51897 6.20633 6.21411 6.58514 4.98913C7.15408 3.11013 8.44186 2.11637 10.4138 2.12679C13.7999 2.13345 14.5028 4.88003 14.6718 7.71401C14.6961 8.07459 14.7155 8.43459 14.7447 8.78041L13.5872 8.77491C13.617 8.46064 13.6572 8.02655 13.6752 7.71864C13.8008 5.83357 13.5973 3.34135 11.3985 2.81611C10.7573 2.66766 10.07 2.66766 9.42867 2.81611C7.61479 3.24817 7.15119 5.03746 7.12659 6.68726C7.11096 7.36935 7.17521 8.09138 7.24032 8.77491L6.08276 8.78041V8.7807Z' fill='%23171609'/></svg>");
8112  }
8113  /* Hide the ATC button ONLY when the BP Notify Me block replaces it as
8114     the primary CTA — i.e. the variant is sold out AND restock-eligible
8115     (full price, no on-hand, no inbound). The inline script below sets
8116     `[data-bp-sold-out]` on that same gate; a sold-out-but-NOT-eligible
8117     variant keeps Horizon's disabled "Sold out" button so the buy box is
8118     never left empty.
8119
8120     Gating on the attribute (not `[disabled]`) also avoids the transient
8121     submit-disable that product-form.js:56 applies mid-add-to-cart, which
8122     would otherwise flash-hide the button on every successful click. */
8123  .product-information add-to-cart-component[data-bp-sold-out] button[data-testid="standalone-add-to-cart"] {
8124    display: none !important;
8125  }
8126
8127  /* ---- Rise.ai GiftWizard "Send as a Gift" button ----------------
8128     Rise's app injects its own <button> INSIDE <add-to-cart-component>
8129     as a sibling of the real Add to Bag button on gift-card PDPs.
8130     Both then match the ATC selector above and pick up the dark
8131     filled treatment.
8132
8133     Override just Rise's button (it always carries `.gwbutton` and
8134     `.GiftWizard-gift-button`) to render as the BP secondary CTA:
8135     stacked full-width below Add to Bag, white bg, black border,
8136     text-only. Specificity is (0,3,3), cleanly beats the ATC
8137     rule's (0,1,3) so Horizon's !important doesn't win. */
8138  .product-information add-to-cart-component button.gwbutton.GiftWizard-gift-button,
8139  .product-information add-to-cart-component button.gwbutton,
8140  .product-information add-to-cart-component button.GiftWizard-gift-button {
8141    display: flex !important;
8142    width: 100% !important;
8143    max-height: 44px !important;
8144    min-height: 44px !important;
8145    padding: 16px !important;
8146    margin: 0 !important;
8147    justify-content: center !important;
8148    align-items: center !important;
8149    gap: 4px !important;
8150    background: var(--bp-color-bg-page) !important;
8151    background-color: var(--bp-color-bg-page) !important;
8152    color: var(--bp-color-text, #171609) !important;
8153    border: 1px solid var(--bp-color-text, #171609) !important;
8154    border-radius: 0 !important;
8155    box-shadow: none !important;
8156    font-family: var(--bp-font-body) !important;
8157    font-size: 17px !important;
8158    font-weight: 500 !important;
8159    letter-spacing: -0.17px !important;
8160    line-height: normal !important;
8161    text-transform: none !important;
8162    cursor: pointer !important;
8163    transition: background-color 0.15s ease, color 0.15s ease !important;
8164  }
8165  .product-information add-to-cart-component button.gwbutton::after,
8166  .product-information add-to-cart-component button.GiftWizard-gift-button::after {
8167    display: none !important;
8168    content: none !important;
8169  }
8170  .product-information add-to-cart-component button.gwbutton:hover,
8171  .product-information add-to-cart-component button.GiftWizard-gift-button:hover {
8172    background: var(--bp-color-text, #171609) !important;
8173    background-color: var(--bp-color-text, #171609) !important;
8174    color: var(--bp-color-cta-text, #FDFFFA) !important;
8175  }
8176  /* Text-only — hide any icon Rise's app may inject inside its button. */
8177  .product-information add-to-cart-component button.gwbutton svg,
8178  .product-information add-to-cart-component button.gwbutton img,
8179  .product-information add-to-cart-component button.gwbutton i,
8180  .product-information add-to-cart-component button.GiftWizard-gift-button svg,
8181  .product-information add-to-cart-component button.GiftWizard-gift-button img,
8182  .product-information add-to-cart-component button.GiftWizard-gift-button i {
8183    display: none !important;
8184  }
8185  /* Rise's app stamps `style="margin-right: 15px; margin-bottom: 15px;"`
8186     on the sibling Add to Bag button — zero those out so the two
8187     buttons stack flush per the design. */
8188  .product-information add-to-cart-component:has(button.gwbutton) button:not(.gwbutton):not(.GiftWizard-gift-button) {
8189    margin: 0 0 8px 0 !important;
8190  }
8191
8192  /* ---- Quantity selector — keep compact, BP border ---------------- */
8193  .product-information quantity-input,
8194  .product-information .quantity-selector,
8195  .product-information .quantity {
8196    border: 1px solid var(--bp-pdp-border);
8197    border-radius: 0;
8198    height: 40px;
8199  }
8200  .product-information quantity-input input,
8201  .product-information .quantity-selector input {
8202    font-family: var(--bp-font-body);
8203    color: var(--bp-pdp-text);
8204  }
8205
8206  /* ---- Accelerated checkout (Shop Pay) ----------------------------
8207     Hidden on the PDP per Figma — the bp-pay-in-4 block renders a
8208     static "Pay in full or in 4 interest-free installments with
8209     Shop Pay" line in its place. The block lives after buy-buttons
8210     in templates/product.json's block_order. */
8211  .product-information accelerated-checkout-component,
8212  .product-information .accelerated-checkout-block,
8213  .product-information shopify-buy-it-now-button,
8214  .product-information shop-pay-button,
8215  .product-information .shopify-payment-button,
8216  .product-information [data-shop-pay-button] {
8217    display: none !important;
8218  }
8219
8220  /* Tighten the gap between the Add-to-bag button and the Pay-in-4 line so it
8221     sits right below the button (QA: Amber — was ~36px, want ~10px). PDP only
8222     (.product-information scope); the quick-add flyout hides this block and
8223     uses its own footer line. */
8224  .product-information .bp-pay-in-4 {
8225    margin-top: -1rem;
8226  }
8227
8228  /* ---- BP product accordion — Body/XSmall Book typography ----------
8229     Label (summary + inner span): #171609 · Messina · 12 / 400 / 145% / -0.12
8230     Content (body):               #74736B · Messina · 12 / 400 / 145% / -0.12
8231
8232     The accordion block's own CSS sets the summary to 14 / 660 / uppercase.
8233     Override at every common selector for the summary itself AND the inner
8234     <span> that carries the label text. */
8235  .product-information .bp-acc__summary,
8236  .product-information .bp-acc__summary span,
8237  .product-information .bp-acc summary,
8238  .product-information .bp-acc summary span,
8239  .product-information .bp-acc__item summary,
8240  .product-information .bp-acc__item summary span,
8241  html body .bp-acc__summary,
8242  html body .bp-acc__summary span,
8243  html body .bp-acc summary span {
8244    color: var(--bp-color-text, #171609) !important;
8245    font-family: var(--bp-font-body), 'Messina Sans VF', system-ui, sans-serif !important;
8246    font-size: 12px !important;
8247    font-style: normal !important;
8248    font-weight: 400 !important;
8249    line-height: 145% !important;
8250    letter-spacing: -0.12px !important;
8251    text-transform: none !important;
8252  }
8253  .product-information .bp-acc__body,
8254  .product-information .bp-acc__body *,
8255  .product-information .bp-acc__list,
8256  .product-information .bp-acc__list li,
8257  .product-information .bp-acc__item > div,
8258  .product-information .bp-acc__item > div * {
8259    color: var(--bp-color-body-copy, #74736B) !important;
8260    font-family: var(--bp-font-body), 'Messina Sans VF', system-ui, sans-serif !important;
8261    font-size: 12px !important;
8262    font-style: normal !important;
8263    font-weight: 400 !important;
8264    line-height: 145% !important;
8265    letter-spacing: -0.12px !important;
8266    text-transform: none !important;
8267  }
8268
8269  /* ---- Inline BP CTAs (Size Chart, Find My Size) line up ---------- */
8270  .bp-size-chart-link,
8271  .bp-fma {
8272    margin-top: 4px;
8273  }
8274
8275  /* ---- Description text ------------------------------------------- */
8276  .product-information [data-block-type="text"] p,
8277  .product-information .product-description,
8278  .product-information .rte {
8279    font-family: var(--bp-font-body);
8280    font-size: 14px;
8281    line-height: 145%;
8282    color: var(--bp-pdp-body);
8283  }
8284
8285  /* ---- 8px gap between right-column sections ----------------------
8286     The right column lays out as a flex column: breadcrumbs, stars,
8287     title, price, promo, pills, divider, colors, size, etc. Force
8288     8px between every section regardless of the section schema's
8289     gap setting (which is also set to 8 via product.json). */
8290  .product-information .product-information__details,
8291  .product-information .product-information__details > * {
8292    --gap: 8px;
8293  }
8294  .product-information .product-information__details {
8295    gap: 8px !important;
8296  }
8297  /* Inside the title/price group block (group_icgrde) — keep 8px too. */
8298  .product-information .product-information__details .group,
8299  .product-information .product-information__details [class*="group"] {
8300    gap: 8px !important;
8301  }
8302
8303  /* ---- Divider line between price and variant picker -------------- */
8304  .product-information .divider,
8305  .product-information hr {
8306    border: 0;
8307    border-top: 1px solid var(--bp-pdp-border-soft);
8308    margin: 16px 0;
8309  }
8310
8311  /* ---- Yotpo star widget alignment in title group ----------------- */
8312  .product-information .bp-yotpo-stars {
8313    margin: 6px 0 2px;
8314  }
8315  .yotpo-bottomline .yotpo-stars { display: inline-block; }
8316
8317  /* ---- Hide "Write a Review" link in the top bottomline widget ----
8318     Scoped to .bp-yotpo-stars so the write-review form in the full
8319     reviews section below is unaffected. */
8320  .bp-yotpo-stars [class*="write-review"],
8321  .bp-yotpo-stars [class*="writeReview"],
8322  .bp-yotpo-stars .yotpo-bottomline-link,
8323  .bp-yotpo-stars .yotpo-sr-bottom-line-link,
8324  .bp-yotpo-stars .yotpo-sr-bottom-line-new-review {
8325    display: none !important;
8326  }
8327
8328  /* ---- Reviews section spacing ------------------------------------ */
8329  .bp-pdp-extras .bp-pdp-extras__reviews { padding: 0 20px; }
8330
8331  /* ---- Media gallery polish — compact thumbs, no rounded ---------- */
8332  .product-information media-gallery img,
8333  .product-information .media-gallery img {
8334    border-radius: 0;
8335  }
8336
8337  /* ---- Responsive layout — gallery left / buy-box right ----------- */
8338  @media (min-width: 1024px) {
8339    .product-information { gap: 40px; }
8340  }
8341
8342  /* =================================================================
8343     Figma-spec'd PDP layout (frame 309:164601):
8344       - Container 1360 inside 1440 (40px gutters)
8345       - Gallery 900 wide, Right Column 440 wide
8346       - 2-col gallery grid, 446 × 558 cells, 8px gap
8347       - Swatch 40×40, size button 40 high, ATC 440×44
8348       - Accordion row 47 tall
8349     ================================================================= */
8350
8351  @media screen and (min-width: 1024px) {
8352    /* Container — outer gutter 40px each side */
8353    body[data-template="product"] .product-information,
8354    body[data-template="product"] .product-information > * {
8355      padding-left: 0;
8356      padding-right: 0;
8357    }
8358    body[data-template="product"] .product-information .page-width,
8359    body[data-template="product"] .product-information .section-padding,
8360    body[data-template="product"] .product-information .container {
8361      padding-inline: 40px !important;
8362      max-width: 1440px !important;
8363    }
8364
8365    /* Gallery — 900 wide, 2-column grid, 446×558 cells */
8366    body[data-template="product"] .product-information media-gallery,
8367    body[data-template="product"] .product-information .media-gallery {
8368      flex: 0 0 900px;
8369      max-width: 900px;
8370      gap: 8px !important;
8371    }
8372
8373    /* Sticky media gallery (QA, Adrienne). CSS position:sticky never engaged
8374       reliably in this grid across environments, so the pin is done in JS
8375       (BpPdpGallery.initStickyPin) — but SMOOTHLY: the gallery is `position:
8376       fixed` with a CONSTANT top while in the sticky zone, so the browser keeps
8377       it fixed natively (no per-frame movement → no jank, unlike the old
8378       translateY pin that chased the scroll every frame). JS only runs at the
8379       enter/exit thresholds.
8380
8381       Keep `align-items: start` so the media column sits at the gallery's
8382       natural height and the grid ROW height is held by the taller details
8383       column — that way, when the gallery goes `fixed` (out of flow) the row
8384       doesn't collapse/jump (details still defines it). The JS references the
8385       details column for the travel distance, so pinning the gallery never
8386       destabilises the measurement. */
8387    body[data-template="product"] .product-information__grid {
8388      align-items: start !important;
8389    }
8390    body[data-template="product"] .product-information .media-gallery__item,
8391    body[data-template="product"] .product-information .media-gallery > * {
8392      aspect-ratio: 446 / 558;
8393    }
8394
8395    /* Right column — 440 wide cap, with 20px gap from gallery */
8396    body[data-template="product"] .product-information .product-information__details,
8397    body[data-template="product"] .product-information .product-information__main--right,
8398    body[data-template="product"] .product-information [data-block-type="product-details"] {
8399      flex: 0 0 440px !important;
8400      max-width: 440px !important;
8401      margin-left: 20px;
8402    }
8403  }
8404
8405  /* ---- Breadcrumb — 11px uppercase, 15px line-height -------------- */
8406  .bp-crumbs__item { font-size: 11px; letter-spacing: 1px; line-height: 15px; }
8407
8408  /* ---- Ratings row spacing (Yotpo) -------------------------------- */
8409  .product-information .bp-yotpo-stars { min-height: 17px; }
8410
8411  /* ---- Title — Heading/H4 (24px / 120% / -0.48px) ----------------- */
8412  /* Already in earlier rule — no change */
8413
8414  /* ---- Price row layout — sale price first ($70 then $75 strikethrough).
8415     Typography + colors are owned by the Figma-spec price block near the
8416     top of this file; here we only lay the row out. */
8417  .product-information .price {
8418    display: inline-flex;
8419    flex-wrap: wrap;
8420    gap: 6px;
8421    align-items: baseline;
8422  }
8423
8424  /* ---- Promo line height aligned to price row --------------------- */
8425  .bp-promo-line { line-height: 20px; }
8426
8427  /* ---- Badges row — Popular / Matching Set chips ------------------ */
8428  .bp-pills { margin-top: 8px; }
8429  .bp-pills__item {
8430    height: 25px;
8431    padding: 0 12px;
8432    font-size: 12px;
8433    letter-spacing: 0.6px;
8434  }
8435
8436  /* ---- Color row — label 17px, swatches 40×40 ---------------------- */
8437  .bp-colors__label { font-size: 13px; line-height: 17px; }
8438  .bp-colors__swatch { width: 40px; height: 40px; border-radius: 50%; }
8439  .bp-colors__item.is-active .bp-colors__swatch {
8440    border-width: 1px;
8441    border-color: var(--bp-color-text, #171609);
8442    box-shadow: inset 0 0 0 2px #fff;
8443  }
8444  .bp-colors__swatches { gap: 10px; }
8445
8446  /* ---- Quantity selector — hidden on PDP, visible in cart ---------- */
8447  .product-information .quantity-selector-wrapper { display: none; }
8448
8449  /* ---- Size button row — wrap, gap 8 (chips are padding-sized) ----- */
8450  .product-information variant-picker .variant-options,
8451  .product-information variant-picker .variant-option__buttons {
8452    display: flex;
8453    flex-wrap: wrap;
8454    gap: 8px;
8455  }
8456
8457  /* ---- Size-chart + What's my size links sit side-by-side -------- */
8458  .product-information .bp-size-chart-link,
8459  .product-information .bp-fma {
8460    display: inline-flex;
8461  }
8462  .product-information .bp-size-chart-link + .bp-fma,
8463  .product-information .bp-fma + .bp-size-chart-link {
8464    margin-left: 24px;
8465  }
8466  .bp-size-chart-link__btn,
8467  .bp-fma__btn { font-size: 12px; height: 24px; }
8468
8469  /* ---- ATC — 440×44 ------------------------------------------------ */
8470  .product-information add-to-cart-component button,
8471  .product-information button[name="add"],
8472  .product-information .buy-buttons button[type="submit"],
8473  .bp-notify-trigger__btn {
8474    height: 44px;
8475    padding: 0 24px;
8476    font-size: 13px;
8477    letter-spacing: 1.2px;
8478  }
8479
8480  /* ---- "Pay in full or in 4..." installment line ------------------ */
8481  .product-information .shop-pay-installments,
8482  .product-information .additional-checkout-buttons + p {
8483    margin-top: 8px;
8484    font-family: var(--bp-font-body);
8485    font-size: 12px;
8486    line-height: 17px;
8487    color: var(--bp-pdp-body);
8488  }
8489
8490  /* ---- Save for Later (heart) overlay -----------------------------
8491     The bp-pdp-save-for-later block renders below buy-buttons as a
8492     sibling in the section's flex column. Reserve 56px on the right
8493     side of the ATC + Shop Pay row so the heart never overlaps the
8494     button labels, then pull the heart block up so it sits flush with
8495     the right edge of the Add to Bag row. The block's own
8496     `align-self: flex-end` handles horizontal positioning inside the
8497     flex column. */
8498  .product-information buy-buttons-component:has(+ .bp-pdp-save-later),
8499  .product-information .buy-buttons:has(+ .bp-pdp-save-later) {
8500    padding-right: 56px;
8501  }
8502  .product-information buy-buttons-component + .bp-pdp-save-later,
8503  .product-information .buy-buttons + .bp-pdp-save-later {
8504    /* Lift over the buy-buttons row.
8505       ATC is 44px tall + a 12px gap from the next item below it. */
8506    margin-top: calc(-1 * (44px + 12px));
8507    pointer-events: none;
8508    position: relative;
8509    z-index: 2;
8510  }
8511  .product-information buy-buttons-component + .bp-pdp-save-later .bp-pdp-save-later__btn,
8512  .product-information .buy-buttons + .bp-pdp-save-later .bp-pdp-save-later__btn {
8513    pointer-events: auto;
8514  }
8515
8516  /* ---- Final Sale + Popular meta lines ---------------------------- */
8517  .bp-final-sale { font-size: 12px; line-height: 17px; }
8518
8519  /* ---- Editor's Note ---------------------------------------------- */
8520  .bp-editors-note__heading { font-style: italic; font-weight: 700; letter-spacing: 0; text-transform: none; font-family: var(--bp-font-display); font-size: 14px; }
8521
8522  /* ---- Accordion — 47px row, 14px chevron. Typography is locked
8523     above (Body/XSmall Book); don't redefine font-size here. */
8524  .bp-acc__summary { min-height: 47px !important; padding: 14px 0 !important; }
8525  .bp-acc__chevron { width: 14px; height: 14px; }
8526
8527  /* ---- Stylitics image cells — Neutral cream background ------------
8528     Each outfit grid cell renders <div class="stylitics-grid-img-wrap">
8529     wrapping the product photo. Per design, the photo sits on a
8530     #F7F6EA tile so the items read consistently regardless of the
8531     image's own background. Targets both inline Complete-the-Look
8532     and bp-pdp-extras (How to Wear It / You'll Also Love). */
8533  .bp-stylitics .stylitics-grid-img-wrap,
8534  .bp-stylitics [class*="stylitics-grid-img-wrap"],
8535  .bp-pdp-extras .stylitics-grid-img-wrap,
8536  .bp-pdp-extras [class*="stylitics-grid-img-wrap"] {
8537    background: var(--bp-color-bg-cream, #F7F6EA) !important;
8538  }
8539
8540  /* ---- Stylitics counter heading "Outfit 1/4" ----------------------
8541     Same Signifier display face as the section heading, scaled down a
8542     bit (16px) so it reads as a secondary label above the carousel.
8543     Targets both the plain class and the Svelte-hashed variant. */
8544  .bp-stylitics .stylitics-grid-counter-heading,
8545  .bp-stylitics [class*="stylitics-grid-counter-heading"],
8546  .bp-pdp-extras .stylitics-grid-counter-heading,
8547  .bp-pdp-extras [class*="stylitics-grid-counter-heading"] {
8548    display: none !important;
8549  }
8550  /* "1" + "/4" share the same family but read as a single inline tag;
8551     a small gap between "Outfit" and the count keeps them legible. */
8552  .bp-stylitics .stylitics-count-index,
8553  .bp-stylitics .stylitics-count-total,
8554  .bp-pdp-extras .stylitics-count-index,
8555  .bp-pdp-extras .stylitics-count-total {
8556    font-family: var(--bp-font-display) !important;
8557    font-weight: 300 !important;
8558    color: var(--bp-color-text, #171609) !important;
8559    margin-left: 2px !important;
8560  }
8561
8562  /* ---- Stylitics item hover panel ----------------------------------------
8563     DOM (from widget inspection):
8564       <a data-testid="stylitics-grid-item-info" class="stylitics-grid-item-info …">
8565         <div class="stylitics-item-info-texts …">
8566           <p class="stylitics-grid-item-info-brand …">…</p>
8567           <p class="stylitics-grid-item-info-name …">…</p>
8568           <p class="stylitics-grid-item-info-style …">…</p>
8569           <svelte-css-wrapper>
8570             <p data-testid="stylitics-ui-price" …>
8571               <span data-testid="stylitics-ui-regular-price" …>$70</span>
8572             </p>
8573           </svelte-css-wrapper>
8574           <div data-testid="stylitics-grid-item-info-cta" class="stylitics-grid-item-info-cta …">Shop</div>
8575         </div>
8576       </a>
8577
8578     NOTE: Svelte-hashed classes (svelte-efkltz etc.) are intentionally
8579     avoided here — they change on every widget build. We target
8580     data-testid attributes and the stable semantic class names instead. */
8581
8582  /* Panel = the <a> element itself */
8583  [data-testid="stylitics-grid-item-info"] {
8584    background: var(--bp-color-bg-page, #FEFFFA) !important;
8585  }
8586  /* Brand, name, style labels */
8587  .stylitics-grid-item-info-brand,
8588  .stylitics-grid-item-info-name,
8589  .stylitics-grid-item-info-style {
8590    color: var(--bp-color-text, #171609) !important;
8591    font-family: var(--bp-font-body, 'Messina Sans VF', system-ui, sans-serif) !important;
8592  }
8593  /* Price */
8594  [data-testid="stylitics-ui-price"],
8595  [data-testid="stylitics-ui-regular-price"] {
8596    color: var(--bp-color-text, #171609) !important;
8597    font-family: var(--bp-font-body, 'Messina Sans VF', system-ui, sans-serif) !important;
8598  }
8599  /* CTA "Shop" div — BP primary button: dark fill, near-white text */
8600  [data-testid="stylitics-grid-item-info-cta"] {
8601    background: var(--bp-color-text, #171609) !important;
8602    color: var(--bp-color-cta-text, #FDFFFA) !important;
8603    font-family: var(--bp-font-body, 'Messina Sans VF', system-ui, sans-serif) !important;
8604  }
8605
8606  /* ---- Complete the Look (inline PDP right column) — Figma spec ----
8607     Container: display: flex; padding: 20px; flex-direction: column;
8608       justify-content: center; align-items: center; gap: 20px;
8609       align-self: stretch; background: #F7F6EA (Neutral).
8610     Heading: Signifier 20 / 300 / 120% / -0.4 / #171609, centered. */
8611  .product-information .bp-stylitics {
8612    display: flex !important;
8613    flex-direction: column !important;
8614    justify-content: center !important;
8615    align-items: center !important;
8616    gap: 20px !important;
8617    align-self: stretch !important;
8618    width: 100% !important;
8619    padding: 20px !important;
8620    margin: 0 !important;
8621    background: var(--bp-color-bg-cream, #F7F6EA) !important;
8622  }
8623  .product-information .bp-stylitics__heading {
8624    margin: 0 !important;
8625    color: var(--bp-color-text, #171609) !important;
8626    text-align: center !important;
8627    font-family: var(--bp-font-display) !important;
8628    font-size: 20px !important;
8629    font-style: normal !important;
8630    font-weight: 300 !important;
8631    line-height: 120% !important;
8632    letter-spacing: -0.4px !important;
8633    align-self: stretch !important;
8634  }
8635
8636  /* ---- Reviews + How to Wear It + You'll Also Love — full-bleed
8637     viewport width with the home-section padding convention:
8638       display: flex; padding: 40px; gap: 20px; flex-direction: column;
8639       align-items: flex-start; align-self: stretch.
8640     Mobile drops to the standard BP gutter (16px). */
8641  .bp-pdp-extras-section,
8642  .bp-pdp-extras {
8643    width: 100%;
8644    max-width: none;
8645    margin: 0;
8646    padding: 0;
8647    /* Stylitics's composer renders fixed-width carousel rails and grid
8648       cells that occasionally overshoot the section on narrow viewports
8649       (visible as image cells getting cut off on the right edge of the
8650       page on mobile). Clip the overflow at the section so the layout
8651       stays inside the viewport — the carousel rails inside still
8652       scroll horizontally via their own overflow-x: auto. */
8653    overflow-x: hidden;
8654  }
8655  .bp-pdp-extras .bp-stylitics,
8656  .bp-pdp-extras .bp-stylitics__target {
8657    max-width: 100%;
8658    overflow-x: hidden;
8659  }
8660  /* htwi keeps its own scrolling rail — don't clip the host element,
8661     otherwise its rail (overflow-x: auto) can't paint the offscreen
8662     slides during a swipe. The outer .bp-pdp-extras (above) still
8663     contains any layout overshoot at the section edge. */
8664  body[data-template="product"] .bp-pdp-extras > .bp-stylitics,
8665  .bp-pdp-extras-section .bp-pdp-extras > .bp-stylitics,
8666  /* How to Wear It renders as its OWN standalone section since #142 split
8667     the combined bp-pdp-extras — its <bp-htwi class="bp-stylitics"> root is
8668     no longer a child of .bp-pdp-extras, so the two selectors above stopped
8669     matching it and the base .bp-stylitics card style (the standalone
8670     Stylitics widget: centered + cream) bled through. Reset it here too s
8670o
8671     HTWI keeps its pre-split look (left-aligned, transparent, section
8672     padding). Complete the Look keeps its own cream card (bp-ctl) untouched. */
8673  bp-htwi.bp-stylitics {
8674    display: flex !important;
8675    flex-direction: column !important;
8676    align-items: flex-start !important;
8677    align-self: stretch !important;
8678    gap: 20px !important;
8679    padding: 32px 16px !important;
8680    margin: 0 auto !important;
8681    width: 100% !important;
8682    max-width: 90rem !important;
8683    background: transparent !important;
8684  }
8685  /* Stylitics Svelte widget's inner shell tends to ship a 1107 / 1400
8686     max-width. Override so the carousel inside How to Wear It /
8687     You'll Also Love fills the section's 40px-padded container. */
8688  .bp-pdp-extras .bp-stylitics .bp-stylitics__target,
8689  .bp-pdp-extras .bp-stylitics__target,
8690  .bp-pdp-extras .bp-stylitics__target > section,
8691  .bp-pdp-extras .bp-stylitics__target [class*="stylitics-grid-base"],
8692  .bp-pdp-extras .bp-stylitics__target [class*="stylitics-grid-layout"],
8693  .bp-pdp-extras .bp-stylitics__target [class*="stylitics-ui-carousel"],
8694  .bp-pdp-extras .bp-stylitics__target [class*="stylitics-ui-carousel-card-list"] {
8695    width: 100% !important;
8696    max-width: none !important;
8697    margin: 0 !important;
8698  }
8699  @media (min-width: 1024px) {
8700    body[data-template="product"] .bp-pdp-extras > .bp-stylitics,
8701    .bp-pdp-extras-section .bp-pdp-extras > .bp-stylitics,
8702    bp-htwi.bp-stylitics {
8703      padding: 40px !important;
8704    }
8705  }
8706  /* Reviews block — capped at the 90rem page width and centered (margin
8707     auto), with the same 40px (desktop) / 16px (mobile) horizontal padding
8708     as the surrounding bp-stylitics sections so the three home-style modules
8709     share the same edges and content width on ultra-wide screens. */
8710  body[data-template="product"] .bp-pdp-extras .bp-pdp-extras__reviews,
8711  .bp-pdp-extras-section .bp-pdp-extras .bp-pdp-extras__reviews {
8712    display: flex !important;
8713    flex-direction: column !important;
8714    align-items: stretch !important;
8715    gap: 20px !important;
8716    width: 100% !important;
8717    max-width: 90rem !important;
8718    margin: 0 auto !important;
8719    padding: 32px 16px !important;
8720  }
8721  @media (min-width: 1024px) {
8722    body[data-template="product"] .bp-pdp-extras .bp-pdp-extras__reviews,
8723    .bp-pdp-extras-section .bp-pdp-extras .bp-pdp-extras__reviews {
8724      padding: 40px !important;
8725    }
8726  }
8727  /* Yotpo's main-widget layout caps itself at 1380px and adds its own
8728     16px gutter. Kill both so the widget fills our padded container
8729     (which already provides the 40px desktop / 16px mobile padding). */
8730  .yotpo-reviews-main-widget .yotpo-main-widget-layout .yotpo-base-layout,
8731  .bp-pdp-extras__reviews .yotpo-base-layout,
8732  #yotpo-reviews-container .yotpo-base-layout {
8733    width: 100% !important;
8734    max-width: none !important;
8735    margin: 0 !important;
8736    padding: 0 !important;
8737    box-sizing: border-box !important;
8738  }
8739  /* ---- Stylitics composer carousel ------------------------------------
8740     Atlas parity: let the composer render its OWN native carousel + arrows
8741     on every breakpoint. We intentionally do NOT convert it to a vertical
8742     stack or hide the `stylitics-ui-carousel-arrow / -nav / -pagination`
8743     chevrons here — the earlier mobile override did both, which broke the
8744     native navigation. Keep only the width/box-sizing normalisation above. */
8745
8746  /* "How to Wear It" / "You'll Also Love" headings — Heading/H3 spec
8747     (Signifier 32 / 300 / 120% / -0.64 / #171609, left-aligned).
8748     Applies to every .bp-stylitics__heading (Stylitics modules) and
8749     the optional section-level .bp-pdp-extras__heading.
8750     Unscoped selector with html body for maximum specificity. */
8751  html body .bp-stylitics__heading,
8752  html body .bp-pdp-extras__heading,
8753  body[data-template="product"] .bp-pdp-extras .bp-stylitics__heading,
8754  body[data-template="product"] .bp-pdp-extras .bp-pdp-extras__heading {
8755    color: var(--bp-color-text, #171609) !important;
8756    text-align: left !important;
8757    font-family: var(--bp-font-display), Signifier, 'Times New Roman', serif !important;
8758    font-size: 32px !important;
8759    font-style: normal !important;
8760    font-weight: 300 !important;
8761    line-height: 120% !important;
8762    letter-spacing: -0.64px !important;
8763    align-self: stretch !important;
8764    margin: 0 !important;
8765    text-transform: none !important;
8766  }
8767  body[data-template="product"] .bp-pdp-extras .bp-stylitics__target {
8768    width: 100%;
8769  }
8770
8771  /* =================================================================
8772     Yotpo reviews — match ProjectAtlas exactly (no custom layout / no
8773     custom typography). Atlas renders the bare v3 widget into a plain
8774     anchor div and lets Yotpo own everything. The only deviation we
8775     keep is forcing the star color from Yotpo's default black to BP
8776     gold (#EBAE55).
8777
8778     Yotpo v3 renders each star as <svg class="yotpo-star-rating-icon"
8779     yotpo-sr-star-{full,half,empty}> whose <path fill="url(#…)">
8780     references a linearGradient with rgba(0,0,0,1) stops. A CSS `fill`
8781     declaration on the path beats the fill="url(#…)" attribute, and
8782     forcing the gradient stops to transparent neutralizes the gradient
8783     entirely. Selectors anchor on `#yotpo-reviews-container` to win
8784     specificity over Yotpo's id-scoped rules.
8785     ================================================================= */
8786  .bp-pdp-extras__reviews,
8787  .yotpo-widget-instance {
8788    --yotpo-star-color: #EBAE55;
8789  }
8790
8791  /* Repaint each Yotpo star with the BP custom Star 1 SVG. We hide
8792     Yotpo's inner <path> and paint our shape as a background-image on
8793     the <svg> element itself — works on every star occurrence (summary
8794     row, filter chips, per-review cards, write-review modal) without
8795     having to selector-match Yotpo's container hierarchy.
8796
8797     Yotpo wraps each star in <div class="star-container"> and the row
8798     in <div class="yotpo-star-rating">. The container has no intrinsic
8799     size, so we set width/height on it AND on the SVG. Default visible
8800     size is 28×27, generous enough for review rows; the inline bottom-
8801     line variant near the product title overrides down to 16×15. */
8802  .yotpo-star-rating:not(.yotpo-selected-score),
8803  .yotpo-review-star-rating,
8804  .yotpo-sr-bottom-line-summary .yotpo-star-rating {
8805    display: inline-flex !important;
8806    align-items: center !important;
8807    gap: 2px !important;
8808    line-height: 1 !important;
8809  }
8810  /* The score-filter's "currently-selected stars" overlay defaults to
8811     display:none inline. Honor that — only un-hide when a score is
8812     actually selected (Yotpo strips the inline display when active). */
8813  .yotpo-score-filter .yotpo-selected-score[style*="display: none"] {
8814    display: none !important;
8815  }
8816  .star-container {
8817    display: inline-flex !important;
8818    width: 16px !important;
8819    height: 16px !important;
8820    flex: 0 0 auto !important;
8821    align-items: center;
8822    justify-content: center;
8823  }
8824  svg.yotpo-star-rating-icon,
8825  svg[class*="yotpo-sr-star"],
8826  .star-container > svg {
8827    width: 16px !important;
8828    height: 16px !important;
8829    transform: none !important;
8830    background-repeat: no-repeat;
8831    background-position: center;
8832    background-size: contain;
8833    display: block;
8834    overflow: visible;
8835  }
8836  svg.yotpo-star-rating-icon > *,
8837  svg[class*="yotpo-sr-star"] > *,
8838  .star-container > svg > * {
8839    display: none !important;
8840  }
8841
8842  /* Reviews-list star rating — 22px + 4px spacing per Figma.
8843     Yotpo injects its OWN nine-class rules (specificity 0,9,0
8844     !important) for star size and spacing. A plain class rule ties on
8845     specificity and then loses on source order, because Yotpo's CSS is
8846     injected late — which is why the earlier gap/size rules didn't take.
8847     The reviews widget lives inside <section id="bp-pdp-reviews">, so we
8848     anchor on that ID: one ID (1,x,y) beats any all-class Yotpo selector
8849     regardless of chain length or load order.
8850
8851     Spacing is margin-based, not flex `gap`: Yotpo spaces stars via
8852     per-.star-container margins, so we zero the row gap and set the
8853     inter-star margin directly (matches the Yotpo pattern QA supplied).
8854
8855     Two star ratings live inside the widget and both need this:
8856       .yotpo-review-star-rating — the per-review row.
8857       .yotpo-bottom-line-stars  — the widget's aggregate summary rating
8858                                    at the top of the list.
8859     (The top-of-PDP summary is a separate block, .bp-yotpo-stars, sized
8860     independently below.) */
8861  #bp-pdp-reviews .yotpo-review-star-rating,
8862  #bp-pdp-reviews .yotpo-bottom-line-stars {
8863    gap: 0 !important;
8864  }
8865  #bp-pdp-reviews .yotpo-review-star-rating .star-container,
8866  #bp-pdp-reviews .yotpo-bottom-line-stars .star-container {
8867    width: 22px !important;
8868    height: 21px !important;
8869    flex: 0 0 22px !important;
8870    margin: 0 !important;
8871  }
8872  #bp-pdp-reviews .yotpo-review-star-rating .star-container:not(:last-child),
8873  #bp-pdp-reviews .yotpo-bottom-line-stars .star-container:not(:last-child) {
8874    margin-right: 4px !important;
8875  }
8876  #bp-pdp-reviews .yotpo-review-star-rating .star-container > svg,
8877  #bp-pdp-reviews .yotpo-review-star-rating svg.yotpo-star-rating-icon,
8878  #bp-pdp-reviews .yotpo-review-star-rating svg[class*="yotpo-sr-star"],
8879  #bp-pdp-reviews .yotpo-bottom-line-stars .star-container > svg,
8880  #bp-pdp-reviews .yotpo-bottom-line-stars svg.yotpo-star-rating-icon,
8881  #bp-pdp-reviews .yotpo-bottom-line-stars svg[class*="yotpo-sr-star"] {
8882    width: 22px !important;
8883    height: 21px !important;
8884  }
8885
8886  /* --- Reviews header cleanup (BP) ---
8887     Yotpo's default summary header ships a vertical divider bar between
8888     the score and the "See reviews summary" AI button. The divider reads
8889     as a stray line in the BP design, so hide it — but the AI summary
8890     button IS shown (skinned below). Scoped to #bp-pdp-reviews. */
8891  #bp-pdp-reviews .yotpo-vertical-border { display: none !important; }
8892  /* Yotpo also draws a divider as a :after pseudo on the header .yotpo-bottom-line
8893     (a 2px #CCCCCC bar). Hide it too — no divider in the BP design. The #id scope
8894     out-specifies Yotpo's long class chain; content:none also drops the pseudo. */
8895  #bp-pdp-reviews .yotpo-bottom-line::after {
8896    content: none !important;
8897    display: none !important;
8898  }
8899
8900  /* "See reviews summary" AI button — shown, and Yotpo's dark fill pill
8901     re-skinned with BP tokens so it reads on-brand in the reviews header. */
8902  #bp-pdp-reviews .yotpo-reviews-summary-button #yotpo-summary,
8903  #bp-pdp-reviews #yotpo-summary.yotpo-icon-btn {
8904    display: inline-flex !important;
8905    align-items: center !important;
8906    gap: 8px !important;
8907    background: var(--bp-color-text, #171609) !important;
8908    color: var(--bp-color-cta-text, #FDFFFA) !important;
8909    border: 0 !important;
8910    border-radius: 0 !important;
8911    padding: 10px 16px !important;
8912    font-family: var(--bp-font-body) !important;
8913    font-size: 14px !important;
8914    font-weight: 500 !important;
8915    line-height: 1 !important;
8916    text-transform: none !important;
8917    cursor: pointer !important;
8918  }
8919  #bp-pdp-reviews #yotpo-summary .yotpo-button-icon path {
8920    fill: var(--bp-color-cta-text, #FDFFFA) !important;
8921  }
8922
8923  /* Reviews-summary drawer. Yotpo portals #yotpo-summary-container to <body>,
8924     so these rules are GLOBAL (not scoped to #bp-pdp-reviews). Present it as a
8925     right-side, full-height flyout matching the BP cart drawer
8926     (bp-cart-drawer.liquid): pinned right, 1/3 viewport (min 480px) on desktop,
8927     full width on mobile, solid page-bg surface, above the sticky ATC, with the
8928     same slide-in. Internal header/body/footer stack in a column and the body
8929     scrolls within the fixed height. */
8930  #yotpo-summary-container,
8931  .yotpo-reviews-summary-drawer-container {
8932    position: fixed !important;
8933    inset: 0 0 0 auto !important;     /* pin to the right edge, full height */
8934    width: calc(100vw / 3) !important;
8935    min-width: 480px !important;
8936    max-width: 100vw !important;
8937    height: 100dvh !important;
8938    max-height: 100dvh !important;
8939    margin: 0 !important;
8940    border-radius: 0 !important;
8941    display: flex !important;
8942    flex-direction: column !important;
8943    background: var(--bp-color-bg-page, #FEFFFA) !important;
8944    color: var(--bp-color-text, #171609) !important;
8945    font-family: var(--bp-font-body) !important;
8946    box-shadow: -8px 0 40px rgba(23, 22, 9, 0.18) !important;
8947    z-index: 9999 !important;
8948    overflow: hidden !important;       /* the body scrolls, not the drawer */
8949    animation: bpDrawerSlideIn 0.25s cubic-bezier(0.4, 0, 0.2, 1) forwards;
8950  }
8951  @media (max-width: 749px) {
8952    #yotpo-summary-container,
8953    .yotpo-reviews-summary-drawer-container { width: 100vw !important; min-width: 0 !important; }
8954  }
8955  /* Close (X) floats top-right over the header. */
8956  #yotpo-summary-container .yotpo-summary-close,
8957  .yotpo-reviews-summary-drawer-container .yotpo-summary-close {
8958    position: absolute !important;
8959    top: 24px !important;
8960    right: 24px !important;
8961    width: 16px !important;
8962    height: 16px !important;
8963    color: var(--bp-color-text, #171609) !important;
8964    cursor: pointer !important;
8965    z-index: 1 !important;
8966  }
8967  /* Header + footer hold their size; the body takes the rest and scrolls. */
8968  #yotpo-summary-container .yotpo-summary-header,
8969  #yotpo-summary-container .yotpo-summary-footer-container { flex: 0 0 auto !important; }
8970  #yotpo-summary-container .yotpo-summary-body {
8971    flex: 1 1 auto !important;
8972    min-height: 0 !important;
8973    overflow-y: auto !important;
8974  }
8975  /* Local copy of the cart drawer's slide-in so this doesn't depend on
8976     bp-cart-drawer's keyframes being present (identical name/values). */
8977  @keyframes bpDrawerSlideIn {
8978    from { transform: translateX(100%); }
8979    to   { transform: translateX(0); }
8980  }
8981  /* Topic sentiment icons default to Yotpo pink/green — recolor to the BP
8982     black theme. !important beats the SVG's inline fill presentation attr. */
8983  #yotpo-summary-container .yotpo-summary-body .yotpo-review-summary .yotpo-summary-sentiment svg path {
8984    fill: var(--bp-color-text, #171609) !important;
8985  }
8986
8987  /* Full + (any non-explicit) star: solid gold filled star.
8988     Yotpo ships TWO markup shapes depending on which widget renders the
8989     stars (DEV-1587):
8990       - "vanilla" widget: class lives on the <svg> itself
8991         (<div class="star-container"><svg class="… yotpo-sr-star-half">).
8992       - Vue-rendered widget (has a trailing <!--v-if--> comment): class
8993         lives on .star-container and the <svg> carries NO class at all
8994         (<div class="star-container yotpo-sr-star-half"><svg (no class)>).
8995     A catch-all that excludes on only ONE of the two locations is wrong
8996     for the other shape — excluding on .star-container alone is always
8997     vacuously true for the svg-classed shape (container never has the
8998     class), and excluding on the svg alone is always vacuously true for
8999     the Vue shape (svg never has a class to exclude on). Either way the
9000     "always true" :not() lets this rule's higher specificity beat the
9001     dedicated empty/half rules below and paint every star gold. Exclude
9002     on BOTH the container's and the svg's own class so a real empty/half
9003     star fails the match under either shape. */
9004  svg.yotpo-sr-star-full,
9005  svg.yotpo-star-rating-icon:not(.yotpo-sr-star-empty):not(.yotpo-sr-star-half),
9006  .star-container.yotpo-sr-star-full > svg,
9007  .star-container:not(.yotpo-sr-star-empty):not(.yotpo-sr-star-half) > svg:not(.yotpo-sr-star-empty):not(.yotpo-sr-star-half) {
9008    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='21' viewBox='0 0 22 21' fill='none'><path d='M10.7344 0L12.881 8.04547L21.196 7.60081L14.2076 12.1285L17.2 
900819.8992L10.7344 14.652L4.26874 19.8992L7.26112 12.1285L0.272754 7.60081L8.58778 8.04547L10.7344 0Z' fill='%23EBAE55' stroke='%23EBAE55' stroke-width='1' stroke-linejoin='bevel'/></svg>");
9009  }
9010  /* Empty star: gold outline only. */
9011  svg.yotpo-sr-star-empty,
9012  .star-container.yotpo-sr-star-empty > svg {
9013    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='21' viewBox='0 0 22 21' fill='none'><path d='M10.7344 0L12.881 8.04547L21.196 7.60081L14.2076 12.1285L17.2 19.8992L10.7344 14.652L4.26874 19.8992L7.26112 12.1285L0.272754 7.60081L8.58778 8.04547L10.7344 0Z' fill='none' stroke='%23EBAE55' stroke-linejoin='bevel' stroke-width='1'/></svg>");
9014  }
9015  /* Half star: gold-filled left half, gold outline right half. */
9016  svg.yotpo-sr-star-half,
9017  .star-container.yotpo-sr-star-half > svg {
9018    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='22' height='21' viewBox='0 0 22 21' fill='none'><defs><linearGradient id='g' x1='0' y1='0' x2='1' y2='0'><stop offset='50%25' stop-color='%23EBAE55'/><stop offset='50%25' stop-color='transparent'/></linearGradient></defs><path d='M10.7344 0L12.881 8.04547L21.196 7.60081L14.2076 12.1285L17.2 
901819.8992L10.7344 14.652L4.26874 19.8992L7.26112 12.1285L0.272754 7.60081L8.58778 8.04547L10.7344 0Z' fill='url(%23g)' stroke='%23EBAE55' stroke-linejoin='bevel' stroke-width='1'/></svg>");
9019  }
9020
9021  /* Bottom-line star row — Yotpo renders:
9022       .yotpo-sr-bottom-line-summary  (inline-style column, center)
9023         > <div>                       (inline-style row, center)
9024             .star-container × 5
9025             .yotpo-sr-bottom-line-right-panel
9026               .yotpo-sr-bottom-line-text--right-panel  "82 Reviews"
9027     Yotpo's inline styles default to column-stacked and Futura
9028     typography. Override both with !important so the row reads
9029     "★★★★★  82 Reviews" left-aligned with BP typography. */
9030  .product-information .bp-yotpo-stars,
9031  .product-information .bp-yotpo-stars > *,
9032  .bp-yotpo-stars .yotpo-sr-bottom-line-summary,
9033  .bp-yotpo-stars .yotpo-sr-bottom-line-summary > div,
9034  .bp-yotpo-stars .yotpo-sr-bottom-line-right-panel {
9035    display: flex !important;
9036    flex-direction: row !important;
9037    align-items: center !important;
9038    justify-content: flex-start !important;
9039    gap: 8px !important;
9040    flex-wrap: nowrap !important;
9041    margin: 0 !important;
9042  }
9043  .bp-yotpo-stars .yotpo-star-rating,
9044  .bp-yotpo-stars .yotpo-sr-bottom-line,
9045  .bp-yotpo-stars .yotpo-sr-bottom-line-summary > div {
9046    display: inline-flex !important;
9047    align-items: center !important;
9048    gap: 4px !important;
9049  }
9050  /* Top-of-PDP summary stars are 16px (smaller than the reviews-widget
9051     ratings, which are 22px) — per QA. Same treatment as the others:
9052     gold glyph (from the global mask rules) + 4px inter-star spacing via
9053     margin. Was 22px with margin-right:0, so the stars were oversized
9054     and touching. */
9055  .bp-yotpo-stars .star-container {
9056    width: 16px !important;
9057    height: 16px !important;
9058    margin: 0 !important;
9059    flex: 0 0 16px !important;
9060  }
9061  .bp-yotpo-stars .star-container:not(:last-child) {
9062    margin-right: 4px !important;
9063  }
9064  .bp-yotpo-stars svg.yotpo-star-rating-icon,
9065  .bp-yotpo-stars svg[class*="yotpo-sr-star"],
9066  .bp-yotpo-stars .star-container > svg {
9067    width: 16px !important;
9068    height: 16px !important;
9069  }
9070  /* The "82 Reviews" text — Yotpo applies inline
9071     `font-family: Futura-PT-Regular; font-size: 16px; color: rgb(0,0,0)`
9072     directly on the element. !important on external CSS still wins
9073     against inline styles that aren't themselves marked !important. */
9074  .bp-yotpo-stars .yotpo-sr-bottom-line-text,
9075  .bp-yotpo-stars .yotpo-sr-bottom-line-text--right-panel,
9076  .bp-yotpo-stars .yotpo-sr-bottom-line-right-panel [class*="bottom-line-text"] {
9077    color: var(--bp-color-body-copy, #74736B) !important;
9078    font-family: var(--bp-font-body), 'Messina Sans VF', system-ui, sans-serif !important;
9079    font-size: 12px !important;
9080    font-style: normal !important;
9081    font-weight: 500 !important;
9082    line-height: 145% !important;
9083    letter-spacing: -0.12px !important;
9084    text-transform: none !important;
9085    white-space: nowrap !important;
9086    margin: 0 !important;
9087  }
9088
9089  /* =================================================================
9090     Yotpo review filter row — laid out as a single flex grid of 9
9091     chips (Search / Rating / Media / Age / Usual Size / Size Purchased
9092     / Occasion / Fit / Sort by). Yotpo nests them under three sibling
9093     panels (.yotpo-filters-top-panel, .yotpo-custom-questions-filters,
9094     .yotpo-filters-right-panel), so we flatten those intermediate
9095     wrappers with display: contents and let the flex parent place the
9096     items as if they were direct children.
9097
9098     Each chip is flex: 0 1 calc(25% - gap), min-width 220px — so they
9099     show 4-up on desktop, 3-up on narrower, 2-up on tablet, 1-up on
9100     mobile, all automatically via flex-wrap.
9101
9102     Per Figma: #74736B / Messina Sans VF / 14px / 500 / 145% / -0.14px.
9103     Each chip is just a bottom hairline; no box border, no fill.
9104     ================================================================= */
9105
9106  /* Outer container → wrapping flex. Flatten intermediate panels so
9107     filters become direct flex children. */
9108  .yotpo-filters-container,
9109  #yotpo-reviews-container .yotpo-filters-container {
9110    display: flex !important;
9111    flex-wrap: wrap !important;
9112    align-items: stretch !important;
9113    gap: 16px 24px !important;
9114    padding: 24px 0 !important;
9115    margin: 0 !important;
9116    background: transparent !important;
9117    border: 0 !important;
9118    box-shadow: none !important;
9119  }
9120  .yotpo-filters-container-inner,
9121  .yotpo-filters-top-panel,
9122  .yotpo-custom-questions-filters,
9123  .yotpo-custom-questions-filters-wrapper,
9124  .yotpo-filters-right-panel,
9125  #yotpo-reviews-container .yotpo-filters-container-inner,
9126  #yotpo-reviews-container .yotpo-filters-top-panel,
9127  #yotpo-reviews-container .yotpo-custom-questions-filters,
9128  #yotpo-reviews-container .yotpo-custom-questions-filters-wrapper,
9129  #yotpo-reviews-container .yotpo-filters-right-panel {
9130    display: contents !important;
9131  }
9132
9133  /* Each chip → 25% width minus gap, min 220px, flat hairline only. */
9134  .yotpo-search-filter,
9135  .yotpo-score-filter,
9136  .yotpo-media-filter,
9137  .yotpo-custom-questions-filter,
9138  .yotpo-sorting-filter-container,
9139  #yotpo-reviews-container .yotpo-search-filter,
9140  #yotpo-reviews-container .yotpo-score-filter,
9141  #yotpo-reviews-container .yotpo-media-filter,
9142  #yotpo-reviews-container .yotpo-custom-questions-filter,
9143  #yotpo-reviews-container .yotpo-sorting-filter-container {
9144    flex: 0 1 calc(25% - 18px) !important;
9145    min-width: 220px !important;
9146    max-width: 100% !important;
9147    margin: 0 !important;
9148    padding: 0 !important;
9149    background: transparent !important;
9150    border: 0 !important;
9151    border-bottom: 1px solid rgba(23, 22, 9, 0.16) !important;
9152    border-radius: 0 !important;
9153    box-shadow: none !important;
9154    box-sizing: border-box !important;
9155  }
9156
9157  /* The inner clickable element (label / button) — flexbox row that
9158     pins the visible label on the left and the chevron / icon on the
9159     right. Strip its own borders / bg / shadow. */
9160  .yotpo-search-filter .yotpo-search-label,
9161  .yotpo-score-filter > .yotpo-dropdown-base,
9162  .yotpo-media-filter .yotpo-media-select,
9163  .yotpo-custom-questions-filter .yotpo-dropdown-closable,
9164  .yotpo-sorting-filter-container .yotpo-dropdown-closable {
9165    display: flex !important;
9166    align-items: center !important;
9167    justify-content: space-between !important;
9168    gap: 8px !important;
9169    width: 100% !important;
9170    min-height: 40px !important;
9171    padding: 6px 4px !important;
9172    margin: 0 !important;
9173    background: transparent !important;
9174    border: 0 !important;
9175    border-radius: 0 !important;
9176    box-shadow: none !important;
9177    text-align: left !important;
9178    cursor: pointer !important;
9179    position: relative !important;
9180  }
9181  /* The label inside Search + Sort sits flush-left of its content. */
9182  .yotpo-search-filter .yotpo-search-label,
9183  .yotpo-sorting-filter-container .yotpo-dropdown-closable {
9184    justify-content: flex-start !important;
9185  }
9186
9187  /* Yotpo uses placeholder <input> elements inside each dropdown chip
9188     as the click→focus target. Previous attempts to hide them broke
9189     Yotpo's click-handler chain (display: none kills label→input
9190     forwarding; position: absolute over the chip covered the button).
9191
9192     Final approach: leave the input's layout entirely to Yotpo and
9193     only override its appearance so it blends with the BP styling.
9194     The input's white background, default size, and event wiring
9195     stay intact — only the text/border become invisible. */
9196  .yotpo-score-filter .yotpo-filter-select,
9197  .yotpo-custom-questions-filter .yotpo-dropdown-placeholder-input,
9198  .yotpo-sorting-filter-container input[readonly] {
9199    background: transparent !important;
9200    background-color: transparent !important;
9201    color: transparent !important;
9202    caret-color: transparent !important;
9203    border: 0 !important;
9204    outline: 0 !important;
9205    box-shadow: none !important;
9206  }
9207
9208  /* Reorder filters so the row layout matches the Figma:
9209       Row 1: Age, Usual Size, Size Purchased, Fit          (custom)
9210       Row 2: Search, Rating, With media, Sort by           (top + sort)
9211     Yotpo doesn't expose a stable class per custom-question filter, so
9212     we use :has(.yotpo-selected-value[title="…"]) to pick each one by
9213     its label. Occasion (not in the comp) falls to the end. */
9214  .yotpo-custom-questions-filter:has(.yotpo-selected-value[title="Age"])            { order: 1 !important; }
9215  .yotpo-custom-questions-filter:has(.yotpo-selected-value[title="Usual Size"])     { order: 2 !important; }
9216  .yotpo-custom-questions-filter:has(.yotpo-selected-value[title="Size Purchased"]) { order: 3 !important; }
9217  .yotpo-custom-questions-filter:has(.yotpo-selected-value[title="Fit"])            { order: 4 !important; }
9218  .yotpo-search-filter             { order: 5 !important; }
9219  .yotpo-score-filter              { order: 6 !important; }
9220  .yotpo-media-filter              { order: 7 !important; }
9221  .yotpo-sorting-filter-container  { order: 8 !important; }
9222  /* Anything not explicitly ordered (e.g. Occasion) sinks below. */
9223  .yotpo-custom-questions-filter   { order: 9 !important; }
9224  .yotpo-custom-questions-filter:has(.yotpo-selected-value[title="Age"]),
9225  .yotpo-custom-questions-filter:has(.yotpo-selected-value[title="Usual Size"]),
9226  .yotpo-custom-questions-filter:has(.yotpo-selected-value[title="Size Purchased"]),
9227  .yotpo-custom-questions-filter:has(.yotpo-selected-value[title="Fit"]) {
9228    /* re-apply specific orders to defeat the catch-all above */
9229  }
9230
9231  /* BP typography on every visible label. */
9232  .yotpo-search-filter input.yotpo-search-input,
9233  .yotpo-score-filter .yotpo-selected-value,
9234  .yotpo-media-filter .yotpo-selected-value,
9235  .yotpo-custom-questions-filter .yotpo-selected-value,
9236  .yotpo-sorting-filter-container .yotpo-dropdown-placeholder,
9237  .yotpo-sorting-filter-container .yotpo-selected-value {
9238    color: var(--bp-color-body-copy, #74736B) !important;
9239    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9240    font-size: 14px !important;
9241    font-style: normal !important;
9242    font-weight: 500 !important;
9243    line-height: 145% !important;
9244    letter-spacing: -0.14px !important;
9245    background: transparent !important;
9246    border: 0 !important;
9247    padding: 0 !important;
9248    margin: 0 !important;
9249    flex: 1 1 auto !important;
9250    text-align: left !important;
9251    white-space: nowrap !important;
9252    overflow: hidden !important;
9253    text-overflow: ellipsis !important;
9254  }
9255
9256  /* Search input internals — magnifier on left as a static flex item,
9257     input fills the rest. Yotpo's own CSS positions the SVG absolutely
9258     against the label which causes the placeholder to render under it;
9259     force position: static on both so flex governs layout. */
9260  .yotpo-search-filter .yotpo-search-label {
9261    position: relative !important;
9262    padding: 6px 4px 6px 8px !important;
9263  }
9264  .yotpo-search-filter .yotpo-search-icon {
9265    position: static !important;
9266    flex: 0 0 16px !important;
9267    width: 16px !important;
9268    height: 16px !important;
9269    margin: 0 !important;
9270    transform: none !important;
9271    inset: auto !important;
9272  }
9273  .yotpo-search-filter .yotpo-search-icon path {
9274    fill: var(--bp-color-body-copy, #74736B) !important;
9275  }
9276  .yotpo-search-filter input.yotpo-search-input {
9277    position: static !important;
9278    flex: 1 1 0 !important;
9279    min-width: 0 !important;
9280    width: auto !important;
9281    padding: 0 0 0 8px !important;
9282    margin: 0 !important;
9283    min-height: 40px !important;
9284    border: 0 !important;
9285    background: transparent !important;
9286    resize: none !important;
9287    outline: none !important;
9288    box-shadow: none !important;
9289  }
9290  .yotpo-search-filter input.yotpo-search-input::placeholder {
9291    color: var(--bp-color-body-copy, #74736B) !important;
9292    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9293    font-size: 14px !important;
9294    font-weight: 500 !important;
9295    letter-spacing: -0.14px !important;
9296    opacity: 1 !important;
9297  }
9298
9299  /* Media filter's circle icon and order — put it on the right. */
9300  .yotpo-media-filter .yotpo-radio-icon {
9301    flex: 0 0 auto !important;
9302    width: 16px !important;
9303    height: 16px !important;
9304  }
9305  .yotpo-media-filter .yotpo-radio-icon circle {
9306    stroke: var(--bp-color-body-copy, #74736B) !important;
9307  }
9308
9309  /* Score (Rating) chip — chevron right of label; if a rating is
9310     applied, the visible .yotpo-selected-score star row sits between
9311     the label and the chevron. The label container is already
9312     space-between, so the natural order works. */
9313  .yotpo-score-filter .yotpo-selected-score {
9314    flex: 0 0 auto !important;
9315    margin: 0 0 0 8px !important;
9316  }
9317
9318  /* Chevron arrow — re-tint to BP body copy color. */
9319  .yotpo-filters-container .yotpo-dropdown-arrow-icon path {
9320    stroke: var(--bp-color-body-copy, #74736B) !important;
9321    fill: none !important;
9322  }
9323  .yotpo-filters-container .yotpo-dropdown-arrow-icon {
9324    flex: 0 0 auto !important;
9325    width: 10px !important;
9326    height: 7px !important;
9327  }
9328
9329  /* Dropdown menus (open state) — match the chip typography + flat
9330     background, light hover state. */
9331  .yotpo-filters-container .yotpo-dropdown-content,
9332  .yotpo-filters-container .yotpo-dropdown-content-wrapper {
9333    background: var(--bp-color-bg-page) !important;
9334    border: 1px solid rgba(23, 22, 9, 0.12) !important;
9335    border-radius: 0 !important;
9336    box-shadow: 0 8px 24px rgba(23, 22, 9, 0.08) !important;
9337    padding: 4px 0 !important;
9338    margin-top: 4px !important;
9339  }
9340  .yotpo-filters-container .yotpo-dropdown-option,
9341  .yotpo-filters-container .yotpo-score-option {
9342    color: var(--bp-color-text, #171609) !important;
9343    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9344    font-size: 14px !important;
9345    font-weight: 500 !important;
9346    line-height: 145% !important;
9347    letter-spacing: -0.14px !important;
9348    padding: 10px 16px !important;
9349    cursor: pointer !important;
9350  }
9351  .yotpo-filters-container .yotpo-dropdown-option .yotpo-selected-icon path,
9352  .yotpo-filters-container .yotpo-score-option .yotpo-selected-icon path {
9353    fill: var(--bp-color-text, #171609) !important;
9354  }
9355
9356  /* Tighten the filter row on narrow viewports. */
9357  @media (max-width: 767px) {
9358    .yotpo-search-filter,
9359    .yotpo-score-filter,
9360    .yotpo-media-filter,
9361    .yotpo-custom-questions-filter,
9362    .yotpo-sorting-filter-container {
9363      flex: 0 1 calc(50% - 6px) !important;
9364      min-width: 0 !important;
9365    }
9366    .yotpo-filters-container,
9367    #yotpo-reviews-container .yotpo-filters-container {
9368      gap: 12px !important;
9369    }
9370  }
9371
9372  /* =================================================================
9373     Yotpo review cards — individual review card layout + typography.
9374     Targets the 2-col card (reviewer left / content right) that Yotpo
9375     v3 renders for each review in the list.
9376     ================================================================= */
9377
9378  /* Card row — 2-col grid. The card itself has no border anymore
9379     (Yotpo renders a separate .yotpo-review-border-smooth element
9380     between cards which we color below). */
9381  .yotpo-review,
9382  .yotpo-reviews-main-widget .yotpo-review {
9383    display: grid !important;
9384    grid-template-columns: 200px 1fr !important;
9385    gap: 24px !important;
9386    border-top: 0 !important;
9387    border-top-width: 0 !important;
9388    border-bottom: none !important;
9389    padding: 24px 0 !important;
9390    background: transparent !important;
9391  }
9392  /* Separator that Yotpo paints between review cards — switch from
9393     the default #CCCCCC to BP's E1E0D4 hairline tone. */
9394  .yotpo-review-border-smooth,
9395  .yotpo-review-border-smooth.top-margin,
9396  .yotpo-reviews-main-widget .yotpo-review-border-smooth,
9397  .yotpo-reviews-main-widget .yotpo-review-border-smooth.top-margin {
9398    background: #E1E0D4 !important;
9399  }
9400  @media (max-width: 767px) {
9401    .yotpo-review,
9402    .yotpo-reviews-main-widget .yotpo-review {
9403      grid-template-columns: 1fr !important;
9404      gap: 12px !important;
9405    }
9406    /* Mobile: the star row is inline-flex, so Yotpo's centered text-align
9407       on the rating/title wrapper centers the stars while the (block-level)
9408       title + body stay left — the stars end up out of line with the rest
9409       of the review. Force the star row (and its wrapper) hard-left so it
9410       aligns with the title, body, and size details. */
9411    #bp-pdp-reviews .yotpo-review-rating-title {
9412      text-align: left !important;
9413      align-items: flex-start !important;
9414    }
9415    #bp-pdp-reviews .yotpo-review-star-rating {
9416      justify-content: flex-start !important;
9417      align-self: flex-start !important;
9418      margin-left: 0 !important;
9419      margin-right: auto !important;
9420    }
9421  }
9422
9423  /* ---- Left column: reviewer info ---- */
9424  .yotpo-reviewer,
9425  .yotpo-review-reviewer {
9426    display: flex !important;
9427    flex-direction: column !important;
9428    align-items: flex-start !important;
9429    gap: 2px !important;
9430    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9431  }
9432
9433  /* Reviewer name — Body/Semi/Small */
9434  .yotpo-reviewer-name,
9435  .yotpo-reviewer-full-name {
9436    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9437    font-size: 14px !important;
9438    font-weight: 700 !important;
9439    line-height: 145% !important;
9440    letter-spacing: -0.14px !important;
9441    color: var(--bp-color-text, #171609) !important;
9442    margin: 0 !important;
9443  }
9444
9445  /* Verified buyer badge — ONE element shown as a flex row (icon + text side by side).
9446     We target the badge CONTAINER (.yotpo-verified-buyer-badge) and the confirmed
9447     text class (.yotpo-reviewer-verified-buyer-text) as the same rule.
9448     The broad [class*="verified"] wildcard is intentionally removed — it caused
9449     multiple elements to receive display:flex and produced the double-check symptom. */
9450  .yotpo-verified-buyer-badge,
9451  .yotpo-reviewer-verified-buyer,
9452  .yotpo-reviewer-verified-buyer-text {
9453    display: flex !important;
9454    flex-direction: row !important;
9455    align-items: center !important;
9456    gap: 4px !important;
9457    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9458    font-size: 12px !important;
9459    font-weight: 500 !important;
9460    line-height: 145% !important;
9461    letter-spacing: -0.12px !important;
9462    color: var(--bp-color-text, #171609) !important;
9463    margin: 2px 0 0 !important;
9464  }
9465  /* If Yotpo renders the text as a sibling of the badge container (double-rendering),
9466     hide the standalone text element — the badge container already shows both icon + text. */
9467  .yotpo-verified-buyer-badge + .yotpo-reviewer-verified-buyer-text,
9468  .yotpo-reviewer-verified-buyer + .yotpo-reviewer-verified-buyer-text {
9469    display: none !important;
9470  }
9471
9472  /* Reviewer custom field rows — Size Purchased / Usual Size / Age / Location.
9473     Yotpo renders these when the widget's "show reviewer attributes" option is
9474     on (Yotpo Admin → Widget Builder). */
9475  .yotpo-reviewer-tags,
9476  .yotpo-reviewer-custom-fields,
9477  .yotpo-reviewer [class*="tags"],
9478  .yotpo-reviewer [class*="custom-field"]:not([class*="label"]):not([class*="value"]) {
9479    display: flex !important;
9480    flex-direction: column !important;
9481    gap: 2px !important;
9482    margin-top: 10px !important;
9483  }
9484  .yotpo-reviewer-tag,
9485  .yotpo-reviewer-custom-field,
9486  .yotpo-reviewer [class*="-tag"]:not([class*="label"]):not([class*="value"]) {
9487    display: grid !important;
9488    grid-template-columns: auto 1fr !important;
9489    gap: 0 6px !important;
9490    align-items: baseline !important;
9491    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9492    line-height: 145% !important;
9493  }
9494  /* Field label: Size Purchased: / Usual Size: etc. — Body/Semi/Small */
9495  .yotpo-reviewer-tag-label,
9496  .yotpo-reviewer-tag-title,
9497  .yotpo-reviewer-custom-field-label,
9498  .yotpo-reviewer-field-label,
9499  .yotpo-reviewer [class*="-label"] {
9500    font-size: 14px !important;
9501    font-weight: 700 !important;
9502    color: var(--bp-color-text, #171609) !important;
9503    letter-spacing: -0.14px !important;
9504    white-space: nowrap !important;
9505  }
9506  /* Field value: S (4-8) / 55-64 / Tennessee etc. — Body/XSmall Book */
9507  .yotpo-reviewer-tag-value,
9508  .yotpo-reviewer-tag-content,
9509  .yotpo-reviewer-custom-field-value,
9510  .yotpo-reviewer-field-value,
9511  .yotpo-reviewer [class*="-value"],
9512  .yotpo-reviewer [class*="-content"] {
9513    font-size: 12px !important;
9514    font-weight: 400 !important;
9515    color: var(--bp-color-body-copy, #74736B) !important;
9516    letter-spacing: -0.12px !important;
9517  }
9518
9519  /* ---- Shared 2-column grid for all reviewer question types ----
9520     Collapses every question wrapper to display:contents so label and value
9521     spans land directly in this grid, aligning ALL value columns regardless
9522     of label width differences (e.g. "Size Purchased" vs "Location").
9523     .bp-pdp-extras__reviews prefix gives specificity (0,2,0) which beats
9524     Yotpo's async-loaded single-class rules even if they carry !important. */
9525  .bp-pdp-extras__reviews .yotpo-review-customer-questions {
9526    display: grid !important;
9527    grid-template-columns: max-content 1fr !important;
9528    column-gap: 8px !important;
9529    row-gap: 4px !important;
9530    align-items: baseline !important;
9531  }
9532  /* Key-value + free-text wrappers: flatten into the shared grid */
9533  .bp-pdp-extras__reviews .yotpo-review-question-wrapper,
9534  .bp-pdp-extras__reviews .yotpo-review-key-value-question,
9535  .bp-pdp-extras__reviews .yotpo-review-free-text-question,
9536  .bp-pdp-extras__reviews .yotpo-custom-questions-wrapper,
9537  .bp-pdp-extras__reviews .yotpo-custom-questions-free-text-wrapper,
9538  .bp-pdp-extras__reviews .yotpo-custom-questions-free-text-question {
9539    display: contents !important;
9540  }
9541
9542  /* Range question: its outer container has inline display:flex so display:contents
9543     is unreliable there. Instead keep it as a single grid item spanning both columns,
9544     and make the wrapper a flex row so title + value appear side by side. */
9545  .bp-pdp-extras__reviews .yotpo-custom-questions-range-question,
9546  .bp-pdp-extras__reviews .yotpo-review-range-question-top {
9547    grid-column: 1 / -1 !important;
9548  }
9549  .bp-pdp-extras__reviews .yotpo-custom-questions-range-question-wrapper {
9550    display: flex !important;
9551    flex-direction: row !important;
9552    align-items: baseline !important;
9553    gap: 8px !important;
9554    width: auto !important;
9555    margin-bottom: 0 !important;
9556  }
9557  /* Hide progress bar — only label + text value are shown */
9558  .bp-pdp-extras__reviews .yotpo-progress-bar-wrapper {
9559    display: none !important;
9560  }
9561  /* See More link spans both columns so it sits full-width below the fields */
9562  .bp-pdp-extras__reviews .yotpo-custom-questions-see-more-label {
9563    grid-column: 1 / -1 !important;
9564  }
9565
9566  /* ---- Label typography (all question types) ---- */
9567  .yotpo-custom-questions-title,
9568  .yotpo-custom-questions-range-question-title,
9569  .yotpo-custom-questions-free-text-title {
9570    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9571    font-size: 12px !important;
9572    font-weight: 700 !important;
9573    line-height: 145% !important;
9574    letter-spacing: -0.12px !important;
9575    color: var(--bp-color-text, #171609) !important;
9576    white-space: nowrap !important;
9577  }
9578
9579  /* ---- Value typography (all question types) ---- */
9580  .yotpo-custom-questions-value,
9581  .yotpo-custom-questions-range-question-value,
9582  .yotpo-custom-questions-free-text-value {
9583    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9584    font-size: 12px !important;
9585    font-weight: 500 !important;
9586    line-height: 145% !important;
9587    letter-spacing: -0.12px !important;
9588    color: var(--bp-color-body-copy, #74736B) !important;
9589  }
9590
9591  /* High-specificity overrides for all question types.
9592     Yotpo's CDN stylesheet is async-injected (appears later in cascade), so
9593     at equal class-count !important rules Yotpo wins on cascade order.
9594     Strategy: add the `html` element selector — specificity (0,0,N,1
9594) beats
9595     Yotpo's (0,0,N,0) regardless of source order.
9596     Free-text value needs one extra class because its DOM has two extra
9597     wrapper elements; key-value and range skip those. */
9598
9599  /* Free-text value: 14 classes (0,14,0) — already beats Yotpo's 13. */
9600  .bp-pdp-extras__reviews .yotpo-reviews-main-widget .yotpo-main-widget-layout .yotpo-main-layout .yotpo-reviews-container .yotpo-reviews-list .yotpo-review .yotpo-review-left-panel .yotpo-review-customer-questions-container .yotpo-review-customer-questions .yotpo-review-question-wrapper .yotpo-review-free-text-question .yotpo-custom-questions-free-text-question .yotpo-custom-questions-free-text-value {
9601    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9602    font-size: 12px !important;
9603    font-weight: 500 !important;
9604    line-height: 145% !important;
9605    letter-spacing: -0.12px !important;
9606    color: #74736B !important;
9607  }
9608
9609  /* Key-value + range labels: html + 12 classes = (0,0,12,1).
9610     Even if Yotpo uses 12 classes (0,0,12,0), the element selector tips the win. */
9611  /* Labels — html + 13 classes = (0,0,13,1), beats Yotpo's (0,0,13,0). */
9612  html .bp-pdp-extras__reviews .yotpo-reviews-main-widget .yotpo-main-widget-layout .yotpo-main-layout .yotpo-reviews-container .yotpo-reviews-list .yotpo-review .yotpo-review-left-panel .yotpo-review-customer-questions-container .yotpo-review-customer-questions .yotpo-review-question-wrapper .yotpo-custom-questions-wrapper .yotpo-custom-questions-title,
9613  html .bp-pdp-extras__reviews .yotpo-reviews-main-widget .yotpo-main-widget-layout .yotpo-main-layout .yotpo-reviews-container .yotpo-reviews-list .yotpo-review .yotpo-review-left-panel .yotpo-review-customer-questions-container .yotpo-review-customer-questions .yotpo-review-question-wrapper .yotpo-custom-questions-range-question .yotpo-custom-questions-range-question-wrapper .yotpo-custom-questions-range-question-title,
9614  html .bp-pdp-extras__reviews .yotpo-reviews-main-widget .yotpo-main-widget-layout .yotpo-main-layout .yotpo-reviews-container .yotpo-reviews-list .yotpo-review .yotpo-review-left-panel .yotpo-review-customer-questions-container .yotpo-review-customer-questions .yotpo-review-question-wrapper .yotpo-review-free-text-question .yotpo-custom-questions-free-text-question .yotpo-custom-questions-free-text-title {
9615    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9616    font-size: 12px !important;
9617    font-weight: 700 !important;
9618    line-height: 145% !important;
9619    letter-spacing: -0.12px !important;
9620    color: var(--bp-color-text, #171609) !important;
9621    white-space: nowrap !important;
9622  }
9623
9624  /* Values — same (0,0,13,1) or (0,0,14,1) approach. */
9625  html .bp-pdp-extras__reviews .yotpo-reviews-main-widget .yotpo-main-widget-layout .yotpo-main-layout .yotpo-reviews-container .yotpo-reviews-list .yotpo-review .yotpo-review-left-panel .yotpo-review-customer-questions-container .yotpo-review-customer-questions .yotpo-review-question-wrapper .yotpo-custom-questions-wrapper .yotpo-custom-questions-value,
9626  html .bp-pdp-extras__reviews .yotpo-reviews-main-widget .yotpo-main-widget-layout .yotpo-main-layout .yotpo-reviews-container .yotpo-reviews-list .yotpo-review .yotpo-review-left-panel .yotpo-review-customer-questions-container .yotpo-review-customer-questions .yotpo-review-question-wrapper .yotpo-custom-questions-range-question .yotpo-custom-questions-range-question-wrapper .yotpo-custom-questions-range-question-value {
9627    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9628    font-size: 12px !important;
9629    font-weight: 500 !important;
9630    line-height: 145% !important;
9631    letter-spacing: -0.12px !important;
9632    color: #74736B !important;
9633  }
9634
9635  /* "See More" reviewer info link — CTA/CTA Small.
9636     Yotpo renders this as <label class="yotpo-custom-questions-see-more-label">
9637     with an inline display:flex. text-decoration applies to flex elements
9638     so no display override needed — keep it as-is to preserve left alignment. */
9639  html body .yotpo-custom-questions-see-more-label,
9640  .yotpo-see-more-reviewers-info,
9641  [class*="yotpo-see-more"],
9642  [class*="see-more-reviewers"] {
9643    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9644    font-size: 12px !important;
9645    font-weight: 500 !important;
9646    line-height: 145% !important;
9647    letter-spacing: -0.12px !important;
9648    color: var(--bp-color-text, #171609) !important;
9649    text-decoration: underline !important;
9650    text-decoration-line: underline !important;
9651    text-underline-offset: 2px !important;
9652    background: none !important;
9653    border: none !important;
9654    padding: 0 !important;
9655    margin-top: 10px !important;
9656    cursor: pointer !important;
9657  }
9658
9659  /* ---- Right column: review content ---- */
9660  .yotpo-review-content {
9661    display: flex !important;
9662    flex-direction: column !important;
9663    gap: 0 !important;
9664    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9665  }
9666
9667  /* Header: stars + title + date on one row */
9668  .yotpo-review-header,
9669  .yotpo-review-content .yotpo-review-header {
9670    display: flex !important;
9671    align-items: center !important;
9672    gap: 8px !important;
9673    flex-wrap: nowrap !important;
9674    margin-bottom: 8px !important;
9675  }
9676  /* Figma Body/Semi/Small spec: Messina 14 / 660 / 145% / -0.14 / BP black. */
9677  .yotpo-review-title,
9678  .yotpo-review-header-title {
9679    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9680    font-size: 14px !important;
9681    font-style: normal !important;
9682    font-weight: 700 !important;
9683    line-height: 145% !important;
9684    letter-spacing: -0.14px !important;
9685    color: var(--bp-color-text, #171609) !important;
9686    flex: 1 1 auto !important;
9687    margin: 0 !important;
9688  }
9689  /* Yotpo's app injects a NINE-class selector (0,9,0 !important) forcing
9690     the review title to Futura PT 18/500. An all-class override ties on
9691     specificity and loses on load order (Yotpo injects late), so the
9692     `html`-prefixed mirror wasn't reliably winning. The reviews widget
9693     lives inside <section id="bp-pdp-reviews">, so anchor on that ID:
9694     one ID beats any all-class Yotpo selector (1,1,0 > 0,9,0) no matter
9695     the chain length or load order, and it survives Yotpo renaming an
9696     internal class. */
9697  #bp-pdp-reviews .yotpo-review-title {
9698    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9699    font-size: 14px !important;
9700    font-style: normal !important;
9701    font-weight: 700 !important;
9702    line-height: 145% !important;
9703    letter-spacing: -0.14px !important;
9704    color: var(--bp-color-text, #171609) !important;
9705    margin: 0 !important;
9706  }
9707  .yotpo-review-date {
9708    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9709    font-size: 12px !important;
9710    font-weight: 400 !important;
9711    line-height: 145% !important;
9712    letter-spacing: -0.12px !important;
9713    color: var(--bp-color-text, #171609) !important;
9714    margin-left: auto !important;
9715    white-space: nowrap !important;
9716    flex-shrink: 0 !important;
9717  }
9718
9719  /* Review body text */
9720  .yotpo-review-body,
9721  .yotpo-review-body-text,
9722  .yotpo-review-content [class*="review-body"] {
9723    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9724    font-size: 14px !important;
9725    font-weight: 400 !important;
9726    line-height: 145% !important;
9727    letter-spacing: -0.14px !important;
9728    color: var(--bp-color-text, #171609) !important;
9729    margin: 0 0 8px !important;
9730  }
9731
9732  /* Inline custom question answers in the review body, e.g. "Fit: True to size" */
9733  .yotpo-review-custom-fields,
9734  .yotpo-review-custom-questions-answers,
9735  .yotpo-review-content [class*="custom-questions-answers"],
9736  .yotpo-review-content [class*="custom-fields"] {
9737    display: flex !important;
9738    flex-direction: column !important;
9739    gap: 2px !important;
9740    margin-bottom: 8px !important;
9741  }
9742  .yotpo-review-custom-field,
9743  .yotpo-review-content [class*="custom-field"]:not([class*="label"]):not([class*="value"]) {
9744    display: flex !important;
9745    gap: 4px !important;
9746    align-items: baseline !important;
9747    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9748    font-size: 14px !important;
9749    line-height: 145% !important;
9750    color: var(--bp-color-text, #171609) !important;
9751  }
9752  .yotpo-review-custom-field-label,
9753  .yotpo-review-content [class*="custom-field-label"],
9754  .yotpo-review-content [class*="field-label"] {
9755    font-weight: 600 !important;
9756    letter-spacing: -0.14px !important;
9757  }
9758  .yotpo-review-custom-field-value,
9759  .yotpo-review-content [class*="custom-field-value"],
9760  .yotpo-review-content [class*="field-value"] {
9761    font-weight: 400 !important;
9762    letter-spacing: -0.14px !important;
9763  }
9764
9765  /* Brand / store response block — the "Boston Proper" reply box */
9766  .yotpo-brand-response,
9767  .yotpo-review-response,
9768  .yotpo-review-content [class*="brand-response"],
9769  .yotpo-review-content [class*="review-response"] {
9770    background: rgba(23, 22, 9, 0.04) !important;
9771    border: none !important;
9772    border-radius: 0 !important;
9773    padding: 16px !important;
9774    margin: 12px 0 !important;
9775  }
9776  .yotpo-brand-response-header,
9777  .yotpo-brand-response-name,
9778  [class*="brand-response"] [class*="header"],
9779  [class*="brand-response"] [class*="name"],
9780  [class*="review-response"] [class*="header"],
9781  [class*="review-response"] [class*="name"] {
9782    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9783    font-size: 14px !important;
9784    font-weight: 600 !important;
9785    line-height: 145% !important;
9786    letter-spacing: -0.14px !important;
9787    color: var(--bp-color-text, #171609) !important;
9788    margin: 0 0 8px !important;
9789  }
9790  .yotpo-brand-response-body,
9791  [class*="brand-response"] [class*="body"],
9792  [class*="review-response"] [class*="body"] {
9793    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9794    font-size: 14px !important;
9795    font-weight: 400 !important;
9796    line-height: 145% !important;
9797    letter-spacing: -0.14px !important;
9798    color: var(--bp-color-text, #171609) !important;
9799    margin: 0 !important;
9800  }
9801
9802  /* "Was this review helpful?" row — right-aligned, Body/XSmall Book */
9803  .yotpo-helpful,
9804  .yotpo-helpful-question,
9805  .yotpo-review-content [class*="helpful"]:not([class*="icon"]):not(svg):not(path) {
9806    display: flex !important;
9807    align-items: center !important;
9808    gap: 8px !important;
9809    justify-content: flex-end !important;
9810    margin-top: 12px !important;
9811    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9812    font-size: 12px !important;
9813    font-weight: 400 !important;
9814    line-height: 145% !important;
9815    letter-spacing: -0.12px !important;
9816    color: var(--bp-color-text, #171609) !important;
9817  }
9818
9819  /* =================================================================
9820     Yotpo v3 confirmed class names (from live widget HTML inspection).
9821     These selectors fill the gap between the generic patterns above
9822     and the actual class names Yotpo ships in the rendered DOM.
9823     ================================================================= */
9824
9825  /* ---- Tabs row (.ugc-storefront-widgets-tabs-container__tab) ---- */
9826  .ugc-storefront-widgets-tabs-container {
9827    display: flex !important;
9828    border-bottom: 1px solid rgba(23, 22, 9, 0.12) !important;
9829    margin-bottom: 0 !important;
9830    padding: 0 !important;
9831    background: transparent !important;
9832  }
9833  /* Tab: Body/Bold/Medium — inactive uses 40% opacity to indicate unselected state.
9834     Yotpo's injected rule uses 4 chained classes (0,4,0) + !important and hardcodes
9835     'Futura PT' directly (not via a variable, so the --primary-font-family fix doesn't
9836     reach it). Doubling the tab class pushes our specificity to (0,5,0) to win. */
9837  .ugc-storefront-widgets-tabs-container__tab,
9838  .yotpo-widget-override-css .yotpo-main-widget-layout .ugc-storefront-widgets-tabs-container .ugc-storefront-widgets-tabs-container__tab.ugc-storefront-widgets-tabs-container__tab {
9839    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9840    font-size: 17px !important;
9841    font-weight: 775 !important;
9842    line-height: 145% !important;
9843    letter-spacing: -0.17px !important;
9844    color: var(--bp-color-text, #171609) !important;
9845    background: none !important;
9846    border: none !important;
9847    border-bottom: 2px solid transparent !important;
9848    padding: 0 0 12px !important;
9849    margin-right: 24px !important;
9850    margin-bottom: -1px !important;
9851    cursor: pointer !important;
9852    text-transform: none !important;
9853  }
9854  .ugc-storefront-widgets-tabs-container__tab.selected,
9855  .ugc-storefront-widgets-tabs-container__tab[aria-selected="true"] {
9856    color: var(--bp-color-text, #171609) !important;
9857    border-bottom-color: var(--bp-color-text, #171609) !important;
9858  }
9859
9860  /* ---- Summary row container: centered flex with score group + divider + CTA ---- */
9861  /* Yotpo v3 uses several possible wrapper class names for the overall rating summary.
9862     Cover all common patterns so the row is centered regardless of exact DOM shape. */
9863  /* NOTE the :not([class*="drawer"]) guard: the broad [class*="reviews-summary"]
9864     match also hit the AI reviews-summary DRAWER (.yotpo-reviews-summary-drawer-
9865     container), forcing its header/body/footer into a centered flex-wrap row and
9866     scattering the panel. Exclude the drawer so it keeps Yotpo's native column
9867     layout (styled separately above). */
9868  .yotpo-main-widget-bottom-line,
9869  .yotpo-reviews-summary,
9870  .yotpo-bottom-line-wrapper,
9871  .yotpo-bottom-line-inner,
9872  [class*="main-widget-bottom-line"],
9873  [class*="reviews-summary"]:not([class*="drawer"]) {
9874    display: flex !important;
9875    align-items: center !important;
9876    justify-content: center !important;
9877    gap: 40px !important;
9878    padding: 24px 0 !important;
9879    background: transparent !important;
9880    flex-wrap: wrap !important;
9881  }
9882
9883  /* Left group: score number + star row + count — laid out as a row with gap */
9884  .yotpo-bottom-line-left-panel,
9885  [class*="bottom-line-left-panel"] {
9886    display: flex !important;
9887    align-items: center !important;
9888    gap: 12px !important;
9889    flex-shrink: 0 !important;
9890  }
9891
9892  /* Big score number */
9893  .yotpo-bottom-line-score,
9894  .yotpo-bottom-line-left-panel.yotpo-bottom-line-score {
9895    font-family: var(--bp-font-display, "Signifier"), "Times New Roman", serif !important;
9896    font-size: 56px !important;
9897    font-weight: 300 !important;
9898    line-height: 1 !important;
9899    color: var(--bp-color-text, #171609) !important;
9900    letter-spacing: -1px !important;
9901  }
9902  /* Stars + count stacked vertically inside the left group */
9903  .yotpo-bottom-line-right-panel,
9904  [class*="bottom-line-right-panel"] {
9905    display: flex !important;
9906    flex-direction: column !important;
9907    align-items: flex-start !important;
9908    gap: 2px !important;
9909  }
9910  .yotpo-bottom-line-basic-text,
9911  .yotpo-bottom-line-text.yotpo-bottom-line-basic-text {
9912    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9913    font-size: 12px !important;
9914    font-weight: 500 !important;
9915    line-height: 145% !important;
9916    letter-spacing: -0.12px !important;
9917    color: var(--bp-color-text, #171609) !important;
9918  }
9919
9920  /* "Write a Review" primary CTA.
9921     The gap between the left group and the button is 40px (set on the
9922     container above). We don't use a border trick here because the button
9923     background would start AT the border, leaving no visible space.
9924     Instead, a ::before pseudo-element on the button acts as the divider. */
9925  button#yotpo-main-widget-btn,
9926  .yotpo-new-review-btn {
9927    background: var(--bp-color-text, #171609) !important;
9928    color: var(--bp-color-cta-text, #FDFFFA) !important;
9929    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9930    font-size: 14px !important;
9931    font-weight: 500 !important;
9932    letter-spacing: -0.14px !important;
9933    padding: 14px 28px !important;
9934    border: none !important;
9935    border-radius: 0 !important;
9936    cursor: pointer !important;
9937    text-transform: none !important;
9938    transition: opacity 0.15s !important;
9939    flex-shrink: 0 !important;
9940    position: relative !important;
9941  }
9942  button#yotpo-main-widget-btn:hover,
9943  .yotpo-new-review-btn:hover { opacity: 0.85 !important; }
9944
9945  /* Vertical divider — rendered as a pseudo-element 20px to the left of the button */
9946  button#yotpo-main-widget-btn::before,
9947  .yotpo-new-review-btn::before {
9948    content: '' !important;
9949    position: absolute !important;
9950    left: -20px !important;
9951    top: 50% !important;
9952    transform: translateY(-50%) !important;
9953    width: 1px !important;
9954    height: 52px !important;
9955    background: rgba(23, 22, 9, 0.2) !important;
9956    pointer-events: none !important;
9957  }
9958  /* Empty state (product has no reviews): Yotpo centers the "Write a Review"
9959     button with NO rating-summary group to its left, so the divider above is
9960     an orphan vertical line beside the button. Yotpo adds `.empty-state` to the
9961     button then, so drop the pseudo-divider in that case (QA: Brooke). */
9962  button#yotpo-main-widget-btn.empty-state::before,
9963  .yotpo-new-review-btn.empty-state::before {
9964    content: none !important;
9965    display: none !important;
9966  }
9967
9968  /* ---- Review card: left panel (reviewer) / center+right panels (content) ---- */
9969  .yotpo-review-left-panel {
9970    display: flex !important;
9971    flex-direction: column !important;
9972    align-items: flex-start !important;
9973    gap: 2px !important;
9974  }
9975  .yotpo-review-center-panel {
9976    display: flex !important;
9977    flex-direction: column !important;
9978    gap: 0 !important;
9979  }
9980  /* If Yotpo renders a 3rd panel (right-panel) as a sibling, keep it
9981     in the right column so it stacks below center-panel rather than
9982     wrapping back to column 1. */
9983  .yotpo-review-right-panel {
9984    display: flex !important;
9985    flex-direction: column !important;
9986    gap: 0 !important;
9987    grid-column: 2 !important;
9988  }
9989
9990  /* ---- Review body: confirmed class from live HTML ---- */
9991  .yotpo-read-more-text,
9992  .yotpo-review-wrapper .yotpo-read-more-text {
9993    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
9994    font-size: 14px !important;
9995    font-weight: 400 !important;
9996    line-height: 145% !important;
9997    letter-spacing: -0.14px !important;
9998    color: var(--bp-color-text, #171609) !important;
9999    margin: 0 0 8px !important;
10000  }
10001  /* "Read more" expand link */
10002  .yotpo-read-more-link,
10003  .yotpo-review-wrapper [class*="read-more"] a {
10004    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
10005    font-size: 13px !important;
10006    font-weight: 500 !important;
10007    color: var(--bp-color-text, #171609) !important;
10008    text-decoration: underline !important;
10009  }
10010
10011  /* ---- Date: confirmed class .yotpo-date-format ---- */
10012  .yotpo-date-format {
10013    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
10014    font-size: 12px !important;
10015    font-weight: 400 !important;
10016    line-height: 145% !important;
10017    letter-spacing: -0.12px !important;
10018    color: var(--bp-color-text, #171609) !important;
10019  }
10020
10021  /* ---- Helpful votes: text + number ---- */
10022  .yotpo-review-votes-text {
10023    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
10024    font-size: 12px !important;
10025    font-weight: 400 !important;
10026    letter-spacing: -0.12px !important;
10027    color: var(--bp-color-text, #171609) !important;
10028  }
10029  .yotpo-review-votes-number {
10030    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
10031    font-size: 12px !important;
10032    font-weight: 500 !important;
10033    letter-spacing: -0.12px !important;
10034    color: var(--bp-color-text, #171609) !important;
10035  }
10036
10037  /* ---- Reviews + Q&A empty states --------------------------------
10038     Yotpo's injected rule targets .yotpo-title-text inside any
10039     [class*="-empty-state"] with var(--my-third-color) at (0,4,0).
10040     --my-third-color is undefined on our end so it renders invisible.
10041     Doubling .yotpo-title-text pushes our specificity to (0,5,0). */
10042  .yotpo-qna-empty-state,
10043  [class*="-empty-state"] {
10044    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
10045    font-size: 14px !important;
10046    font-weight: 400 !important;
10047    color: var(--bp-color-text, #171609) !important;
10048    text-align: center !important;
10049    padding: 32px 0 !important;
10050    align-items: center !important;
10051  }
10052  /* Center the empty-state ICON too. text-align:center only centers the icon
10053     when Yotpo renders the SVG inline (the "Tell Us Everything" variant). Other
10054     variants (e.g. "We're Looking For Stars") render the SVG as display:block /
10055     lay the container out as flex-start, so the icon left-aligns (QA: Brooke
10056     8/20). margin:auto centers it in both a block and a flex container; the
10057     align-items above is a harmless no-op unless Yotpo uses flex. */
10058  .yotpo-qna-empty-state > svg,
10059  [class*="-empty-state"] > svg {
10060    display: block !important;
10061    margin-left: auto !important;
10062    margin-right: auto !important;
10063  }
10064  .yotpo-widget-override-css .yotpo-main-widget-layout [class*="yotpo-main-"] [class*="-empty-state"] .yotpo-title-text.yotpo-title-text,
10065  .yotpo-widget-override-css .yotpo-main-widget-layout [class*="yotpo-main-"] [class*="-empty-state"] .yotpo-body-text.yotpo-body-text {
10066    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
10067    font-size: 14px !important;
10068    font-weight: 400 !important;
10069    color: var(--bp-color-text, #171609) !important;
10070  }
10071  button[class*="yotpo-ask-question-btn"] {
10072    background: var(--bp-color-text, #171609) !important;
10073    color: var(--bp-color-cta-text, #FDFFFA) !important;
10074    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
10075    font-size: 14px !important;
10076    font-weight: 500 !important;
10077    letter-spacing: -0.14px !important;
10078    padding: 14px 28px !important;
10079    border: none !important;
10080    border-radius: 0 !important;
10081    cursor: pointer !important;
10082    text-transform: none !important;
10083  }
10084  button[class*="yotpo-ask-question-btn"] span {
10085    font-family: var(--bp-font-body, "Messina Sans VF"), system-ui, sans-serif !important;
10086    padding: 0 !important;
10087  }
10088  button[class*="yotpo-ask-question-btn"]:hover { opacity: 0.85 !important; }
10089
10090  /* ---- Broad font-family catch-all for Yotpo widget instances ------
10091     Yotpo injects its own stylesheet (Futura PT / system defaults) and
10092     sometimes inline styles. This rule forces Messina Sans VF on every
10093     text node inside either widget wrapper. Specific overrides above
10094     (e.g. `.yotpo-bottom-line-score` → Signifier display face) still
10095     win because they have equal or higher specificity and appear later
10096     in the stylesheet.
10097
10098     Yotpo's injected CSS resolves font via its own --primary-font-family
10099     and --secondary-font-family variables. Redefining them on the widget
10100     root makes Yotpo's own !important rules use Messina Sans VF — no
10101     specificity fight needed. */
10102  .yotpo-widget-instance,
10103  .bp-yotpo-reviews {
10104    --primary-font-family: 'Messina Sans VF', system-ui, sans-serif;
10105    --secondary-font-family: 'Messina Sans VF', system-ui, sans-serif;
10106  }
10107  .yotpo-widget-instance *,
10108  .bp-yotpo-reviews * {
10109    font-family: var(--bp-font-body, 'Messina Sans VF', system-ui, sans-serif) !important;
10110  }
10111  /* Re-pin the display-face elements that should stay as Signifier */
10112  .yotpo-bottom-line-score,
10113  .yotpo-bottom-line-left-panel.yotpo-bottom-line-score {
10114    font-family: var(--bp-font-display, 'Signifier', 'Times New Roman', serif) !important;
10115  }
10116
10117  /* ---- "Let us know what you think" / write-review form heading ----
10118     Yotpo v3 renders the write-review section header with several
10119     possible class names depending on review count (first-review state
10120     vs. existing reviews). Body/Bold/Medium spec from Figma. */
10121  .yotpo-headline,
10122  .yotpo-write-review-header,
10123  .yotpo-write-review-title,
10124  .yotpo-first-review-headline,
10125  [class*="write-review"] [class*="title"],
10126  [class*="write-review"] [class*="header"],
10127  [class*="write-review"] [class*="headline"],
10128  [class*="first-review"] [class*="headline"],
10129  [class*="submission"] [class*="title"],
10130  .yotpo-modal-header-title,
10131  .yotpo-form-title {
10132    font-family: var(--bp-font-body, 'Messina Sans VF', system-ui, sans-serif) !important;
10133    font-size: 17px !important;
10134    font-weight: 775 !important;
10135    line-height: 145% !important;
10136    letter-spacing: -0.17px !important;
10137    color: var(--bp-color-text, #171609) !important;
10138    text-transform: none !important;
10139  }
10140
10141  /* ---- Alternate Yotpo tab selectors (v2-legacy + v3 modal tabs) ---
10142     `.ugc-storefront-widgets-tabs-container__tab` covers the main
10143     Reviews/Q&A tab bar. These additional selectors cover older nav
10144     patterns and the tab bar inside the write-review modal. */
10145  .yotpo-nav-tab,
10146  .yotpo-nav .yotpo-nav-content,
10147  [class*="yotpo"][class*="-tab"]:not([class*="container"]) {
10148    font-family: var(--bp-font-body, 'Messina Sans VF', system-ui, sans-serif) !important;
10149    text-transform: none !important;
10150  }
10151</style>
10152<script>
10153  (function () {
10154    /* morph.js resets data-current-checked from server HTML after every async
10155       variant fetch, so we cannot rely on the onBeforeUpdate hook preserving it.
10156       Instead we store the user's selection on the variant-picker element itself
10157       — morph uses childrenOnly: true so the root element's JS properties are
10158       never touched — then re-enforce data-current-checked after every morph. */
10159
10160    // On user click: record selection AND apply data-current-checked immediately
10161    // so the pill moves without waiting for the async fetch + morph cycle.
10162    document.addEventListener('change', function (e) {
10163      var input = e.target;
10164      if (!(input instanceof HTMLInputElement) || input.type !== 'radio') return;
10165      var picker = input.closest('variant-picker');
10166      if (!picker) return;
10167      var fieldset = input.closest('fieldset');
10168      if (!fieldset) return;
10169      var idx = fieldset.dataset.fieldsetIndex;
10170      if (idx === undefined || idx === '') return;
10171
10172      if (!picker._bpSel) picker._bpSel = {};
10173      picker._bpSel[idx] = {
10174        id: input.dataset.optionValueId || '',
10175        text: input.value,
10176      };
10177
10178      // Instant visual feedback — update data-current-checked now so the
10179      // selected button highlights immediately on click, before the fetch resolves.
10180      fieldset.querySelectorAll('input[type="radio"]').forEach(function (inp) {
10181        inp.dataset.currentChecked = inp === input ? 'true' : 'false';
10182      });
10183
10184      // Immediate legend update (before the fetch completes).
10185      var swatch = fieldset.querySelector('.variant-option__swatch-value');
10186      if (swatch) swatch.textContent = input.value;
10187    });
10188
10189    // After morph: re-apply data-current-checked and fix the legend.
10190    document.addEventListener('variant:update', function () {
10191      document.querySelectorAll('variant-picker').forEach(function (picker) {
10192        if (!picker._bpSel) return;
10193        Object.keys(picker._bpSel).forEach(function (idx) {
10194          var sel = picker._bpSel[idx];
10195          var fieldset = picker.querySelector('fieldset[data-fieldset-index="' + idx + '"]');
10196          if (!fieldset) return;
10197
10198          fieldset.querySelectorAll('input[type="radio"]').forEach(function (input) {
10199            input.dataset.currentChecked = input.dataset.optionValueId === sel.id ? 'true' : 'false';
10200          });
10201
10202          var swatch = fieldset.querySelector('.variant-option__swatch-value');
10203          if (swatch) swatch.textContent = sel.text;
10204        });
10205      });
10206    });
10207
10208    /* Toggle `[data-bp-sold-out]` on every <add-to-cart-component>. The CSS
10209       above uses that attribute to hide the ATC button — but the button may
10210       ONLY be hidden when the BP Notify Me block actually replaces it, i.e.
10211       the variant is RESTOCK-ELIGIBLE. Hiding it for every sold-out variant
10212       (as this did before) left the buy box EMPTY on a sold-out-but-not-
10213       eligible variant — e.g. one with inbound restock scheduled — because
10214       Notify Me doesn't render for it and its inline `display:''` can't beat
10215       this rule's `!important` (Ernie 7/22, both the "button disappears" and
10216       "Notify shows anytime OOS" tickets).
10217
10218       Restock-eligibility is read from the SAME per-variant table the Notify
10219       Me block embeds (blocks/bp-notify-me-button.liquid), so the two stay
10220       consistent by construction: eligible → hide button, Notify Me shows;
10221       not eligible → keep Horizon's disabled "Sold out" button. */
10222    function bpNotifyTable() {
10223      var el = document.querySelector('[id^="bp-notify-variants-"]');
10224      if (!el) return null;
10225      try { return JSON.parse(el.textContent || '{}'); } catch (_) { return null; }
10226    }
10227    function bpRestockEligible(vid) {
10228      var table = bpNotifyTable();
10229      var entry = table && table[String(vid)];
10230      if (!entry) return false;
10231      var available = entry.available !== false;
10232      var gates = entry.gates || {};
10233      var currentInv = Number(gates.currentInv) || 0;
10234      var inboundInv = Number(gates.inboundInv) || 0;
10235      // Identical gate to bp-notify-me-button.liquid's restockEligible.
10236      return !available && !!entry.fullPrice && currentInv <= 0 && inboundInv <= 0;
10237    }
10238    function syncSoldOut(vid) {
10239      var eligible = bpRestockEligible(vid);
10240      document.querySelectorAll('.product-information add-to-cart-component').forEach(function (comp) {
10241        if (eligible) comp.setAttribute('data-bp-sold-out', '');
10242        else comp.removeAttribute('data-bp-sold-out');
10243      });
10244    }
10245    /* Initial page load — gate on the current variant so a direct load of a
10246       sold-out-but-not-eligible variant keeps Horizon's disabled "Sold out"
10247       button instead of an empty box. */
10248    (function initSoldOut() {
10249      var input = document.querySelector('.product-information input[name="id"]');
10250      var vid = input && input.value;
10251      if (vid) syncSoldOut(vid);
10252    })();
10253    document.addEventListener('variant:update', function (e) {
10254      var d = e && e.detail;
10255      var vid = d && (
10256        (d.resource && d.resource.id) ||
10257        (d.variant && d.variant.id) ||
10258        d.id
10259      );
10260      if (vid) syncSoldOut(vid);
10261    });
10262  })();
10263</script>
10263<script>
10264(function () {
10265  if (window.__bpPdpSwap) return;
10266  window.__bpPdpSwap = true;
10267
10268  var TRACKING_PREFIXES = [
10269    'utm_', 'gclid', 'gad_', 'nb_', 'campaign', 'adgroup',
10270    'keyword', 'matchtype', 'network', 'device', 'source', 'gbraid'
10271  ];
10272
10273  // Silent in production. Enable diagnostics (fetch/swap timings, cache
10274  // hits, prefetch) by setting window.bpPdpSwapDebug = true or visiting
10275  // with ?bp-pdp-swap-debug=1.
10276  if (typeof window.bpPdpSwapDebug === 'undefined') {
10277    window.bpPdpSwapDebug = false;
10278    try {
10279      if (new URLSearchParams(location.search).get('bp-pdp-swap-debug') === '1') {
10280        window.bpPdpSwapDebug = true;
10281      }
10282    } catch (e) {}
10283  }
10284  function log() {
10285    if (!window.bpPdpSwapDebug) return;
10286    var args = ['[bp-pdp-swap]'].concat(Array.prototype.slice.call(arguments));
10287    console.log.apply(console, args);
10288  }
10289
10290  function preserveTracking(targetPath) {
10291    try {
10292      var src = new URL(window.location.href);
10293      var dst = new URL(targetPath, window.location.origin);
10294      src.searchParams.forEach(function (val, key) {
10295        var keep = TRACKING_PREFIXES.some(function (p) { return key.indexOf(p) === 0; });
10296        if (keep && !dst.searchParams.has(key)) dst.searchParams.set(key, val);
10297      });
10298      return dst.pathname + (dst.search || '') + (dst.hash || '');
10299    } catch (e) {
10300      return targetPath;
10301    }
10302  }
10303
10304  function reexecuteScripts(root) {
10305    var scripts = root.querySelectorAll('script');
10306    log('re-executing', scripts.length, 'scripts');
10307    scripts.forEach(function (oldScript) {
10308      var s = document.createElement('script');
10309      for (var i = 0; i < oldScript.attributes.length; i++) {
10310        var attr = oldScript.attributes[i];
10311        s.setAttribute(attr.name, attr.value);
10312      }
10313      var hasSrc = oldScript.hasAttribute('src');
10314      var typeAttr = (oldScript.getAttribute('type') || '').toLowerCase();
10315      var isJsType = !typeAttr || typeAttr === 'text/javascript' || typeAttr === 'application/javascript';
10316      if (!hasSrc && isJsType && oldScript.textContent) {
10317        // Wrap inline JS in an IIFE so top-level `const`/`let`/`class`
10318        // declarations are scoped to the wrapper. Without this, the
10319        // re-executed script collides with the original page-load
10320        // declarations and throws "Identifier 'X' has already been
10321        // declared" — which then aborts the rest of reexecuteScripts.
10322        // The try/catch keeps one bad script from breaking the others.
10323        s.text = '(function(){try{' + oldScript.textContent + '}catch(e){console.warn("[bp-pdp-swap] inline script error",e);}}).call(this);';
10324      } else {
10325        s.text = oldScript.textContent;
10326      }
10327      try {
10328        oldScript.parentNode.replaceChild(s, oldScript);
10329      } catch (e) {
10330        console.warn('[bp-pdp-swap] script swap failed', e);
10331      }
10332    });
10333  }
10334
10335  function updateMetaFromDoc(doc) {
10336    try {
10337      var newTitle = doc.querySelector('title');
10338      if (newTitle) document.title = newTitle.textContent;
10339      ['description', 'og:title', 'og:description', 'og:image', 'og:url'].forEach(function (n) {
10340        var sel = n.indexOf('og:') === 0 ? 'meta[property="' + n + '"]' : 'meta[name="' + n + '"]';
10341        var src = doc.querySelector(sel);
10342        var dst = document.querySelector(sel);
10343        if (src && dst) dst.setAttribute('content', src.getAttribute('content') || '');
10344      });
10345      var canonSrc = doc.querySelector('link[rel="canonical"]');
10346      var canonDst = document.querySelector('link[rel="canonical"]');
10347      if (canonSrc && canonDst) canonDst.setAttribute('href', canonSrc.getAttribute('href') || '');
10348    } catch (e) { log('meta update failed', e); }
10349  }
10350
10351  // Snapshot the shopper's non-colour option selections (e.g. Size)
10352  // from the live Horizon variant picker, so a colour swap can
10353  // re-apply them on the freshly-swapped product. Keyed by the
10354  // option's display name (the legend prefix) so it survives the
10355  // section-suffixed input names.
10356  function captureVariantOptions() {
10357    var out = [];
10358    try {
10359      var scope = document.getElementById('MainContent') || document;
10360      scope.querySelectorAll('variant-picker input[type="radio"]:checked').forEach(function (input) {
10361        var fs = input.closest('fieldset');
10362        var pfx = fs && fs.querySelector('.variant-option__swatch-prefix');
10363        var name = pfx ? pfx.textContent.trim() : (input.name || '');
10364        var lc = name.toLowerCase();
10365        if (lc === 'color' || lc === 'colour') return; // colour changes with the swap
10366        out.push({ option: name, value: input.value });
10367      });
10368    } catch (e) { log('capture options failed', e); }
10369    return out;
10370  }
10371
10372  // Re-select the captured options on the swapped-in picker. Firing
10373  // `change` lets Horizon's variant-picker.js update price / ATC /
10374  // availability for the chosen size — no full reload.
10375  function restoreVariantOptions(root, saved) {
10376    if (!root || !saved || !saved.length) return;
10377    saved.forEach(function (sel) {
10378      try {
10379        var fieldsets = root.querySelectorAll('variant-picker fieldset.variant-option');
10380        var target = null;
10381        for (var i = 0; i < fieldsets.length; i++) {
10382          var pfx = fieldsets[i].querySelector('.variant-option__swatch-prefix');
10383          var name = pfx ? pfx.textContent.trim() : '';
10384          if (name && sel.option && name.toLowerCase() === sel.option.toLowerCase()) {
10385            target = fieldsets[i];
10386            break;
10387          }
10388        }
10389        if (!target) return;
10390        var radios = target.querySelectorAll('input[type="radio"]');
10391        for (var j = 0; j < radios.length; j++) {
10392          if (radios[j].value === sel.value) {
10393            if (!radios[j].checked) {
10394              radios[j].checked = true;
10395              radios[j].dispatchEvent(new Event('input', { bubbles: true }));
10396              radios[j].dispatchEvent(new Event('change', { bubbles: true }));
10397            }
10398            break;
10399          }
10400        }
10401      } catch (e) { log('restore option failed', e); }
10402    });
10403  }
10404
10405  function perfNow() {
10406    try { return (window.performance && performance.now) ? performance.now() : Date.now(); }
10407    catch (e) { return Date.now(); }
10408  }
10409
10410  // Primary gallery image of a parsed section/root — used to preload the
10411  // incoming colour's main image BEFORE the swap so it paints from cache
10412  // with no blank frame (the main cause of the colour-change flash).
10413  function firstGalleryImg(root) {
10414    if (!root) return '';
10415    try {
10416      var img = root.querySelector('.bp-pdp-gallery__img, [data-bp-pdp-rail] img, .product-information__media img');
10417      if (!img) return '';
10418      return img.getAttribute('src') || (img.getAttribute('srcset') || '').trim().split(' ')[0] || '';
10419    } catch (e) { return ''; }
10420  }
10421  function preloadImg(url) {
10422    return new Promise(function (resolve) {
10423      if (!url) return resolve();
10424      var im = new Image();
10425      var done = false;
10426      var go = function () { if (done) return; done = true; resolve(); };
10427      im.onload = go;
10428      im.onerror = go;
10429      im.src = url;
10430      if (im.decode) { try { im.decode().then(go).catch(go); } catch (e) {} }
10431      setTimeout(go, 400); // never block the swap on a slow image
10432    });
10433  }
10434
10435  // The product buy box + gallery live in the JSON-template `main`
10436  // section (type: product-information). Learn its wrapper id once so a
10437  // colour swap fetches JUST that section (?section_id=template--N__main)
10438  // instead of the whole document — a fraction of the bytes + server
10439  // render. Every colourway shares templates/product.json, so the id is
10440  // stable across the family and applies to the sibling URL too.
10441  function getMainSectionId() {
10442    if (window.__bpPdpMainSectionId) return window.__bpPdpMainSectionId;
10443    try {
10444      var stored = sessionStorage.getItem('bpPdpMainSectionId');
10445      if (stored) { window.__bpPdpMainSectionId = stored; return stored; }
10446    } catch (e) {}
10447    var main = document.getElementById('MainContent');
10448    if (!main) return null;
10449    var wrap = null;
10450    try { wrap = main.querySelector('[id^="shopify-section-"]:has(.product-information)'); }
10451    catch (e) { wrap = null; } // :has() unsupported — fall through to scan
10452    if (!wrap) {
10453      var all = main.querySelectorAll('[id^="shopify-section-"]');
10454      for (var i = 0; i < all.length; i++) {
10455        if (all[i].querySelector('.product-information')) { wrap = all[i]; break; }
10456      }
10457    }
10458    if (!wrap) return null;
10459    var id = wrap.id.replace(/^shopify-section-/, '');
10460    window.__bpPdpMainSectionId = id;
10461    try { sessionStorage.setItem('bpPdpMainSectionId', id); } catch (e) {}
10462    return id;
10463  }
10464
10465  // Section-scoped fetch URL — also the cache key. Tracking params ride
10466  // the pushState (display) URL, NOT the fetch, so hover-prefetch and
10467  // click resolve to the exact same key (the old cross-surface prefetch
10468  // bug was a key mismatch — do not repeat it).
10469  function sectionFetchUrl(pathOnly, sectionId) {
10470    return pathOnly + '?section_id=' + encodeURIComponent(sectionId);
10471  }
10472
10473  // In-memory cache of section-scoped sibling HTML, keyed by fetch URL.
10474  var htmlCache = (typeof Map !== 'undefined') ? new Map() : null;
10475  var CACHE_TTL = 5 * 60 * 1000; // 5 min
10476  var prefetchCtrls = {};
10477
10478  function cacheGet(key) {
10479    if (!htmlCache) return null;
10480    var hit = htmlCache.get(key);
10481    if (!hit) return null;
10482    if ((perfNow() - hit.t) > CACHE_TTL) { htmlCache.delete(key); return null; }
10483    return hit.html;
10484  }
10485  function cacheSet(key, html) {
10486    if (htmlCache) htmlCache.set(key, { html: html, t: perfNow() });
10487  }
10488  function clearHtmlCache() { if (htmlCache) htmlCache.clear(); }
10489
10490  // Warm the cache on intent (hover / focus / idle). One request per
10491  // handle; skips if already cached or in flight.
10492  function prefetchHandle(pathOnly) {
10493    if (!htmlCache || !pathOnly) return;
10494    // Full-page cache key — colour swaps swap the whole #MainContent, so the
10495    // click reads the FULL sibling page from cache (same key as the swap's
10496    // fetchUrl when opts.fullPage). Warms the whole colourway page + its
10497    // primary image at idle so the click is instant and flash-free.
10498    var key = pathOnly;
10499    if (cacheGet(key) || prefetchCtrls[key]) return;
10500    var ctrl = ('AbortController' in window) ? new AbortController() : null;
10501    prefetchCtrls[key] = ctrl || true;
10502    fetch(key, {
10503      credentials: 'same-origin',
10504      headers: { 'Accept': 'text/html' },
10505      signal: ctrl ? ctrl.signal : undefined
10506    })
10507      .then(function (r) { return r.ok ? r.text() : null; })
10508      .then(function (html) {
10509        if (!html) return;
10510        cacheSet(key, html);
10511        log('prefetched', key);
10512        // Warm the incoming primary image too, so a hover-then-click swap
10513        // is flash-free (HTML + image both cached).
10514        try {
10515          var pdoc = new DOMParser().parseFromString(html, 'text/html');
10516          var pimg = firstGalleryImg(pdoc);
10517          if (pimg) { var warm = new Image(); warm.src = pimg; }
10518        } catch (e) {}
10519      })
10520      .catch(function () {})
10521      .then(function () { delete prefetchCtrls[key]; });
10522  }
10523
10524  // Title + canonical from the swapped-in section (a section_id response
10525  // carries no <head>, so updateMetaFromDoc can't run). Reads the
10526  // product name from the section's JSON-LD (bp-product-schema block).
10527  function updateMetaFromProduct(displayUrl, sectionId) {
10528    try {
10529      var scope = (sectionId && document.getElementById('shopify-section-' + sectionId)) || document;
10530      var ld = scope.querySelector('script[type="application/ld+json"]');
10531      if (ld && ld.textContent) {
10532        var data = JSON.parse(ld.textContent);
10533        if (data && data.name) document.title = data.name;
10534      }
10535    } catch (e) { log('meta title failed', e); }
10536    try {
10537      var canon = document.querySelector('link[rel="canonical"]');
10538      if (canon) canon.setAttribute('href', window.location.origin + displayUrl.split('?')[0].split('#')[0]);
10539    } catch (e) {}
10540  }
10541
10542  // Which sibling swatches are confirmed in-stock (visible, not --pending)
10543  // right now. Captured before a colour swap so we can reveal exactly those
10544  // on the re-rendered strip — the fresh strip renders its siblings
10545  // --pending (display:none) until bp-color-siblings re-fetches them, and a
10546  // click in that gap is the "have to click the colour twice" bug.
10547  function captureVisibleSiblings() {
10548    var out = {};
10549    try {
10550      var strip = document.querySelector('[data-bp-colors]');
10551      if (strip) {
10552        var items = strip.querySelectorAll('.bp-colors__item');
10553        for (var i = 0; i < items.length; i++) {
10554          if (!items[i].classList.contains('bp-colors__item--pending')) {
10555            var h = items[i].getAttribute('data-bp-color-handle');
10556            if (h) out[h] = true;
10557          }
10558        }
10559      }
10560    } catch (e) {}
10561    return out;
10562  }
10563  function revealSiblings(root, set) {
10564    if (!root || !set) return;
10565    try {
10566      var strip = root.querySelector('[data-bp-colors]');
10567      if (!strip) return;
10568      var pend = strip.querySelectorAll('.bp-colors__item--pending');
10569      for (var i = 0; i < pend.length; i++) {
10570        var h = pend[i].getAttribute('data-bp-color-handle');
10571        if (h && set[h]) pend[i].classList.remove('bp-colors__item--pending');
10572      }
10573    } catch (e) {}
10574  }
10575
10576  var inflight = null;
10577
10578  function swapToHandle(targetPath, opts) {
10579    if (!targetPath) return Promise.resolve();
10580    opts = opts || {};
10581    var displayUrl = preserveTracking(targetPath);
10582    var pathOnly = targetPath.split('?')[0].split('#')[0];
10583    var savedScrollY = window.scrollY || window.pageYOffset || 0;
10584    var sectionId = getMainSectionId();
10585
10586    if (inflight) {
10587      try { inflight.abort(); } catch (e) {}
10588    }
10589    var ctrl = ('AbortController' in window) ? new AbortController() : null;
10590    inflight = ctrl;
10591
10592    document.body.classList.add('bp-pdp-swapping');
10593
10594    // Colour swaps (opts.fullPage) swap the ENTIRE #MainContent so every
10595    // product-dependent section reflects the new colourway — buy box, How to
10596    // Wear It, You'll Also Love, Yotpo stars/reviews — the way a full reload
10597    // would, but AJAX + cross-faded. Other swaps stay section-scoped (just the
10598    // product section) for speed. Both cache by their fetch URL.
10599    var fullPage = !!opts.fullPage;
10600    var fetchUrl = (!fullPage && sectionId) ? sectionFetchUrl(pathOnly, sectionId) : pathOnly;
10601    var cached = cacheGet(fetchUrl);
10602    var tStart = perfNow();
10603    log('fetching', fetchUrl, cached ? '(cache hit)' : '');
10604
10605    var pending = cached
10606      ? Promise.resolve(cached)
10607      : fetch(fetchUrl, {
10608          credentials: 'same-origin',
10609          headers: { 'Accept': 'text/html' },
10610          signal: ctrl ? ctrl.signal : undefined
10611        }).then(function (r) {
10612          log('fetch status', r.status);
10613          if (!r.ok) throw new Error('HTTP ' + r.status);
10614          return r.text();
10615        }).then(function (html) {
10616          cacheSet(fetchUrl, html);
10617          return html;
10618        });
10619
10620    return pending
10621      .then(function (html) {
10622        log('fetch done in', Math.round(perfNow() - tStart), 'ms', cached ? '(cached)' : '');
10623        var doc = new DOMParser().parseFromString(html, 'text/html');
10624        var freshSection = (!fullPage && sectionId)
10625          ? (doc.getElementById('shopify-section-' + sectionId) || doc.querySelector('.shopify-section'))
10626          : null;
10627
10628        // Decode the incoming primary image before touching the DOM so
10629        // the swap reveals a ready image instead of a blank → pop flash.
10630        return preloadImg(firstGalleryImg(freshSection || doc)).then(function () {
10631          var tSwap = perfNow();
10632          var newRoot = null;
10633
10634          // Confirmed-in-stock siblings BEFORE the swap → revealed instantly on
10635          // the re-rendered strip so it never flashes hidden ("click twice").
10636          var visibleSiblings = opts.crossfade ? captureVisibleSiblings() : null;
10637
10638          // The DOM mutation itself. Kept in one function so it can run either
10639          // directly or inside a View-Transition callback (which must mutate
10640          // synchronously). Sets the closure `newRoot`.
10641          function performSwap() {
10642            if (sectionId && freshSection) {
10643              var liveSection = document.getElementById('shopify-section-' + sectionId);
10644              if (liveSection) {
10645                // Replace only the product section — the browser parses +
10646                // connects its custom elements; reexecuteScripts re-runs the
10647                // block IIFEs (same mechanism as before, smaller surface).
10648                liveSection.outerHTML = freshSection.outerHTML;
10649                newRoot = document.getElementById('shopify-section-' + sectionId);
10650              }
10651            }
10652            if (!newRoot) {
10653              // Fallback: full-#MainContent swap (id unresolved or response
10654              // wasn't section-scoped) — preserves the original behavior.
10655              var freshMain = doc.getElementById('MainContent');
10656              var liveMain = document.getElementById('MainContent');
10657              if (!freshMain || !liveMain) throw new Error('no #MainContent to swap');
10658              liveMain.outerHTML = freshMain.outerHTML;
10659              newRoot = document.getElementById('MainContent');
10660              updateMetaFromDoc(doc);
10661            }
10662            if (newRoot) {
10663              reexecuteScripts(newRoot);
10664              if (visibleSiblings) revealSiblings(newRoot, visibleSiblings);
10665            }
10666          }
10667
10668          // Everything that must run AFTER the DOM is swapped — meta, size
10669          // restore, and critically the `bp:pdp:swapped` event that tells the
10670          // OTHER product sections (How to Wear It, etc.) to re-render for the
10671          // new colour. This MUST run after performSwap, not just after the
10672          // call that schedules it: startViewTransition() runs its callback
10673          // asynchronously, so dispatching here synchronously (as before) fired
10674          // the event against the OLD DOM and those sections never updated —
10675          // the "How to Wear It doesn't switch" regression. On release
10676          // (no transition) performSwap is synchronous and this ran after it.
10677          function afterSwap() {
10678            log('swap applied in', Math.round(perfNow() - tSwap), 'ms', (opts.crossfade && allowMotion && document.startViewTransition) ? '(view-transition)' : '');
10679
10680            // Full-page swaps already updated meta from the parsed doc
10681            // (updateMetaFromDoc in performSwap); only the section-scoped path
10682            // needs the JSON-LD title/canonical fallback.
10683            if (!fullPage && sectionId) updateMetaFromProduct(displayUrl, sectionId);
10684
10685            // Re-apply the shopper's size on the swapped-in product so a
10686            // colour change doesn't reset it (QA 7/16). rAF lets the new
10687            // <variant-picker> upgrade + connect first.
10688            if (opts.restoreOptions && opts.restoreOptions.length && newRoot) {
10689              requestAnimationFrame(function () {
10690                restoreVariantOptions(newRoot, opts.restoreOptions);
10691              });
10692            }
10693
10694            var handle = (pathOnly.match(/\/products\/([^\/?#]+)/) || [])[1] || '';
10695            document.body.classList.remove('bp-pdp-swapping');
10696            if (opts.keepScroll) {
10697              // Colour swap = in-place content update, not a navigation.
10698              // Hold the shopper's scroll position so it doesn't read as a
10699              // full page reload.
10700              try { window.scrollTo(0, savedScrollY); } catch (e) {}
10701            } else {
10702              try {
10703                window.scrollTo({ top: 0, behavior: 'auto' });
10704              } catch (e) { window.scrollTo(0, 0); }
10705            }
10706
10707            document.dispatchEvent(new CustomEvent('bp:pdp:swapped', {
10708              detail: { handle: handle, url: displayUrl }
10709            }));
10710            log('done →', displayUrl);
10711          }
10712
10713          // Cross-fade the swap with the View Transitions API (colour swaps
10714          // only). The browser snapshots the old product area, applies the
10715          // swap, and cross-fades old→new — a smooth dissolve, not a hard
10716          // repaint/flash. Every colourway is prefetched at page load, so this
10717          // fires with no network wait ("preload all → instant cross-fade").
10718          // afterSwap() is chained off updateCallbackDone so the swapped-in DOM
10719          // is live before bp:pdp:swapped fires. Falls back to the
10720          // .bp-pdp-fade-in class when the API is absent (Firefox) or motion is
10721          // reduced.
10722          var allowMotion = !(window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches);
10723          if (opts.crossfade && allowMotion && document.startViewTransition) {
10724            var transition = document.startViewTransition(performSwap);
10725            return transition.updateCallbackDone.then(afterSwap, afterSwap);
10726          } else {
10727            performSwap();
10728            if (newRoot) newRoot.classList.add('bp-pdp-fade-in');
10729            afterSwap();
10730          }
10731        });
10732      })
10733      .catch(function (err) {
10734        document.body.classList.remove('bp-pdp-swapping');
10735        if (err && err.name === 'AbortError') return;
10736        console.warn('[bp-pdp-swap] swap failed', err);
10737        document.dispatchEvent(new CustomEvent('bp:pdp:swap-failed', {
10738          detail: { url: displayUrl, error: err }
10739        }));
10740      });
10741  }
10742
10743  function isSwapCandidate(anchor) {
10744    if (!anchor || !anchor.href) return false;
10745    var hrefAttr = anchor.getAttribute('href') || '';
10746    if (!hrefAttr || hrefAttr.charAt(0) === '#') return false;
10747    if (anchor.target && anchor.target !== '_self') return false;
10748    if (anchor.hasAttribute('download')) return false;
10749    var u;
10750    try { u = new URL(anchor.href, window.location.origin); } catch (e) { return false; }
10751    if (u.origin !== window.location.origin) return false;
10752    if (!/^\/products\//.test(u.pathname)) return false;
10753    var here = (window.location.pathname.match(/\/products\/[^\/?#]+/) || [''])[0];
10754    var there = (u.pathname.match(/\/products\/[^\/?#]+/) || [''])[0];
10755    if (here === there) return false;
10756    return true;
10757  }
10758
10759  document.addEventListener('click', function (e) {
10760    if (e.defaultPrevented) return;
10761    if (e.button !== 0) return;
10762    if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
10763
10764    var anchor = e.target.closest('a[href]');
10765    if (!anchor) return;
10766    // Anchors inside the quick-view drawer are handled by the drawer
10767    // itself (it swaps the sibling into the drawer, not the main page).
10768    if (anchor.closest('#quick-add-dialog, .quick-add-modal, .bp-qd')) return;
10769    if (!anchor.closest('[data-bp-colors], [data-bp-pdp-swap]')) return;
10770    if (!isSwapCandidate(anchor)) return;
10771
10772    e.preventDefault();
10773    var href = anchor.getAttribute('href');
10774    var preserved = preserveTracking(href);
10775    log('intercept click →', preserved);
10776    if (window.history && window.history.pushState) {
10777      window.history.pushState({ bpPdpSwap: true }, '', preserved);
10778    }
10779    // Colour-swatch swaps stay in place: keep the scroll position, carry the
10780    // shopper's size selection across, and cross-fade the change (View
10781    // Transitions) so it reads as a smooth dissolve, not a reload/flash.
10782    var isColorSwap = !!anchor.closest('[data-bp-colors]');
10783    swapToHandle(href, isColorSwap ? {
10784      keepScroll: true,
10785      crossfade: true,
10786      fullPage: true,
10787      restoreOptions: captureVariantOptions()
10788    } : undefined);
10789  }, true);
10790
10791  // Warm the section-scoped cache on intent so the click resolves with
10792  // no network. mouseover/focusin/touchstart all bubble, so one
10793  // delegated listener covers every swatch. prefetchHandle de-dupes.
10794  function onIntent(e) {
10795    var t = e.target;
10796    var anchor = t && t.closest ? t.closest('[data-bp-colors] a[href]') : null;
10797    if (!anchor) return;
10798    if (anchor.closest('#quick-add-dialog, .quick-add-modal, .bp-qd')) return;
10799    if (!isSwapCandidate(anchor)) return;
10800    prefetchHandle(anchor.getAttribute('href').split('?')[0].split('#')[0]);
10801  }
10802  ['mouseover', 'focusin', 'touchstart'].forEach(function (evt) {
10803    document.addEventListener(evt, onIntent, { passive: true });
10804  });
10805
10806  // Idle-preload EVERY colourway sibling after first paint ("preload all"):
10807  // the whole colour family shares one section id and is cached in-memory, so
10808  // once this runs, every swatch click — on this product or any colourway we
10809  // swap to — resolves from cache with no network. prefetchHandle also warms
10810  // each incoming primary image, so the click cross-fade is flash-free. The
10811  // 30-item cap is a runaway guard (INV5 families are far smaller); the swatch
10812  // anchors are all present in the DOM even while --pending, so this doesn't
10813  // depend on bp-color-siblings having finished revealing them.
10814  function idlePrefetchSiblings() {
10815    try {
10816      var anchors = document.querySelectorAll('[data-bp-colors] a[href]');
10817      var count = 0;
10818      for (var i = 0; i < anchors.length && count < 30; i++) {
10819        if (!isSwapCandidate(anchors[i])) continue;
10820        prefetchHandle(anchors[i].getAttribute('href').split('?')[0].split('#')[0]);
10821        count++;
10822      }
10823    } catch (e) {}
10824  }
10825  if ('requestIdleCallback' in window) {
10826    requestIdleCallback(idlePrefetchSiblings, { timeout: 3000 });
10827  } else {
10828    setTimeout(idlePrefetchSiblings, 1500);
10829  }
10830
10831  // Price / availability can drift after a cart change — drop the cache.
10832  // 'cart:update' is Horizon's stock event; 'cart:updated' is BP-internal.
10833  document.addEventListener('cart:update', clearHtmlCache);
10834  document.addEventListener('cart:updated', clearHtmlCache);
10835
10836  window.addEventListener('popstate', function () {
10837    if (!/^\/products\//.test(window.location.pathname)) return;
10838    swapToHandle(window.location.pathname + window.location.search);
10839  });
10840
10841  document.addEventListener('bp:pdp:swapped', function () {
10842    // Re-hydrate the swapped-in Yotpo widgets (stars + reviews). The full
10843    // #MainContent swap injects fresh widget markup for the new product, so
10844    // the SDK has to be poked to scan + render it. The MODERN widget SDK is
10845    // window.yotpoWidgetsContainer.initWidgets() — the old code only called the
10846    // legacy yotpo.refreshWidgets(), which no-ops on the new widget markup, so
10847    // stars/reviews never rendered after a colour swap.
10848    //
10849    // Call only the FIRST available API — don't stack the legacy
10850    // refreshWidgets() on top of initWidgets() (extra full re-scans). Firing
10851    // both back-to-back races two concurrent scans against the same
10852    // .yotpo-widget-instance nodes, which left some stars painted from one
10853    // pass and others stuck on the pre-render "full" placeholder (DEV-1587:
10854    // stars showing all-filled regardless of actual rating after a colour
10855    // swap). Same fix already applied in bp-quick-drawer.liquid — mirror it
10856    // here.
10857    try {
10858      var yotpoWidgets = document.querySelectorAll('.yotpo-widget-instance');
10859      yotpoWidgets.forEach(function (w) {
10860        w.removeAttribute('data-yotpo-element-loaded');
10861        w.removeAttribute('data-yotpo-widget-uuid');
10862      });
10863      if (window.yotpoWidgetsContainer && typeof window.yotpoWidgetsContainer.initWidgets === 'function') {
10864        window.yotpoWidgetsContainer.initWidgets();
10865      } else if (window.YotpoApi && typeof window.YotpoApi.refreshWidgets === 'function') {
10866        window.YotpoApi.refreshWidgets();
10867      } else if (window.Yotpo && window.Yotpo.API && typeof window.Yotpo.API.refreshWidgets === 'function') {
10868        window.Yotpo.API.refreshWidgets();
10869      } else if (window.yotpo && typeof window.yotpo.refreshWidgets === 'function') {
10870        window.yotpo.refreshWidgets();
10871      }
10872    } catch (e) {}
10873
10874    try {
10875      if (window.tfcapi && typeof window.tfcapi === 'function') {
10876        window.tfcapi('calculate');
10877      }
10878    } catch (e) {}
10879
10880    try {
10881      var script = document.querySelector('[data-bp-product-schema]');
10882      var newProduct = script && script.textContent ? JSON.parse(script.textContent) : null;
10883      if (newProduct && window.dataLayer && Array.isArray(window.dataLayer)) {
10884        window.dataLayer.push({ event: 'view_item', ecommerce: { items: [{
10885          item_id: newProduct.id, item_name: newProduct.title, price: newProduct.price
10886        }]}});
10887      }
10888    } catch (e) {}
10889  });
10890
10891  window.bpPdpSwap = swapToHandle;
10892})();
10893</script>
10893
10894
10895<style>
10896  .bp-pdp-swapping { cursor: progress; }
10897
10898  /* Colour-swap cross-fade via the View Transitions API. The browser
10899     snapshots the old page, we swap the product section, and it cross-fades
10900     old→new. Only the product area differs between colourways, so the root
10901     cross-fade reads as that area dissolving — the header/footer are
10902     identical old vs new, so they don't visibly change. Short + eased for a
10903     premium feel. Under prefers-reduced-motion the JS skips
10904     startViewTransition entirely, so no snapshot/animation runs. */
10905  ::view-transition-old(root),
10906  ::view-transition-new(root) { animation-duration: 0.26s; animation-timing-function: ease; }
10907
10908  /* Fallback (Firefox / no View-Transitions): fade the swapped-in section in
10909     so a colour change still reads as a transition, not a hard repaint. */
10910  @keyframes bpPdpFadeIn { from { opacity: 0; } to { opacity: 1; } }
10911  .bp-pdp-fade-in { animation: bpPdpFadeIn 0.22s ease both; }
10912  @media (prefers-reduced-motion: reduce) { .bp-pdp-fade-in { animation: none; } }
10913</style>
10913<script src="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-stl-drawer.js?v=94264581757947261801790713714" defer></script>
10913
10914    
10914<script src="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-mega-hover.js?v=154014205721503400101790713714" defer></script>
10914
10915
10916    
10917
10918    
10919      
10920    
10921    
10921<script>
10922      (function (w, d, s, l, i) {
10923        w[l] = w[l] || [];
10924        w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
10925        var f = d.getElementsByTagName(s)[0],
10926          j = d.createElement(s),
10927          dl = l != 'dataLayer' ? '&l=' + l : '';
10928        j.async = true;
10929        j.src =
10930          'https://sst.bostonproper.com/gtm.js?id=' +
10931          i +
10932          dl +
10933          '&gtm_auth=288FkNoOr_QXQEJ-WPHnww&gtm_preview=env-1&gtm_cookies_win=x';
10934        f.parentNode.insertBefore(j, f);
10935      })(window, document, 'script', 'dataLayer', 'GTM-NS3X79G');
10936    </script>
10936<script id="customizer-settings" type="application/json">
10937      {
10938        "final_sale_message": "Final Sale"
10939      }
10940    </script>
10940
10941
10942    
10942<script>window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.start');</script>
10942<meta name="facebook-domain-verification" content="9a5visacrvjynl4zpb4ys6j4byfwwp">
10943<meta id="shopify-digital-wallet" name="shopify-digital-wallet" content="/52960723110/digital_wallets/dialog">
10944<meta id="in-context-paypal-metadata" data-shop-id="52960723110" data-venmo-supported="false" data-environment="production" data-locale="en_US" data-paypal-v4="true" data-currency="USD">
10945<link rel="ucp" href="/.well-known/ucp" version="2026-08-25"><link rel="buy" href="/cart/56389031657638:1?ucp/version=2026-08-25&amp;context/payment/0/handler=dev.shopify.shop_pay" payment="dev.shopify.shop_pay com.google.pay dev.shopify.card"><link rel="alternate" type="application/json+oembed" href="https://www.bostonproper.com/products/boston-proper-printed-scarf-with-love-bp.oembed">
10946<script async="async" src="/checkouts/internal/preloads.js?locale=en-US&default_configuration_id=8857419942"></script>
10946
10947<link rel="preconnect" href="https://shop.app" crossorigin="anonymous">
10948<script async="async" src="https://shop.app/checkouts/internal/preloads.js?locale=en-US&default_configuration_id=8857419942&shop_id=52960723110" crossorigin="anonymous"></script>
vendor: 1 bytes, line 10948
10948
10949<script id="apple-pay-shop-capabilities" type="application/json">{"shopId":52960723110,"countryCode":"US","currencyCode":"USD","merchantCapabilities":["supports3DS"],"merchantId":"gid:\/\/shopify\/Shop\/52960723110","merchantName":"Boston Proper","requiredBillingContactFields":["postalAddress","email"],"requiredShippingContactFields":["postalAddress","email"],"shippingType":"shipping","supportedNetworks":["visa","masterCard","amex","discover","elo","jcb"],"total":{"type":"pending","label":"Boston Proper","amount":"1.00"},"shopifyPaymentsEnabled":true,"supportsSubscriptions":true}</script>
vendor: 1 bytes, line 10949
10949
10950<script id="shopify-features" type="application/json">{"accessToken":"eb9ee10d84a005c2b8e778780263a9d2","betas":["rich-media-storefront-analytics"],"domain":"www.bostonproper.com","predictiveSearch":true,"shopId":52960723110,"locale":"en"}</script>
vendor: 1 bytes, line 10950
10950
10951<script>var Shopify = Shopify || {};
10952Shopify.shop = "bostonproper.myshopify.com";
10953Shopify.locale = "en";
10954Shopify.currency = {"active":"USD","rate":"1.0"};
10955Shopify.country = "US";
10956Shopify.theme = {"name":"Winter Home 1 | 10\/1 | V2.0.12","id":198106775718,"schema_name":"Horizon","schema_version":"3.5.0","theme_store_id":null,"role":"main"};
10957Shopify.theme.handle = "null";
10958Shopify.theme.style = {"id":null,"handle":null};
10959Shopify.cdnHost = "www.bostonproper.com/cdn";
10960Shopify.routes = Shopify.routes || {};
10961Shopify.routes.root = "/";
10962Shopify.shopJsCdnBaseUrl = "https://cdn.shopify.com/shopifycloud/shop-js";
10963Shopify.SignInWithShop = Shopify.SignInWithShop || {};
10964Shopify.SignInWithShop.User = Shopify.SignInWithShop.User || {};
10965Shopify.SignInWithShop.User.recognized = false;</script>
vendor: 1 bytes, line 10965
10965
10966<script type="module">!function(o){(o.Shopify=o.Shopify||{}).modules=!0}(window);</script>
vendor: 1 bytes, line 10966
10966
10967<script>!function(o){function n(){var o=[];function n(){o.push(Array.prototype.slice.apply(arguments))}return n.q=o,n}var t=o.Shopify=o.Shopify||{};t.loadFeatures=n(),t.autoloadFeatures=n()}(window);</script>
vendor: 1 bytes, line 10967
10967
10968<script>
10969  window.ShopifyPay = window.ShopifyPay || {};
10970  window.ShopifyPay.apiHost = "shop.app\/pay";
10971  window.ShopifyPay.redirectState = null;
10972</script>
vendor: 1 bytes, line 10972
10972
10973<script>
10974  window.Shopify = window.Shopify || {};
10975  window.Shopify.SignInWithShop = window.Shopify.SignInWithShop || {};
10976  window.Shopify.SignInWithShop.assetMetrics = { sampleRate: 0.25 };
10977  window.Shopify.SignInWithShop.eligible = true;
10978</script>
vendor: 1 bytes, line 10978
10978
10979<script id="shop-js-analytics" type="application/json">{"pageType":"product"}</script>
vendor: 1 bytes, line 10979
10979
10980<script defer="defer" async type="module" src="https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.init-shop-cart-sync.en.esm.js"></script>
vendor: 1 bytes, line 10980
10980
10981<script type="module">
10982  await import("https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.init-shop-cart-sync.en.esm.js");
10983
10984  window.Shopify.SignInWithShop?.initShopCartSync?.({"fedCMEnabled":true,"windoidEnabled":true});
10985
10986</script>
vendor: 1 bytes, line 10986
10986
10987<script>
10988  window.Shopify = window.Shopify || {};
10989  if (!window.Shopify.featureAssets) window.Shopify.featureAssets = {};
10990  window.Shopify.featureAssets['shop-js'] = {"avatar":["modules/v2/loader.avatar.en.esm.js"],"checkout-modal":["modules/v2/loader.checkout-modal.en.esm.js"],"init-customer-accounts-sign-up":["modules/v2/loader.init-customer-accounts-sign-up.en.esm.js"],"init-customer-accounts":["modules/v2/loader.init-customer-accounts.en.esm.js"],"init-fed-cm":["modules/v2/loader.init-fed-cm.en.esm.js"],"init-shop-cart-sync":["modules/v2/loader.init-shop-cart-sync.en.esm.js"],"init-shop-email-lookup-coordinator":["modules/v2/loader.init-shop-email-lookup-coordinator.en.esm.js"],"init-shop-for-new-customer-accounts":["modules/v2/loader.init-shop-for-new-customer-accounts.en.esm.js"],"init-shop-user-recognition":["modules/v2/loader.init-shop-user-recognition.en.esm.js"],"init-windoid":["modules/v2/loader.init-windoid.en.esm.js"],"lead-capture":["modules/v2/loader.lead-capture.en.esm.js"],"listener":["modules/v2/loader.listener.en.esm.js"],"pay-button":["modules/v2/loader.pay-button.en.esm.js"],"payment-terms":["modules/v2/loader.payment-terms.en.esm.js"],"shop-button":["modules/v2/loader.shop-button.en.esm.js"],"shop-cart-sync":["modules/v2/loader.shop-cart-sync.en.esm.js"],"shop-cash-offers":["modules/v2/loader.shop-cash-offers.en.esm.js"],"shop-follow-button":["modules/v2/loader.shop-follow-button.en.esm.js"],"shop-login-button":["modules/v2/loader.shop-login-button.en.esm.js"],"shop-login":["modules/v2/loader.shop-login.en.esm.js"],"shop-toast-manager":["modules/v2/loader.shop-toast-manager.en.esm.js"],"shop-user-recognition":["modules/v2/loader.shop-user-recognition.en.esm.js"]};
10991</script>
vendor: 1 bytes, line 10991
10991
10992<script>(function() {
10993  var isLoaded = false;
10994  function asyncLoad() {
10995    if (isLoaded) return;
10996    isLoaded = true;
10997    var urls = ["https:\/\/assets.smartwishlist.webmarked.net\/static\/v6\/smartwishlist.js?shop=bostonproper.myshopify.com","\/\/staticw2.yotpo.com\/gadsaMpv721mEDmSKobOdMTvocj7m5YYA1Mhe5gz\/widget.js?shop=bostonproper.myshopify.com","https:\/\/str.rise-ai.com\/?shop=bostonproper.myshopify.com","https:\/\/strn.rise-ai.com\/?shop=bostonproper.myshopify.com","https:\/\/cdn-loyalty.yotpo.com\/loader\/K13MR0xh3osOG6J13_kFIw.js?shop=bostonproper.myshopify.com","\/\/staticw2.yotpo.com\/l9OjGj5YqKVR9PFonEHJc4ms9HXq9RV8dOWnI8LL\/widget.js?shop=bostonproper.myshopify.com","https:\/\/config.gorgias.chat\/bundle-loader\/01GYCCVTPDFMYGPZ5V9AWDKET3?source=shopify1click\u0026shop=bostonproper.myshopify.com","https:\/\/container.pepperjam.com\/4041270386.js?shop=bostonproper.myshopify.com","https:\/\/media.9gtb.com\/loader.js?g_cvt_id=78dc5f7e-d6e2-4440-bdb7-1111f59638b3\u0026shop=bostonproper.myshopify.com"];
10998    for (var i = 0; i < urls.length; i++) {
10999      var s = document.createElement('script');
11000      s.type = 'text/javascript';
11001      s.async = true;
11002      s.src = urls[i];
11003      var x = document.getElementsByTagName('script')[0];
11004      x.parentNode.insertBefore(s, x);
11005    }
11006  };
11007  if(window.attachEvent) {
11008    window.attachEvent('onload', asyncLoad);
11009  } else {
11010    window.addEventListener('load', asyncLoad, false);
11011  }
11012})();</script>
vendor: 1 bytes, line 11012
11012
11013<script id="__st">var __st={"a":52960723110,"offset":-14400,"reqid":"366c6d67-7b42-4351-97e1-f226d34f308c-1791063068","pageurl":"www.bostonproper.com\/products\/boston-proper-printed-scarf-with-love-bp","u":"a321b22096fb","p":"product","rtyp":"product","rid":15286962618534};</script>
vendor: 1 bytes, line 11013
11013
11014<script>window.ShopifyPaypalV4VisibilityTracking = true;</script>
vendor: 1 bytes, line 11014
11014
11015<script id="captcha-bootstrap">!function(){'use strict';const t='contact',e='account',n='new_comment',o=[[t,t],['blogs',n],['comments',n],[t,'customer']],c=[[e,'customer_login'],[e,'guest_login'],[e,'recover_customer_password'],[e,'create_customer']],r=t=>t.map((([t,e])=>`form[action*='/${t}']:not([data-nocaptcha='true']) input[name='form_type'][value='${e}']`)).join(','),a=t=>()=>t?[...document.querySelectorAll(t)].map((t=>t.form)):[];function s(){const t=[...o],e=r(t);return a(e)}const i='password',u='form_key',d=['recaptcha-v3-token','g-recaptcha-response','h-captcha-response',i],f=()=>{try{return window.sessionStorage}catch{return}},m='__shopify_v',_=t=>t.elements[u];function p(t,e,n=!1){try{const o=window.sessionStorage,c=JSON.parse(o.getItem(e)),{data:r}=function(t){const{data:e,action:n}=t;return t[m]||n?{data:e,action:n}:{data:t,action:n}}(c);for(const[e,n]of Object.entries(r))t.elements[e]&&(t.elements[e].value=n);n&&o.removeItem(e)}catch(o){console.error('form repopulation failed',{error:o})}}const l='form_type',E='cptcha';function T(t){t.dataset[E]=!0}const w=window,h=w.document,L='Shopify',v='ce_forms',y='captcha';let A=!1;((t,e)=>{const n=(g='f06e6c50-85a8-45c8-87d0-21a2b65856fe',I='https://cdn.shopify.com/shopifycloud/storefront-forms-hcaptcha/ce_storefront_forms_captcha_hcaptcha.v1.5.3.iife.js',D={infoText:'Protected by hCaptcha',privacyText:'Privacy',termsText:'Terms'},(t,e,n)=>{const o=w[L][v],c=o.bindForm;if(c)return c(t,g,e,D).then(n);var r;o.q.push([[t,g,e,D],n]),r=I,A||(h.body.append(Object.assign(h.createElement('script'),{id:'captcha-provider',async:!0,src:r})),A=!0)});var g,I,D;w[L]=w[L]||{},w[L][v]=w[L][v]||{},w[L][v].q=[],w[L][y]=w[L][y]||{},w[L][y].protect=function(t,e){n(t,void 0,e),T(t)},Object.freeze(w[L][y]),function(t,e,n,w,h,L){const[v,y,A,g]=function(t,e,n){const i=e?o:[],u=t?c:[],d=[...i,...u],f=r(d),m=r(i),_=r(d.filter((([t,e])=>n.includes(e))));return[a(f),a(m),a(_),s()]}(w,h,L),I=t=>{const e=t.target;return e instanceof HTMLFormElement?e:e&&e.form},D=t=>v().includes(t);t.addEventListener('submit',(t=>{const e=I(t);if(!e)return;const n=D(e)&&!e.dataset.hcaptchaBound&&!e.dataset.recaptchaBound,o=_(e),c=g().includes(e)&&(!o||!o.value);(n||c)&&t.preventDefault(),c&&!n&&(function(t){try{if(!f())return;!function(t){const e=f();if(!e)return;const n=_(t);if(!n)return;const o=n.value;o&&e.removeItem(o)}(t);const e=Array.from(Array(32),(()=>Math.random().toString(36)[2])).join('');!function(t,e){_(t)||t.append(Object.assign(document.createElement('input'),{type:'hidden',name:u})),t.elements[u].value=e}(t,e),function(t,e){const n=f();if(!n)return;const o=[...t.querySelectorAll(`input[type='${i}']`)].map((({name:t})=>t)),c=[...d,...o],r={};for(const[a,s]of new FormData(t).entries())c.includes(a)||(r[a]=s);n.setItem(e,JSON.stringify({[m]:1,action:t.action,data:r}))}(t,e)}catch(e){console.error('failed to persist form',e)}}(e),e.submit())}));const S=(t,e)=>{t&&!t.dataset[E]&&(n(t,e.some((e=>e===t))),T(t))};for(const o of['focusin','change'])t.addEventListener(o,(t=>{const e=I(t);D(e)&&S(e,y())}));const B=e.get('form_key'),M=e.get(l),P=B&&M;t.addEventListener('DOMContentLoaded',(()=>{const t=y();if(P)for(const e of t)e.elements[l].value===M&&p(e,B);[...new Set([...A(),...v().filter((t=>'true'===t.dataset.shopifyCaptcha))])].forEach((e=>S(e,t)))}))}(h,new URLSearchParams(w.location.search),n,t,e,['guest_login'])})(!1,!0)}();</script>
vendor: 1 bytes, line 11015
11015
11016<script integrity="sha256-JjoPp5ZfB1sSAs5SQaol1x1GgvveM+BgmRzyDexInEQ=" data-source-attribution="shopify.loadfeatures" defer="defer" src="//www.bostonproper.com/cdn/shopifycloud/storefront/assets/storefront/load_feature-1bd60354.js" crossorigin="anonymous"></script>
vendor: 1 bytes, line 11016
11016
11017<script>(function () {var userAgent = navigator.userAgent;var platform = navigator.platform;var maxTouchPoints = navigator.maxTouchPoints || 0;var isIOS = /iPad|iPhone|iPod/.test(platform) || (platform === 'MacIntel' && maxTouchPoints > 1);var isMacSafari = platform.indexOf('Mac') === 0 && /Safari/.test(userAgent) && !/Chrome|Chromium|CriOS|FxiOS|Edg|OPR|Android/.test(userAgent);var isAppleSafari = isIOS || isMacSafari;if (isAppleSafari) {fetch('/sf_private_access_tokens' + location.search).catch(function () {});}function browserMajorVersion(pattern) {var match = userAgent.match(pattern);return match ? parseInt(match[1], 10) : null;}function shouldLoadAutosizesPolyfill() {if (!window.PerformanceObserver?.supportedEntryTypes?.includes('paint')) {return false;}var chromeVersion = browserMajorVersion(/Chrome\/(\d+)/);if (chromeVersion !== null) {return chromeVersion < 126;}var firefoxVersion = browserMajorVersion(/Firefox\/(\d+)/);if (firefoxVersion !== null) {return firefoxVersion < 150;}var safariVersion = isAppleSafari ? browserMajorVersion(/Version\/(\d+).*Safari\//) : null;if (safariVersion !== null) {return safariVersion < 27;}return true;}if (shouldLoadAutosizesPolyfill()) {var autosizesScript = document.createElement('script');autosizesScript.async = true;autosizesScript.crossOrigin = 'anonymous';autosizesScript.src = "//www.bostonproper.com/cdn/shopifycloud/storefront/assets/storefront/autosizes-84416378.js";(document.head || document.documentElement).appendChild(autosizesScript);}window.ShopifyAnalytics = window.ShopifyAnalytics || {};window.ShopifyAnalytics.performance = window.ShopifyAnalytics.performance || {};(function () {var LONG_FRAME_THRESHOLD = 50;var longAnimationFrames = [];var activeRafId = null;function collectLongFrames() {var previousTime = null;function rafMonitor(now) {if (activeRafId === null) {return;}var delta = now - previousTime;if (delta > LONG_FRAME_THRESHOLD) {longAnimationFrames.push({startTime: previousTime,endTime: now,});}previousTime = now;activeRafId = requestAnimationFrame(rafMonitor);}previousTime = performance.now();activeRafId = requestAnimationFrame(rafMonitor);}if (!window.PerformanceObserver?.supportedEntryTypes?.includes('long-animation-frame')) {collectLongFrames();var timeoutId = setTimeout(function () {cancelAnimationFrame(activeRafId);}, 10000);window.ShopifyAnalytics.performance.getLongAnimationFrames = function (stopCollection) {if (stopCollection === undefined) {stopCollection = false;}if (stopCollection) {clearTimeout(timeoutId);cancelAnimationFrame(activeRafId);}return longAnimationFrames;};}})();})();</script>
11017<script crossorigin="anonymous" defer="defer" src="//www.bostonproper.com/cdn/shopifycloud/storefront/assets/shopify_pay/storefront-616277c7.js?v=20250812"></script>
vendor: 1 bytes, line 11017
11017
11018<script id="shopify-origin-trials" async="async" integrity="sha256-qJbe/jEZBHtr5W/BlA2cKAz3vkXu6vJQyLjgvgCC86g=" src="//cdn.shopify.com/shopifycloud/storefront/assets/storefront/origin_trials-318ab40a.js" crossorigin="anonymous" onload="window.__shopifyOriginTrialsDone = true" onerror="window.__shopifyOriginTrialsDone = true"></script>
vendor: 1 bytes, line 11018
11018
11019<script>
11020  window.Shopify = window.Shopify || {};
11021  window.Shopify.MCP = window.Shopify.MCP || {};
11022  window.Shopify.MCP.enabled = true;
11023  window.Shopify.MCP.shop = "bostonproper.myshopify.com";
11024  window.Shopify.MCP.mcpEndpoint = "https:\/\/www.bostonproper.com\/api\/mcp";
11025  window.Shopify.MCP.tools = [{"name":"search_shop_policies_and_faqs","description":"Used to get facts about the stores policies, products, or services.\nSome examples of questions you can ask are:\n  - What is your return policy?\n  - What is your shipping policy?\n  - What is your phone number?\n  - What are your hours of operation?\"\n","inputSchema":{"$schema":"https:\/\/json-schema.org\/draft\/2020-12\/schema","type":"object","properties":{"query":{"type":"string","description":"A natural language query."},"context":{"type":"string","description":"Additional information about the request such as user demographics, mood, location, or other relevant details that could help in tailoring the response appropriately."}},"required":["query"]}}];
11026</script>
vendor: 1 bytes, line 11026
11026
11027<script>(()=>{var d="shopify:webmcp_adapter_loaded",n=Symbol.for("shopify.webmcp_adapter_loading");function s(c,a,{win:r=window,doc:o=document}={}){function p(){try{return r.localStorage.getItem(d)==="true"}catch{return!1}}function l(){try{r.localStorage.setItem(d,"true")}catch{}}function u(){return typeof(o.modelContext||r.navigator?.modelContext)?.registerTool=="function"}function f(){if(r[n]||!u())return;let t=o.head||o.getElementsByTagName("head")[0];if(!t)return;let e=o.createElement("script");e.type="module",e.crossOrigin="anonymous",a&&(e.integrity=a),e.src=c,e.addEventListener("load",l,{once:!0}),e.addEventListener("error",()=>{r[n]=!1},{once:!0}),t.appendChild(e),r[n]=!0}function _(t){let e=o.getElementById("shopify-origin-trials");if(!e||r.__shopifyOriginTrialsDone){t();return}e.addEventListener("load",t,{once:!0}),e.addEventListener("error",t,{once:!0})}function i(){_(()=>r.setTimeout(f,0))}function m(){o.addEventListener("DOMContentLoaded",i,{once:!0})}p()?i():m()}s("\/\/www.bostonproper.com\/cdn\/shopifycloud\/storefront\/assets\/storefront\/webmcp-c6b62ece.js","sha256-ke4DDuBjdvea3vxLWxHc9E9nq8zihuG4IfYEGbb77ys=");})();
11028</script>
vendor: 1 bytes, line 11028
11028
11029<script data-source-attribution="shopify.dynamic_checkout.dynamic.init">var Shopify=Shopify||{};Shopify.PaymentButton=Shopify.PaymentButton||{isStorefrontPortableWallets:!0,init:function(){window.Shopify.PaymentButton.init=function(){};var t=document.createElement("script");t.src="https://www.bostonproper.com/cdn/shopifycloud/portable-wallets/latest/portable-wallets.en.js",t.type="module",document.head.appendChild(t)}};
11030</script>
vendor: 1 bytes, line 11030
11030
11031<script data-source-attribution="shopify.dynamic_checkout.buyer_consent">
11032  function portableWalletsHideBuyerConsent(e){var t=document.getElementById("shopify-buyer-consent"),n=document.getElementById("shopify-subscription-policy-button");t&&n&&(t.classList.add("hidden"),t.setAttribute("aria-hidden","true"),n.removeEventListener("click",e))}function portableWalletsShowBuyerConsent(e){var t=document.getElementById("shopify-buyer-consent"),n=document.getElementById("shopify-subscription-policy-button");t&&n&&(t.classList.remove("hidden"),t.removeAttribute("aria-hidden"),n.addEventListener("click",e))}window.Shopify?.PaymentButton&&(window.Shopify.PaymentButton.hideBuyerConsent=portableWalletsHideBuyerConsent,window.Shopify.PaymentButton.showBuyerConsent=portableWalletsShowBuyerConsent);
11033</script>
vendor: 1 bytes, line 11033
11033
11034<script>
11035  function portableWalletsCleanup(e){e&&e.src&&console.error("Failed to load portable wallets script "+e.src);var t=document.querySelectorAll("shopify-accelerated-checkout .shopify-payment-button__skeleton, shopify-accelerated-checkout-cart .wallet-cart-button__skeleton"),e=document.getElementById("shopify-buyer-consent");for(let e=0;e<t.length;e++)t[e].remove();e&&e.remove()}function portableWalletsNotLoadedAsModule(e){e instanceof ErrorEvent&&"string"==typeof e.message&&e.message.includes("import.meta")&&"string"==typeof e.filename&&e.filename.includes("portable-wallets")&&(window.removeEventListener("error",portableWalletsNotLoadedAsModule),window.Shopify.PaymentButton.failedToLoad=e,"loading"===document.readyState?document.addEventListener("DOMContentLoaded",window.Shopify.PaymentButton.init):window.Shopify.PaymentButton.init())}window.addEventListener("error",portableWalletsNotLoadedAsModule);
11036</script>
11036
11037
11038<script type="module" src="https://www.bostonproper.com/cdn/shopifycloud/portable-wallets/latest/portable-wallets.en.js" onError="portableWalletsCleanup(this)" crossorigin="anonymous"></script>
vendor: 1 bytes, line 11038
11038
11039<script nomodule>
11040  document.addEventListener("DOMContentLoaded", portableWalletsCleanup);
11041</script>
11041
11042
11043<script integrity="sha256-/LA1C2Bx6899fYCos0FS9qLj2opaGFm7AXrTUvBEb4s=" data-source-attribution="shopify.remote_product_tracking" data-shopify-remote-tracking="{&quot;session_id&quot;:&quot;01M41TV44XWD8DKQ9237Y83TWX&quot;,&quot;publisher_shop_id&quot;:52960723110,&quot;theme_id&quot;:198106775718,&quot;theme_published&quot;:true,&quot;theme_store_id&quot;:0,&quot;placement&quot;:&quot;collection&quot;,&quot;event_data&quot;:{&quot;source_product_id&quot;:15286962618534,&quot;handle&quot;:&quot;boston-proper-printed-scarf-with-love-bp&quot;,&quot;page_type&quot;:&quot;product&quot;},&quot;recommendations_tracking_enabled&quot;:true}" defer="defer" src="//www.bostonproper.com/cdn/shopifycloud/storefront/assets/storefront/remote_product_tracking-91d95044.js" crossorigin="anonymous"></script>
11043
11044<link id="shopify-accelerated-checkout-styles" rel="stylesheet" media="screen" href="https://www.bostonproper.com/cdn/shopifycloud/portable-wallets/latest/accelerated-checkout-backwards-compat.css" crossorigin="anonymous">
11045<style id="shopify-accelerated-checkout-cart">
11046        #shopify-buyer-consent {
11047  margin-top: 1em;
11048  display: inline-block;
11049  width: 100%;
11050}
11051
11052#shopify-buyer-consent.hidden {
11053  display: none;
11054}
11055
11056#shopify-subscription-policy-button {
11057  background: none;
11058  border: none;
11059  padding: 0;
11060  text-decoration: underline;
11061  font-size: inherit;
11062  cursor: pointer;
11063}
11064
11065#shopify-subscription-policy-button::before {
11066  box-shadow: none;
11067}
11068
11069      </style>
11070<link rel="stylesheet" media="screen" href="//www.bostonproper.com/cdn/shop/t/1521/compiled_assets/styles.css?v=14521000909776209651790719704">
11071<script id="sections-script" data-sections="bp-how-to-wear-it,bp-collection-details,bp-yotpo-reviews,bp-footer-main,bp-quick-drawer" defer="defer" src="//www.bostonproper.com/cdn/shop/t/1521/compiled_assets/scripts.js?v=99640834855126272041790719705"></script>
vendor: 1 bytes, line 11071
11071
11072<script id="blocks-script" data-blocks="bp-complete-the-look,bp-pdp-bundle,bp-pdp-media-gallery,bp-promo-line,bp-require-size" defer="defer" src="//www.bostonproper.com/cdn/shop/t/1521/compiled_assets/block-scripts.js?v=169005028727735037821790713714"></script>
vendor: 1 bytes, line 11072
11072
11073<script id="snippets-script" data-snippets="bp-search-drawer,bp-card-swatches" defer="defer" src="//www.bostonproper.com/cdn/shop/t/1521/compiled_assets/snippet-scripts.js?v=66079492489357529931790713714"></script>
vendor: 1 bytes, line 11073
11073
11074<script id="shopify-cfh-end">window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.end');</script>
11074
11075  <!-- BEGIN app block: shopify://apps/black-crow-ai-that-delivers/blocks/blackcrow_ai_script/3e73f597-cb71-47a1-8a06-0c931482ecd2 -->
11076
11077<script type="text/javascript" async src="https://shopify-init.blackcrow.ai/js/core/bostonproper.js?shop=bostonproper.myshopify.com&tagSrc=ShopifyThemeAppExtension"></script>
11077
11078
11079
11080<!-- END app block --><!-- BEGIN app block: shopify://apps/yotpo-loyalty-rewards/blocks/loader-app-embed-block/2f9660df-5018-4e02-9868-ee1fb88d6ccd -->
11081    
11081<script src="https://cdn-widgetsrepository.yotpo.com/v1/loader/K13MR0xh3osOG6J13_kFIw" async></script>
11081
11082
11083
11084
11085    
11085<script src="https://cdn-loyalty.yotpo.com/loader/K13MR0xh3osOG6J13_kFIw.js?shop=www.bostonproper.com" async></script>
11085
11086
11087
11088
11089
11090
11091<!-- END app block --><!-- BEGIN app block: shopify://apps/bloomreach-loomi/blocks/unified-tracking-script/019beafc-b2ba-790d-9ed1-850d869fc572 -->
11092
11093
11094
11095
11096
11097
11098
11099
11100  <!-- BEGIN app snippet: bloomreach-analytics-publish -->
11100<script>
11101  /**
11102    * Publishes an event to Shopify.analytics with retry logic.
11103    * Waits for Shopify.analytics to become available before publishing.
11104    *
11105    * @param {string} eventName - The name of the event to publish
11106    * @param {object} eventData - The data payload for the event
11107    */
11108  window.bloomreachPublishEvent = function(eventName, eventData) {
11109    const maxAttempts = 100; // Max 10 seconds (100 * 100ms)
11110    let attempts = 0;
11111
11112    function tryPublish() {
11113      if (typeof Shopify !== "undefined" && Shopify.analytics && typeof Shopify.analytics.publish === "function") {
11114        Shopify.analytics.publish(eventName, eventData);
11115      } else if (attempts < maxAttempts) {
11116        attempts++;
11117        setTimeout(tryPublish, 100);
11118      } else {
11119        console.error('[Bloomreach Unified Tracking] Shopify.analytics object is not available');
11120      }
11121    }
11122    tryPublish();
11123  };
11124</script>
11124
11125<!-- END app snippet -->
11126  <!-- BEGIN app snippet: bloomreach-consent-gate -->
11126<script>
11127  (function() {
11128    const LOG_PREFIX = '[Bloomreach Unified Tracking]';
11129    const POLL_INTERVAL_MS = 100;
11130    const MAX_POLL_ATTEMPTS = 100;
11131    let trackingInitialized = false;
11132    let consentListenerRegistered = false;
11133
11134    function isBloomreachTrackingConsentGranted() {
11135      const privacy = window.Shopify && window.Shopify.customerPrivacy;
11136      if (!privacy) {
11137        return false;
11138      }
11139      return typeof privacy.analyticsProcessingAllowed === 'function'
11140        && typeof privacy.marketingAllowed === 'function'
11141        && typeof privacy.saleOfDataAllowed === 'function'
11142        && privacy.analyticsProcessingAllowed()
11143        && privacy.marketingAllowed()
11144        && privacy.saleOfDataAllowed();
11145    }
11146
11147    function waitForCustomerPrivacy(onReady, onTimeout) {
11148      let attempts = 0;
11149
11150      function tryLoadPrivacyApi() {
11151        if (typeof window.Shopify === 'undefined'
11152          || typeof window.Shopify.loadFeatures !== 'function') {
11153          if (attempts < MAX_POLL_ATTEMPTS) {
11154            attempts++;
11155            setTimeout(tryLoadPrivacyApi, POLL_INTERVAL_MS);
11156            return;
11157          }
11158          if (onTimeout) {
11159            onTimeout();
11160          }
11161          return;
11162        }
11163
11164        window.Shopify.loadFeatures(
11165          [{ name: 'consent-tracking-api', version: '0.1' }],
11166          function(error) {
11167            if (error) {
11168              if (onTimeout) {
11169                onTimeout();
11170              }
11171              return;
11172            }
11173            onReady();
11174          },
11175        );
11176      }
11177
11178      tryLoadPrivacyApi();
11179    }
11180
11181    function tryInitialize(initializeFn, config) {
11182      if (trackingInitialized) {
11183        return;
11184      }
11185      if (!isBloomreachTrackingConsentGranted()) {
11186        return;
11187      }
11188      if (typeof window.initializeDiscoveryCookie === 'function') {
11189        window.initializeDiscoveryCookie();
11190      }
11191      trackingInitialized = true;
11192      initializeFn(config);
11193    }
11194
11195    window.runWhenBloomreachTrackingAllowed = function(startFn, config, loadFn) {
11196      if (typeof loadFn === 'function') {
11197        loadFn(config);
11198      }
11199
11200      function onPrivacyApiReady() {
11201        tryInitialize(startFn, config);
11202
11203        if (!consentListenerRegistered) {
11204          consentListenerRegistered = true;
11205          document.addEventListener('visitorConsentCollected', function() {
11206            tryInitialize(startFn, config);
11207          });
11208        }
11209      }
11210
11211      function onPrivacyApiUnavailable() {
11212        console.error(LOG_PREFIX + ' Customer Privacy API unavailable');
11213      }
11214
11215      waitForCustomerPrivacy(onPrivacyApiReady, onPrivacyApiUnavailable);
11216    };
11217  })();
11218</script>
11218
11219<!-- END app snippet -->
11220<script>
11221    window.bloomreachPublishEvent("bre.domain_key", {
11222      domain_key: "bostonproper"
11223    });
11224  </script>
11224<script>
11225    // Publish localization data to the web pixel extension
11226    window.bloomreachPublishEvent("bre.localization", {
11227      country: "US",
11228      language: "en"
11229    });
11230
11231    
11232    window.bloomreachPublishEvent("bre.feature_flags", {});
11233    window.bloomreachPublishEvent("bre.discovery_config", {
11234      test_data: false,
11235      debug: false
11236    });
11237  </script>
11237
11238
11239  
11240  
11241
11242  <!-- BEGIN app snippet: bloomreach-br-uid-2-cookie -->
11242<script>
11243  (function() {
11244    const BR_UID_2_COOKIE_NAME = '_br_uid_2';
11245    const BR_UID_2_VERSION = 'app';
11246    const BR_UID_2_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365 * 2;
11247
11248    function decodeBrUid2CookieValue(value) {
11249      try {
11250        return decodeURIComponent(value);
11251      } catch (error) {
11252        return value;
11253      }
11254    }
11255
11256    function generateBrUid2Uid() {
11257      return String(Math.round(Math.random() * 10e12));
11258    }
11259
11260    function formatBrUid2CookieValue(uid, version, timestamp, hitCount) {
11261      return 'uid=' + uid + ':v=' + version + ':ts=' + timestamp + ':hc=' + hitCount;
11262    }
11263
11264    function generateBrUid2CookieValue(hitCount) {
11265      return formatBrUid2CookieValue(
11266        generateBrUid2Uid(),
11267        BR_UID_2_VERSION,
11268        Date.now(),
11269        hitCount
11270      );
11271    }
11272
11273    function parseBrUid2CookieValue(value) {
11274      const segments = decodeBrUid2CookieValue(value).split(':');
11275      let uid;
11276      let version;
11277      let timestamp;
11278      let hitCount;
11279
11280      for (let i = 0; i < segments.length; i++) {
11281        const segment = segments[i];
11282        if (segment.indexOf('uid=') === 0) {
11283          uid = segment.slice(4);
11284        } else if (segment.indexOf('v=') === 0) {
11285          version = segment.slice(2);
11286        } else if (segment.indexOf('ts=') === 0) {
11287          timestamp = parseInt(segment.slice(3), 10);
11288        } else if (segment.indexOf('hc=') === 0) {
11289          hitCount = parseInt(segment.slice(3), 10);
11290        }
11291      }
11292
11293      if (!uid || !version || isNaN(timestamp) || isNaN(hitCount) || hitCount < 0) {
11294        return null;
11295      }
11296
11297      return {
11298        uid: uid,
11299        version: version,
11300        timestamp: timestamp,
11301        hitCount: hitCount
11302      };
11303    }
11304
11305    function getBrUid2CookieValue() {
11306      const cookiePrefix = BR_UID_2_COOKIE_NAME + '=';
11307      const cookies = document.cookie.split('; ');
11308
11309      for (let i = 0; i < cookies.length; i++) {
11310        if (cookies[i].indexOf(cookiePrefix) === 0) {
11311          return decodeBrUid2CookieValue(cookies[i].substring(cookiePrefix.length));
11312        }
11313      }
11314
11315      return null;
11316    }
11317
11318    function getBaseDomain(host) {
11319      if (!host) {
11320          return '';
11321      }
11322      const parts = host.split('.');
11323      const length = parts.length;
11324
11325      // Handle cases like 'localhost', 'example.com', '192.168.1.1'
11326      if (length <= 2 || /^\d+\.\d+\.\d+\.\d+$/.test(host)) {
11327          return host;
11328      }
11329
11330      return parts[length - 1].length <= 2 && parts[length - 2].length <= 3
11331          ? parts.slice(-3).join('.')
11332          : parts.slice(-2).join('.');
11333    }
11334
11335    function buildBrUid2CookieString(value, domain) {
11336      const cookieParts = [
11337        BR_UID_2_COOKIE_NAME + '=' + encodeURIComponent(value),
11338        'path=/',
11339        'max-age=' + BR_UID_2_COOKIE_MAX_AGE_SECONDS,
11340        'SameSite=Lax'
11341      ];
11342
11343      if (domain) {
11344        cookieParts.push('domain=' + domain);
11345      }
11346
11347      return cookieParts.join('; ');
11348    }
11349
11350    function setBrUid2CookieValue(value) {
11351      const baseDomain = getBaseDomain(location.hostname);
11352
11353      document.cookie = buildBrUid2CookieString(value, baseDomain);
11354
11355      if (getBrUid2CookieValue() !== value) {
11356        document.cookie = buildBrUid2CookieString(value, null);
11357      }
11358    }
11359
11360    function ensureBrUid2Cookie() {
11361      const existingValue = getBrUid2CookieValue();
11362
11363      if (existingValue) {
11364        const parsed = parseBrUid2CookieValue(existingValue);
11365        if (parsed) {
11366          return existingValue;
11367        }
11368      }
11369
11370      const createdValue = generateBrUid2CookieValue(1);
11371      setBrUid2CookieValue(createdValue);
11372      return createdValue;
11373    }
11374
11375    window.initializeDiscoveryCookie = function() {
11376      const discoveryCookie = ensureBrUid2Cookie();
11377      if (typeof window.bloomreachPublishEvent === 'function') {
11378        window.bloomreachPublishEvent('bre.discovery_cookie', { cookie: discoveryCookie });
11379      }
11380    };
11381  })();
11382</script>
11382
11383<!-- END app snippet -->
11384
11385  
11386    
11386<script src="https://cdn.shopify.com/extensions/01a0f796-156f-7d78-b8ad-f52a94b2ec91/bloomreach-loomi-298/assets/unified-tracking-shop-price.js" defer></script>
11386
11387    
11388    
11389    
11390    
11391    
11392    
11393    
11394    
11395    
11396    
11397    
11398    
11399    
11400    
11401    
11402    
11403    
11404    
11405    
11406    
11407    
11408    
11409    
11410    
11411    
11412    
11413    
11414    
11415    
11416    
11417    
11418    
11419    
11420
11421    
11422    
11423    
11424    
11425  
11426
11427  
11427<script>
11428    const trackingConfig = {
11429      brweb: {
11430        target: "https:\/\/us3-api.eng.bloomreach.com",
11431        stream_id: "d042b089-6e20-44b6-82b8-7bd75742c4a8",
11432        data_layer: true,
11433        
11434        track: {
11435          default_properties: {
11436            customer_locale: "en-US"
11437          }
11438          
11439        },
11440        customConfigRaw: ""
11441      },
11442      
11443      
11444      shopCurrency: "USD",
11445      shopCountryCode: "",
11446      
11447      customer: {
11448        
11449      },
11450      metadata: {
11451        domain_key: "bostonproper"
11452        
11453        
11454      },
11455      deferredEvents: [
11456        
11457        
11458        {
11459          name: "product_viewed_custom",
11460          data: {
11461            product_id: 15286962618534,
11462            title: "Boston Proper Printed Scarf With Love BP",
11463            price: "50.00",
11464            vendor: "Boston Proper",
11465            brand: "Boston Proper",
11466            variant_id: 56389031657638,
11467            tags: ["2CT80","2CT8071","799","Active","Charmeuse","Fashion","Floral","Full Price","INV5_2CT80","Miscellaneous","N\/A","Non-Apparel","nvgroup_2CT80","Pink","Promotions","Published: 20261001","rtly-gc:offer-free-shipping","Scarves","Winter 26","Work","Woven","YGroup_2CT80"],
11468            available: true,
11469            stock_level: 2617,
11470            variant_inventory: 2617,
11471            sku: "2CT8071000",
11472            price_local_currency: 50.0,
11473            
11474            original_price: 50.0,
11475            
11476            original_price_local_currency: 50.0,
11477            local_currency: "USD",
11478            language: "en",
11479            categories_id: ["na"],
11480            categories_name: ["Uncategorized"],
11481            collections_id: [283797979302,680550269094,294174752934,305400348838,294285869222,290934751398,295577223334,295577190566,301181567142,294917963942],
11482            collections_name: ["All","All - Excluding Gift Cards and BWL","Auto Shoes \u0026 Accessories","Breast Cancer Awareness","Charmeuse","Full Price","New Arrivals","New Arrivals: Shoes \u0026 Accessories","No Collectives","Pink Collection"]
11483          }
11484        },
11485        
11486      ]
11487    };
11488
11489    function buildBrwebInitConfig(config) {
11490      const brwebBaseConfig = Object.assign({}, config.brweb);
11491      const customConfigRaw = brwebBaseConfig.customConfigRaw;
11492      delete brwebBaseConfig.customConfigRaw;
11493
11494      let customConfigOverrides = {};
11495      try {
11496        if (customConfigRaw && customConfigRaw.trim() !== '') {
11497          customConfigOverrides = JSON.parse(customConfigRaw);
11498        }
11499      } catch (e) {
11500        console.error('[Bloomreach Unified Tracking] Invalid JSON in Custom Configuration, ignoring: ' + e.message);
11501      }
11502
11503      return Object.assign({}, brwebBaseConfig, customConfigOverrides);
11504    }
11505
11506    function loadBloomreachSdk(config) {
11507      const brwebInitConfig = buildBrwebInitConfig(config);
11508
11509      !function(e,t,n,i,o,r){const s=4e3,c="xnpe_async_hide";function a(e){if("number"!=typeof e)return e;const t=new Date;return new Date(t.getTime()+1e3*e)}function m(e){return e.reduce((function(e,t){return e[t]=function(){e._.push([t.toString(),arguments])},e}),{_:[]})}function p(e,t,n){const i=n.createElement(t);i.src=e;const o=n.getElementsByTagName(t)[0];return o.parentNode.insertBefore(i,o),i}function l(e){return"[object Date]"===Object.prototype.toString.call(e)}r.target=r.target||"https://api.exponea.com",r.file_path=r.file_path||r.target+"/js/brweb.min.js",o[t]=m(["anonymize","initialize","identify","getSegments","update","track","trackLink","trackEnhancedEcommerce","getHtml","showHtml","showBanner","showWebLayer","ping","getAbTest","loadDependency","getRecommendation","reloadWebLayers","_preInitialize","_initializeConfig","metadata"]),o[t].notifications=m(["isAvailable","isSubscribed","subscribe","unsubscribe"]),o[t].segments=m(["subscribe"]),o[t]["snippetVersion"]="v3.1.1",function(e,t,n,i){e[i]={sdk:e[n],sdkObjectName:n,skipExperiments:!!t.new_experiments,path:t.target,streamId:t.stream_id}}(o,r,t,i),function(e,t,n){p(e.file_path,t,n)}(r,n,e),function(e,t,n,i,o,r,m,u){if(!e.new_experiments)return;!0===e.new_experiments&&(e.new_experiments={});const f=e.new_experiments.hide_class||c,d=e.new_experiments.timeout||s,_=encodeURIComponent(r.location.href);let g;e.cookies&&e.cookies.expires&&("number"==typeof e.cookies.expires||l(e.cookies.expires)?g=a(e.cookies.expires):e.cookies.expires.tracking&&("number"==typeof e.cookies.expires.tracking||l(e.cookies.expires.tracking))&&(g=a(e.cookies.expires.tracking))),g&&g<ne
11509w Date&&(g=void 0);const k=e.target+"/webxp/streams/"+e.stream_id+"/"+t+"/"+(u.exec(m.cookie)||[0,"new"])[1]+"/modifications.min.js?http-referer="+_+"&timeout="+d+"ms"+(g?"&cookie-expires="+Math.floor(g.getTime()/1e3):"");"sync"===e.new_experiments.mode&&r.localStorage.getItem("__exponea__sync_modifications__")?function(e,t,n,i,o){n[o][t]="<"+t+' src="'+e+'"></'+t+">",i.writeln(n[o][t]),i.writeln("<"+t+">!"+o+".init && document.writeln("+o+"."+t+'.replace("/'+t+'/", "/'+t+'-async/").replace("><", " async><"))</'+t+">")}(k,t,r,m,n):function(e,t,n,i,o,r,s,c){r.documentElement.classList.add(e);const a=p(n,i,r);function m(){o[c].init||p(n.replace("/"+i+"/","/"+i+"-async/"),i,r)}function l(){r.documentElement.classList.remove(e)}a.onload=m,a.onerror=m,o.setTimeout(l,t),o[s]._revealPage=l}(f,d,k,t,r,m,o,n)}(r,n,i,0,t,o,e,RegExp("__exponea_etc__"+"=([\\w-]+)")),function(e,t,n){var i;e[t]._initializeConfig(n),(null===(i=n.experimental)||void 0===i?void 0:i.non_personalized_weblayers)&&e[t]._preInitialize(n),e[t].start=function(i){i&&Object.keys(i).forEac
11509h((e=>n[e]=i[e])),e[t].initialize(n)}}(o,t,r)}(document,"brweb","script","webxpClient",window, brwebInitConfig);
11510
11511      window.exponea = brweb;
11512    }
11513
11514    function startBloomreachTracking(config) {
11515      window.dataLayer = window.dataLayer || [];
11516
11517      function subscribeCookieListener(dataLayer) {
11518        dataLayer.forEach(processDatalayerEvent);
11519
11520        const originalPush = dataLayer.push;
11521        dataLayer.push = function() {
11522          originalPush.apply(dataLayer, arguments);
11523          Array.from(arguments).forEach(processDatalayerEvent);
11524        };
11525      }
11526
11527      function processDatalayerEvent(event) {
11528        if (event.event === "bre.cookie") {
11529          Shopify.analytics.publish("bre.cookie", event);
11530        }
11531      }
11532
11533      subscribeCookieListener(window.dataLayer);
11534
11535      function getCookie(cname) {
11536        var name = cname + "=";
11537        var ca = document.cookie.split(';');
11538        var cookie = undefined;
11539        for (var i = 0; i < ca.length; i++) {
11540          var c = ca[i];
11541          while (c.charAt(0) == ' ') {
11542            c = c.substring(1);
11543          }
11544          if (c.indexOf(name) == 0) {
11545            cookie = c.substring(name.length, c.length);
11546            break;
11547          }
11548        }
11549        cookie = decodeURIComponent(cookie);
11550        cookie = cookie.split('?')[0];
11551        return cookie;
11552      }
11553
11554      var customer = Object.assign({}, config.customer);
11555      var cart_id = getCookie('cart');
11556      if (cart_id) customer.cart_id = cart_id;
11557
11558      exponea.start({
11559        customer: customer
11560      });
11561
11562      if (config.metadata) {
11563        exponea.metadata(config.metadata);
11564      }
11565
11566      /**
11567       * Quick View Tracking
11568       * Listens for clicks on native Shopify quick-add-component elements.
11569       * Only tracks when clicking a button[type="button"] (opens modal).
11570       * Ignores button[type="submit"] (direct add to cart).
11571       */
11572      (function() {
11573        document.addEventListener('click', function(event) {
11574          const quickAddComponent = event.target.closest('quick-add-component');
11575          if (!quickAddComponent) return;
11576
11577          const clickedButton = event.target.closest('button');
11578          if (!clickedButton || clickedButton.type !== 'button') return;
11579
11580          const productForm = quickAddComponent.querySelector('product-form-component');
11581          const productId = productForm?.getAttribute('data-product-id');
11582          if (!productId) return;
11583
11584          const variantInput = quickAddComponent.querySelector('input[name="id"]');
11585          window.bloomreachPublishEvent('bre.quick_view', {
11586            product_id: productId,
11587            title: quickAddComponent.getAttribute('data-product-title') || '',
11588            variant_id: variantInput?.value || ''
11589          });
11590        });
11591      })();
11592
11593      config.deferredEvents.forEach(function(event) {
11594        if (event.name !== "product_viewed_custom") {
11595          window.bloomreachPublishEvent(event.name, event.data);
11596          return;
11597        }
11598        
11599        var published = false;
11600        var deadlineId = setTimeout(publishPresentment, 3000);
11601        var waitForEnrichId = null;
11602        var enrichAbort = typeof AbortController === "function"
11603          ? new AbortController()
11604          : null;
11605        function publishProductViewed(data) {
11606          if (published) {
11607            return;
11608          }
11609          published = true;
11610          clearTimeout(deadlineId);
11611          clearInterval(waitForEnrichId);
11612          window.removeEventListener("pagehide", publishPresentment);
11613          if (enrichAbort) {
11614            enrichAbort.abort();
11615          }
11616          window.bloomreachPublishEvent(event.name, data);
11617        }
11618        function publishPresentment() {
11619          publishProductViewed(event.data);
11620        }
11621        function tryRunProductViewedEnrich() {
11622          var enrich = window.bloomreachEnrichProductViewedData;
11623          if (typeof enrich !== "function") {
11624            return false;
11625          }
11626          enrich(event.data, {
11627            shopCurrency: config.shopCurrency || "",
11628            shopCountryCode: config.shopCountryCode || "",
11629            signal: enrichAbort ? enrichAbort.signal : undefined
11630          }).then(publishProductViewed, publishPresentment);
11631          return true;
11632        }
11633        window.addEventListener("pagehide", publishPresentment, { once: true });
11634        if (!tryRunProductViewedEnrich()) {
11635          waitForEnrichId = setInterval(function() {
11636            if (published || tryRunProductViewedEnrich()) {
11637              clearInterval(waitForEnrichId);
11638            }
11639          }, 25);
11640        }
11641      });
11642    }
11643
11644    runWhenBloomreachTrackingAllowed(startBloomreachTracking, trackingConfig, loadBloomreachSdk);
11645  </script>
11645
11646
11647<!-- END app block --><!-- BEGIN app block: shopify://apps/microsoft-clarity/blocks/brandAgents_js/31c3d126-8116-4b4a-8ba1-baeda7c4aeea -->
11648
11649
11650
11651<script type="text/javascript">
11652  (function(d){
11653      var s = d.createElement('script');
11654      s.async = true;
11655      s.src = "https://adsagentclientafd-b7hqhjdrf3fpeqh2.b01.azurefd.net/frontendInjection.js";
11656      var firstScript = d.getElementsByTagName('script')[0];
11657      firstScript.parentNode.insertBefore(s, firstScript);
11658  })(document);
11659</script>
11659
11660
11661
11662
11663<!-- END app block --><!-- BEGIN app block: shopify://apps/klaviyo-email-marketing-sms/blocks/klaviyo-onsite-embed/2632fe16-c075-4321-a88b-50b567f42507 -->
11664
11665
11666
11667
11668
11669
11670
11671
11672
11673
11674
11675
11676  
11676<script async src="https://static.klaviyo.com/onsite/js/VZrTML/klaviyo.js?company_id=VZrTML"></script>
11676
11677  
11677<script>!function(){if(!window.klaviyo){window._klOnsite=window._klOnsite||[];try{window.klaviyo=new Proxy({},{get:function(n,i){return"push"===i?function(){var n;(n=window._klOnsite).push.apply(n,arguments)}:function(){for(var n=arguments.length,o=new Array(n),w=0;w<n;w++)o[w]=arguments[w];var t="function"==typeof o[o.length-1]?o.pop():void 0,e=new Promise((function(n){window._klOnsite.push([i].concat(o,[function(i){t&&t(i),n(i)}]))}));return e}}})}catch(n){window.klaviyo=window.klaviyo||[],window.klaviyo.push=function(){var n;(n=window._klOnsite).push.apply(n,arguments)}}}}();</script>
11677
11678
11679  
11680
11681
11682
11683
11684  
11684<script>
11685    window.klaviyoReviewsProductDesignMode = false
11686  </script>
11686
11687
11688
11689
11690  <!-- BEGIN app snippet: customer-hub-data -->
11690<script>
11691  if (!window.customerHub) {
11692    window.customerHub = {};
11693  }
11694  window.customerHub.storefrontRoutes = {
11695    login: "https://www.bostonproper.com/customer_authentication/redirect?locale=en&region_country=US?return_url=%2F%23k-hub",
11696    register: "https://shopify.com/52960723110/account?locale=en&region_country=US&buyer_flags=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJib3N0b25wcm9wZXIubXlzaG9waWZ5LmNvbSIsImZsYWdzIjpbXSwiZXhwIjoxNzkxNjY3ODY5LCJuYmYiOjE3OTEwNjMwNjl9.Y6VmvHvB93TtkRDu_h4pqSFO1UdZ1sak09aAYo6kJxE?return_url=%2F%23k-hub",
11697    logout: "/account/logout",
11698    profile: "/account",
11699    addresses: "/account/addresses",
11700  };
11701  
11702  window.customerHub.userId = null;
11703  
11704  window.customerHub.storeDomain = "bostonproper.myshopify.com";
11705
11706  
11707    window.customerHub.activeProduct = {
11708      name: "Boston Proper Printed Scarf With Love BP",
11709      category: null,
11710      imageUrl: "https://www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236_grande.jpg?v=1791009198",
11711      id: "15286962618534",
11712      link: "https://www.bostonproper.com/products/boston-proper-printed-scarf-with-love-bp",
11713      options: [
11714        
11715          {
11716            name: "Color",
11717            values: [
11718              
11719                
11720                
11721                {
11722                  name: "With Love BP",
11723                  colorHex: null,
11724                  swatchImageUrl: null
11725                }
11726              
11727            ]
11728          },
11729        
11730          {
11731            name: "Size",
11732            values: [
11733              
11734                
11735                
11736                {
11737                  name: "One Size",
11738                  colorHex: null,
11739                  swatchImageUrl: null
11740                }
11741              
11742            ]
11743          }
11744        
11745      ],
11746      variants: [
11747        
11748          {
11749            id: "56389031657638",
11750            selectedOptions: [
11751              
11752                
11753                {
11754                  name: "Color",
11755                  value: "With Love BP"
11756                },
11757              
11758                
11759                {
11760                  name: "Size",
11761                  value: "One Size"
11762                }
11763              
11764            ],
11765            
11766            imageUrl: "https://www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236_grande.jpg?v=1791009198",
11767            
11768            price: "5000",
11769            currency: "USD",
11770            availableForSale: true,
11771            title: "With Love BP \/ One Size",
11772          },
11773        
11774      ],
11775    };
11776    window.customerHub.activeProduct.variants.forEach((variant) => {
11777        
11778        variant.price = `${variant.price.slice(0, -2)}.${variant.price.slice(-2)}`;
11779    });
11780  
11781
11782  
11783    window.customerHub.storeLocale = {
11784        currentLanguage: 'en',
11785        currentCountry: 'US',
11786        availableLanguages: [
11787          
11788            {
11789              iso_code: 'en',
11790              endonym_name: 'English'
11791            }
11792          
11793        ],
11794        availableCountries: [
11795          
11796            {
11797              iso_code: 'CA',
11798              name: 'Canada',
11799              currency_code: 'CAD'
11800            },
11801          
11802            {
11803              iso_code: 'US',
11804              name: 'United States',
11805              currency_code: 'USD'
11806            }
11807          
11808        ]
11809    };
11810  
11811</script>
11811
11812<!-- END app snippet -->
11813
11814
11815
11816  <!-- BEGIN app snippet: customer-hub-replace-links -->
11817<script>
11818  function replaceAccountLinks() {
11819    const selector =
11820      'a[href$="/account/login"], a[href$="/account"], a[href^="https://shopify.com/"][href*="/account"], a[href*="/customer_identity/redirect"], a[href*="/customer_authentication/redirect"], a[href$="/account';
11821    const accountLinksNodes = document.querySelectorAll(selector);
11822    for (const node of accountLinksNodes) {
11823      const ignore = node.dataset.kHubIgnore !== undefined && node.dataset.kHubIgnore !== 'false';
11824      if (!ignore) {
11825        // Any login links to Shopify's account system, point them at the customer hub instead.
11826        node.href = '#k-hub';
11827        /**
11828         * There are some themes which apply a page transition on every click of an anchor tag (usually a fade-out) that's supposed to be faded back in when the next page loads.
11829         * However, since clicking the k-hub link doesn't trigger a page load, the page gets stuck on a blank screen.
11830         * Luckily, these themes usually have a className you can add to links to skip the transition.
11831         * Let's hope that all such themes are consistent/copy each other and just proactively add those classNames when we replace the link.
11832         **/
11833        node.classList.add('no-transition', 'js-no-transition');
11834      }
11835    }
11836  }
11837
11838  
11839    if (document.readyState === 'complete') {
11840      replaceAccountLinks();
11841    } else {
11842      const controller = new AbortController();
11843      document.addEventListener(
11844        'readystatechange',
11845        () => {
11846          replaceAccountLinks(); // try to replace links both during `interactive` state and `complete` state
11847          if (document.readyState === 'complete') {
11848            // readystatechange can fire with "complete" multiple times per page load, so make sure we're not duplicating effort
11849            // by removing the listener afterwards.
11850            controller.abort();
11851          }
11852        },
11853        { signal: controller.signal },
11854      );
11855    }
11856  
11857</script>
11857
11858<!-- END app snippet -->
11859
11860
11861
11862
11863
11864<!-- END app block --><!-- BEGIN app block: shopify://apps/ab-tasty/blocks/abtasty-tag/50439cd8-89e0-4240-838a-2948c07c763d -->
11865  
11866    
11866<script
11867      type="text/javascript"
11868      src="https://try.abtasty.com/443033f8f050ee927ac9047efa5db622.js"
11869    ></script>
11869
11870  
11871  
11871<script type="text/javascript">
11872    // This waits for all the external ressources (including ABTasty tag) to load before executing the callback function.
11873    window.addEventListener('load', function () {
11874      if(!window.ABTasty) {
11875        // AB Tasty tag is not loaded so exit.
11876        return
11877      }
11878
11879      if (window.ABTasty.eventState?.['consentValid']?.status === 'complete') {
11880        updateShopifyDataForWebPixel();
11881      } else {
11882        window.addEventListener('abtasty_consentValid', () => {
11883          updateShopifyDataForWebPixel();
11884        });
11885      }
11886
11887
11888      async function waitForVisitorId(maxRetries = 5, delayMs = 500) {
11889        for (let i = 0; i < maxRetries; i++) {
11890          const visitorId = ABTasty.api.v1.getValue('visitorId')
11891          if (visitorId) {
11892            return visitorId;
11893          }
11894          await new Promise(resolve => setTimeout(resolve, delayMs));
11895        }
11896        return null;
11897      }
11898
11899
11900      async function updateShopifyDataForWebPixel() {
11901        const STORAGE_KEY = 'ABTastyShopify';
11902        const consentReady = ABTasty.consentReady;
11903        const shouldHandleSubdomain = "false" === "true";
11904
11905        if(!consentReady) {
11906          if(shouldHandleSubdomain) {
11907            await cookieStore.delete(STORAGE_KEY);
11908          }
11909          return localStorage.removeItem(STORAGE_KEY);
11910        }
11911
11912        const visitorId = await waitForVisitorId(5, 500);
11913
11914        if (!visitorId) {
11915          console.error('[AB Tasty] Unable to get AB Tasty visitorID after 5 retry');
11916          return;
11917        }
11918
11919        const ABTastyData = {
11920          identifier: "443033f8f050ee927ac9047efa5db622",
11921          campaigns: ABTasty.getCampaignHistory(),
11922          visitorId: visitorId,
11923          accountId: ABTasty.getAccountSettings().id,
11924          consent: ABTasty.consentReady,
11925        };
11926
11927        if (shouldHandleSubdomain) {
11928          await cookieStore.set({
11929            name: STORAGE_KEY,
11930            value: JSON.stringify(ABTastyData),
11931            expires: Date.now() + 1 * 24 * 60 * 60 * 1000, // 1 day
11932            domain: window.location.hostname,
11933          });
11934        }
11935        localStorage.setItem(STORAGE_KEY, JSON.stringify(ABTastyData));
11936      }
11937    });
11938  </script>
11938
11939
11940
11941
11942
11943
11944<!-- END app block --><!-- BEGIN app block: shopify://apps/microsoft-clarity/blocks/clarity_js/31c3d126-8116-4b4a-8ba1-baeda7c4aeea -->
11945<script type="text/javascript">
11946  (function (c, l, a, r, i, t, y) {
11947    c[a] = c[a] || function () { (c[a].q = c[a].q || []).push(arguments); };
11948    t = l.createElement(r); t.async = 1; t.src = "https://www.clarity.ms/tag/" + i + "?ref=shopify";
11949    y = l.getElementsByTagName(r)[0]; y.parentNode.insertBefore(t, y);
11950
11951    c.Shopify.loadFeatures([{ name: "consent-tracking-api", version: "0.1" }], error => {
11952      if (error) {
11953        console.error("Error loading Shopify features:", error);
11954        return;
11955      }
11956
11957      c[a]('consentv2', {
11958        ad_Storage: c.Shopify.customerPrivacy.marketingAllowed() ? "granted" : "denied",
11959        analytics_Storage: c.Shopify.customerPrivacy.analyticsProcessingAllowed() ? "granted" : "denied",
11960        source: 101,
11961      });
11962    });
11963
11964    l.addEventListener("visitorConsentCollected", function (e) {
11965      c[a]('consentv2', {
11966        ad_Storage: e.detail.marketingAllowed ? "granted" : "denied",
11967        analytics_Storage: e.detail.analyticsAllowed ? "granted" : "denied",
11968        source: 101,
11969      });
11970    });
11971  })(window, document, "clarity", "script", "v94zgzk99z");
11972</script>
11972
11973
11974
11975
11976<!-- END app block --><!-- BEGIN app block: shopify://apps/pc97pbn58-opensend/blocks/opensend/019d6301-977a-74bc-a568-af824856dc19 -->
11977<script type='text/javascript'>
11978!function(s) {
11979  let o = s.createElement('script'), u = s.getElementsByTagName('script')[0];
11980  o.src = 'https://cdn.aggle.net/oir/oir.min.js';
11981  o.async = !0, o.setAttribute('oirtyp', '48b1feaa'), o.setAttribute('oirid', 'P7C25MF72');
11982  u.parentNode.insertBefore(o, u);
11983}(document);
11984</script>
11984
11985
11986<script type='text/javascript'>
11987  {
11988    const cleanObj = (value) => {
11989      if (Array.isArray(value)) {
11990        const cleanedArray = value.map(cleanObj).filter((v) => v !== undefined);
11991        return cleanedArray.length ? cleanedArray : undefined;
11992      }
11993      if (value && typeof value === "object") {
11994        const cleanedObject = Object.entries(value).reduce((acc, [key, val]) => {
11995          const cleanedValue = cleanObj(val);
11996          if (cleanedValue !== undefined && cleanedValue !== null && cleanedValue !== "") {
11997            acc[key] = cleanedValue;
11998          }
11999          return acc;
12000        }, {});
12001        return Object.keys(cleanedObject).length ? cleanedObject : undefined;
12002      }
12003      if (value === null || value === undefined || value === "") {
12004        return undefined;
12005      }
12006      return value;
12007    };
12008    const getCustomer = () => ({
12009      shopifyCustomerId: "",
12010      email: "",
12011      phone: "",
12012      first_name: null,
12013      last_name: null,
12014      lifetime_value: null,
12015      order_count: null,
12016      address: {
12017        street: null,
12018        city: null,
12019        state:  null,
12020        stateCode: null,
12021        postalCode: "",
12022        country: "",
12023        province: "",
12024        countryCode: "",
12025      }
12026    });
12027    
12028  }
12029</script>
12029
12030
12031
12032<!-- END app block --><link href="https://monorail-edge.shopifysvc.com" rel="dns-prefetch">
12033<script>(function(){if ("sendBeacon" in navigator && "performance" in window) {try {var session_token_from_headers = performance.getEntriesByType('navigation')[0].serverTiming.find(x => x.name == '_s').description;} catch {var session_token_from_headers = undefined;}var session_cookie_matches = document.cookie.match(/_shopify_s=([^;]*)/);var session_token_from_cookie = session_cookie_matches && session_cookie_matches.length === 2 ? session_cookie_matches[1] : "";var session_token = session_token_from_headers || session_token_from_cookie || "";function handle_abandonment_event(e) {var entries = performance.getEntries().filter(function(entry) {return /monorail-edge.shopifysvc.com/.test(entry.name);});if (!window.abandonment_tracked && entries.length === 0) {window.abandonment_tracked = true;var currentMs = Date.now();var navigation_start = performance.timing.navigationStart;var payload = {shop_id: 52960723110,url: window.location.href,navigation_start,duration: currentMs - navigation_start,session_token,page_type: "product"};window.navigator.sendBeacon("https://monorail-edge.shopifysvc.com/v1/produce", JSON.stringify({schema_id: "online_store_buyer_site_abandonment/1.1",payload: payload,metadata: {event_created_at_ms: currentMs,event_sent_at_ms: currentMs}}));}}window.addEventListener('pagehide', handle_abandonment_event);}}());</script>
vendor: 1 bytes, line 12033
12033
12034<script>
12035  window.__TREKKIE_SHIM_QUEUE = window.__TREKKIE_SHIM_QUEUE || [];
12036</script>
vendor: 1 bytes, line 12036
12036
12037<script>(function(){var wpmLoader=function(){"use strict";var e=/Googlebot|Storebot-Google|bingbot|Baiduspider|YandexBot|DuckDuckBot|Slurp|facebookexternalhit|Twitterbot|LinkedInBot|Applebot|AdsBot-Google|Mediapartners-Google|APIs-Google|PetalBot|SemrushBot|AhrefsBot|MJ12bot|DotBot|Acunetix|PerplexityBot|Perplexity-User/i,t=/bytedance/i;function i(){try{var e=document.cookie;if(!e||"string"!=typeof e)return;for(var t=0,i=e.split(";");t<i.length;t++){var n=i[t],r=n.indexOf("=");if(-1!==r){var o=n.slice(0,r).trim();if(o){var a=void 0;try{a=decodeURIComponent(o)}catch(e){a=o}if("_shopify_s"===a){var d=n.slice(r+1).trim();try{return decodeURIComponent(d)}catch(e){return d}}}}}return}catch(e){return}}function n(e){try{"undefined"!=typeof console&&"function"==typeof console.warn&&console.warn(e)}catch(e){}}function r(e,t){return"string"==typeof e&&e.length>0&&e.length<=t?e:void 0}function o(e){var t;switch(null==(t=null==e?void 0:e.navigation)?void 0:t.type){case 0:return"navigate";case 1:return"reload";case 2:return"back_forward";default:return}}function a(){var e,t,i;try{var n=null==(i=null==(t=null==(e=self.ShopifyAnalytics)?void 0:e.lib)?void 0:t.trekkie)?void 0:i.state;return"awaiting-consent"===n||"initialized"===n?n:void 0}catch(e){return}}return function(d,s,u,l){var c=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};try{var p=c.trekkieShim;!0!==p&&"true"!==p||null!=window.__TREKKIE_SHIM_QUEUE||(window.__TREKKIE_SHIM_QUEUE=[])}catch(e){}var f,v,h,y,g=(v=(f={modern:/Edge?\/(1{2}[4-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Firefox\/(1{2}[4-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Chrom(ium|e)\/(9{2}|\d{3,})\.\d+(\.\d+|)|(Maci|X1{2}).+ Version\/(15\.\d+|(1[6-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( \(\w+\)|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(9{2}|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(15[._]\d+|(1[6-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Android.+Firefox\/(15\d|1[6-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|SamsungBrowser\/([2-9]\d|\d{3,})\.\d+/,legacy:/Edge?\/(1[6-9]|[2-9]\d|\d{3,})\.\d+(\.\d+|)|Firefox\/(5[4-9]|[6-9]\d|\d{3,})\.\d+(\.\d+|)|Chrom(ium|e)\/(5[1-9]|[6-9]\d|\d{3,})\.\d+(\.\d+|)([\d.]+$|.*Safari\/(?![\d.]+ Edge\/[\d.]+$))|(Maci|X1{2}).+ Version\/(10\.\d+|(1[1-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( \(\w+\)|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(3[89]|[4-9]\d|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(10[._]\d+|(1[1-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Mobile Safari.+OPR\/([89]\d|\d{3,})\.\d+\.\d+|Android.+Firefox\/(15\d|1[6-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+(UC? ?Browser|UCWEB|U3)[ /]?(15\.([5-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})\.\d+)\.\d+|SamsungBrowser\/(5\.\d+|([6-9]|\d{2,})\.\d+)|Android.+MQ{2}Browser\/(14(\.(9|\d{2,})|)|(1[5-9]|[2-9]\d|\d{3,})(\.\d+|))(\.\d+|)|K[Aa][Ii]OS\/(3\.\d+|([4-9]|\d{2,})\.\d+)(\.\d+|)/}).modern,h=f.legacy,(y=navigator.userAgent).match(e)?"bot":y.match(v)?"modern":y.match(h)?"legacy":y.match(t)?"bot":"unknown"),m=function(e){var t,i,n=r(e,128);try{var a=window.performance,d=null==(t=null==a?void 0:a.getEntriesByType)?void 0:t.call(a,"navigation")[0];if(!d)return{requestId:n,navigationType:o(a)};var s="type"in d?r(d.type,64):void 0,u="serverTiming"in d&&Array.isArray(d.serverTiming)?d.serverTiming:[];return{requestId:null!=n?n:r(null==(i=u.find(function(e){return"requestID"===e.name}))?void 0:i.description,128),navigationType:s}}catch(e){return{requestId:n}}}(c.requestId),w=function(e){var t=e.version,r=e.browserTarget,o=e.surface,a=e.shopId,d=e.monorailEndpoint,s=window.location.href;return{emit:function(e){var u=e.status,l=e.errorMsg,c=e.failureReason,p=e.useKeepaliveFallback,f=void 0!==p&&p,v=e.navigationType,h=e.pagehidePersisted,y=e.requestId,g=e.trekkieState;if(d){var m,w;try{var b=(new Date).getTime();m=JSON.stringify({metadata:{event_sent_at_ms:b},events:[{schema_id:"web_pixels_manager_load/3.3",payload:{version:t,bundle_target:r,page_url:s,status:u,surface:o,error_msg:l,failure_reason:c,navigation_type:v,pagehide_persisted:h,request_id:y,trekkie_state:g,shop_id:a,visit_token:i()},metadata:{event_created_at_ms:b}}]})}catch(e){return}try{if("function"==typeof window.navigator.sendBeacon&&-1===(w=window.navigator.userAgent).indexOf("iPhone; CPU iPhone OS 12_")&&-1===w.indexOf("iPad; CPU OS 12_")&&-1===w.indexOf("iPod touch; CPU iPhone OS 12_")&&window.navigator.sendBeacon.bind(window.navigator)(d,m))return}catch(e){}if(f)try{"function"==typeof window.fetch&&window.fetch(d,{method:"POST",headers:{"Content-Type":"text/plain"},body:m,keepalive:!0}
12037).catch(function(){})}catch(e){}else try{var _=new XMLHttpRequest;_.open("POST",d,!0),_.setRequestHeader("Content-Type","text/plain"),_.send(m)}catch(e){n("[Web Pixels Manager] Got an unhandled error while logging to Monorail.")}}else n("[Web Pixels Manager] No Monorail endpoint provided, skipping logging.")}}}({version:u,browserTarget:g,surface:d.surface,shopId:d.shopId,monorailEndpoint:d.monorailEndpoint});if(Boolean(null==(_=null==(b=window.Shopify)?void 0:b.analytics)?void 0:_.replayQueue))w.emit({status:"setup-skipped",errorMsg:"replay queue already initialized."});else{var b,_;w.emit({status:"setup-started"}),window.Shopify=window.Shopify||{};var S=window.Shopify;S.analytics=S.analytics||{};var P=S.analytics;P.replayQueue=[],P.publish=function(e,t,i){return P.replayQueue.push([e,t,i]),!0};try{self.performance.mark("wpm:start")}catch(e){}var k,C="modern"===g?"modern":"legacy",E=(null!=l?l:{modern:"",legacy:""})[C],I=[(k={baseUrl:s,hashVersion:u,buildTarget:C}).baseUrl,"/wpm","/b",k.hashVersion,"modern"===k.buildTarget?"m":"l",".js"].join(""),O=!1,T=!1;try{c.browserTarget=g,function(){O=!0;try{window.addEventListener("pagehide",M)}catch(e){O=!1}}(),R(function(){try{R(x)}catch(e){D(e)}}),w.emit({status:"loading",requestId:m.requestId,navigationType:m.navigationType,trekkieState:a()})}catch(e){D(e)}}function U(){var e;if(q(),!function(){var e,t;return Boolean(null==(t=null==(e=window.Shopify)?void 0:e.analytics)?void 0:t.initialized)}()){var t,i,n;try{if("function"!=typeof(null==(e=window.webPixelsManager)?void 0:e.init))return void A();if(!(null!==(n=i=t=window.webPixelsManager.init(d))&&"function"!=typeof n&&Object(n)===n&&"publish"in i&&"function"==typeof i.publish&&"publishCustomEvent"in i&&"function"==typeof i.publishCustomEvent&&"visitor"in i&&"function"==typeof i.visitor))return void A()}catch(e){return void A(e)}var r=window.Shopify.analytics;r.replayQueue.forEach(function(e){var i=e[0],n=e[1],r=e[2];t.publishCustomEvent(i,n,r)}),r.replayQueue=[],r.publish=t.publishCustomEvent,r.visitor=t.visitor,r.initialized=!0}}function A(e){B("manager_api_unavailable",void 0===e?void 0:Q(e))}function x(){B("script_load_failed","".concat(I," has failed to load"))}function B(e,t){T||(T=!0,q(),w.emit({status:"failed",errorMsg:t,failureReason:e,requestId:m.requestId,navigationType:m.navigationType,trekkieState:a()}))}function M(e){O&&(q(),w.emit({status:"pagehide-while-loading",useKeepaliveFallback:!0,pagehidePersisted:e.persisted,requestId:m.requestId,navigationType:m.navigationType,trekkieState:a()}))}function q(){O=!1;try{window.removeEventListener("pagehide",M)}catch(e){}}function R(e){var t;!function(e){var t=e.src,i=e.async,n=void 0===i||i,r=e.onload,o=e.onerror,a=e.sri,d=e.scriptDataAttributes,s=void 0===d?{}:d,u=document.createElement("script"),l=document.querySelector("head"),c=document.querySelector("body");if(u.async=n,u.src=t,a&&(u.integrity=a,u.crossOrigin="anonymous"),s)for(var p in s)if(Object.prototype.hasOwnProperty.call(s,p))try{u.dataset[p]=String(s[p])}catch(e){}if(r&&u.addEventListener("load",r),o&&u.addEventListener("error",o),l)l.appendChild(u);else{if(!c)throw new Error("Did not find a head or body element to append the script");c.appendChild(u)}}({src:I,async:!0,onload:U,onerror:e,sri:(t=E,"string"==typeof t&&/^sha384-[A-Za-z0-9+/=]+$/.test(t)?E:""),scriptDataAttributes:c})}function D(e){B("script_append_failed",Q(e))}function Q(e){return e instanceof Error?e.message:"Unknown error"}}}();wpmLoader({shopId: 52960723110,storefrontBaseUrl: "https://www.bostonproper.com",extensionsBaseUrl: "https://extensions.shopifycdn.com/cdn/shopifycloud/web-pixels-manager",monorailEndpoint: "https://www.bostonproper.com/.well-known/shopify/monorail/unstable/produce_batch",surface: "storefront-renderer",enabledBetaFlags: ["4c64608a","16072cab","8450a54b","7ee89bf1"],webPixelsConfigList: [{"id":"3346137254","configuration":"{\"storeIdentity\":\"bostonproper.myshopify.com\",\"baseURL\":\"https:\\\/\\\/api.printful.com\\\/shopify-pixels\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"74f275712857ab41bea9d998dcb2f9da","type":"APP","apiClientId":156624,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"3309076646","configuration":"{\"target\":\"https:\/\/us3-api.eng.bloomreach.com\", \"token\":\"discovery_pixel_token\", \"search_tracking\":\"true\", \"checkout_tracking\":\"false\", \"view_category_tracking\":\"true\", \"view_item_tracking\":\"true\", \"page_viewed_tracking\":\"false\", \"quick_view_tracking\":\"true\", \"suggest_tracking\":\"true\", \"cart_update_tracking\":\"true\", \"view_homepage_tracking\":\"true\", \"view_search_results_tracking\":\"true\", \"purchase_tracking\":\"true\", \"widget_view_tracking\":\"true\", \"widget_click_tracking\":\"true\", \"integration_id\":\"7fd16166-a982-463e-b56a-8e1f1c50ecd7\", \"gateway_url\":\"https:\/\/us3-api.eng.bloomreach.com\", \"domain\":\"bostonproper.myshopify.com\", \"stream_id\":\"d042b089-6e20-44b6-82b8-7bd75742c4a8\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"d45e93818bd39663ecc8d16ea4407a82","type":"APP","apiClientId":35679600641,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"3154477222","configuration":"{\"storeHandle\":\"bostonproper.myshopify.com\", \"publisherId\": \"P7C25MF72\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"94a881e8d211e628cef2d7cbc6e68cf4","type":"APP","apiClientId":343457300481,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_phone","read_customer_personal_data"],"dataSharingControls":["share_all_events"]}
12037,"dataSharingState":"unrestricted"},{"id":"3038904486","configuration":"{\"storeKey\":\"bog\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"347d2fe4d0c5c4fe761e9f8699b67474","type":"APP","apiClientId":43378180097,"privacyPurposes":[],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_email","read_customer_personal_data"],"dataSharingControls":["share_all_events"]},"dataSharingState":"unrestricted"},{"id":"2927460518","configuration":"{\"projectId\":\"v94zgzk99z\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"d8a2bb2ccbb513dc8e8b6937f4b8033e","type":"APP","apiClientId":240074326017,"privacyPurposes":[],"capabilities":["advanced_dom_events"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_personal_data"],"dataSharingControls":["share_all_events"]},"dataSharingState":"unrestricted"},{"id":"1857388710","configuration":"{\"pixelCode\":\"CMG5U8JC77UDUQCE3LVG\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"22e92c2ad45662f435e4801458fb78cc","type":"APP","apiClientId":4383523,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"1787723942","configuration":"{\"eventKey\":\"219c8a5d-569a-4644-8a21-6d301b41f586\",\"name\":\"bostonproper - Axon Pixel\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"fae105ca09bb030f70a8b83292a88611","type":"APP","apiClientId":256560922625,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"1686995110","configuration":"{\"pixelId\":\"d5052b6d-6a66-4b65-bb5d-37f5d558bb94\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"c119f01612c13b62ab52809eb08154bb","type":"APP","apiClientId":2556259,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"1653538982","configuration":"{\"accountID\":\"VZrTML\",\"webPixelConfig\":\"eyJlbmFibGVBZGRlZFRvQ2FydEV2ZW50cyI6IHRydWV9\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"c63c5b72c8d77be5f2d27d14c081da38","type":"APP","apiClientId":123074,"privacyPurposes":["ANALYTICS","MARKETING"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized","enabledFlags":["9a3ed68a"]},{"id":"1598685350","configuration":"{\"vibePixelId\":\"Nh1Pwu\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"72859894ec8aa8d5e0246c40aaed9466","type":"APP","apiClientId":132266098689,"privacyPurposes":["ANALYTICS","MARKETING"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":[],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"1383923878","configuration":"{\"isUserEvents\":\"enabled\",\"isSavePromiseDate\":\"enabled\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"6d0a6deccdda72f2ea2eba90a96ee634","type":"APP","apiClientId":1461275,"privacyPurposes":["ANALYTICS","PREFERENCES"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"unrestricted"},{"id":"1312194726","configuration":"{\"cart_viewed\":\"true\",\"checkout_address_info_submitted\":\"true\",\"checkout_completed\":\"true\",\"checkout_contact_info_submitted\":\"true\",\"checkout_shipping_info_submitted\":\"true\",\"checkout_started\":\"true\",\"collection_viewed\":\"true\",\"page_viewed\":\"true\",\"payment_info_submitted\":\"true\",\"product_added_to_cart\":\"true\",\"product_removed_from_cart\":\"true\",\"product_viewed\":\"true\",\"search_submitted\":\"true\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"4b912d4db8d67578541bfae8b70a40a9","type":"APP","apiClientId":100317265921,"privacyPurposes":["ANALYTICS"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":[],"dataSharingControls":["share_all_events"]}
12037,"dataSharingState":"unrestricted"},{"id":"1013219494","configuration":"{\"yotpoStoreId\":\"l9OjGj5YqKVR9PFonEHJc4ms9HXq9RV8dOWnI8LL\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"c5c2579aac465eb24ca7bc0501a6000d","type":"APP","apiClientId":70132,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"900497574","configuration":"{\"myshopifyDomain\":\"bostonproper.myshopify.com\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"23b97d18e2aa74363140dc29c9284e87","type":"APP","apiClientId":2775569,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_phone","read_customer_personal_data"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"159482022","configuration":"{\"partnerId\": \"51328\", \"environment\": \"prod\", \"countryCode\": \"US\", \"logLevel\": \"debug\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"e39367b785b1d63117e387ccb6b0db54","type":"APP","apiClientId":5829751,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_email","read_customer_personal_data"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized","enabledFlags":["9a3ed68a"]},{"id":"112263334","configuration":"{\"tagID\":\"2613459126604\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"7ae565e198624b39e0856d352b9a6b4c","type":"APP","apiClientId":3009811,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"26443942","configuration":"{ \"bundleName\": \"bostonproper\" }","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"6d69af31d151d9c0dc4842dc2c8531ca","type":"APP","apiClientId":5106349,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"13041830","configuration":"{\"northbeamId\": \"bad8c33b-2e51-4306-b610-a4bff168053e\", \"collectorDomain\": \"i.bostonproper.com\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"e46c2d6352a678fc6581f4bd0bc772e1","type":"APP","apiClientId":3188721,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"24903846","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"2","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"name":"Merkle \/ 4Cite tracking pixel"},{"id":"42565798","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"name":"Klaviyo Tracking"},{"id":"43909286","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"2","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"name":"Ascend"},{"id":"130089126","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":[],"name":"Postcard-Conversion-Pixel"},{"id":"142573734","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"name":"Northbeam Checkout Events"}
12037,{"id":"149815462","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"5","type":"CUSTOM","privacyPurposes":[],"name":"GTM \/ GA4 DataLayer"},{"id":"149848230","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"name":"Publitas"},{"id":"149913766","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"name":"Graphene"},{"id":"149946534","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"name":"Stylitics"},{"id":"155549862","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"name":"Fit Analytics V2"},{"id":"shopify-app-pixel","configuration":"{}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"0530","apiClientId":"shopify-pixel","type":"APP","privacyPurposes":["ANALYTICS","MARKETING"]},{"id":"shopify-custom-pixel","eventPayloadVersion":"v1","runtimeContext":"LAX","scriptVersion":"0530","apiClientId":"shopify-pixel","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING"]}],isMerchantRequest: false,initData: {"shop":{"name":"Boston Proper","paymentSettings":{"currencyCode":"USD"},"myshopifyDomain":"bostonproper.myshopify.com","countryCode":"US","storefrontUrl":"https:\/\/www.bostonproper.com"},"customer":null,"cart":null,"checkout":null,"productVariants":[{"price":{"amount":50.0,"currencyCode":"USD"},"product":{"title":"Boston Proper Printed Scarf With Love BP","vendor":"Boston Proper","id":"15286962618534","untranslatedTitle":"Boston Proper Printed Scarf With Love BP","url":"\/products\/boston-proper-printed-scarf-with-love-bp","type":"Promotions"},"id":"56389031657638","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198"},"sku":"2CT8071000","title":"With Love BP \/ One Size","untranslatedTitle":"With Love BP \/ One Size"}],"products":[{"id":"15286962618534","handle":"boston-proper-printed-scarf-with-love-bp","isCollective":false,"title":"Boston Proper Printed Scarf With Love BP","type":"Promotions","untranslatedTitle":"Boston Proper Printed Scarf With Love BP","url":"\/products\/boston-proper-printed-scarf-with-love-bp","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56389031657638","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198"},"price":{"amount":50.0,"currencyCode":"USD"},"sku":"2CT8071000","title":"With Love BP \/ One Size","untranslatedTitle":"With Love BP \/ One Size"}]},{"id":"15202416099494","handle":"boston-proper-printed-scarf-americana-bandana","isCollective":false,"title":"Boston Proper Printed Scarf Americana Bandana","type":"Promotions","untranslatedTitle":"Boston Proper Printed Scarf Americana Bandana","url":"\/products\/boston-proper-printed-scarf-americana-bandana","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56032129351846","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8031_SET.jpg?v=1791009109"},"price":{"amount":19.98,"currencyCode":"USD"},"sku":"2CT8031000","title":"Americana Bandana \/ One Size","untranslatedTitle":"Americana Bandana \/ One Size"}]},{"id":"8358210928806","handle":"boston-proper-printed-scarf-florence-fleur","isCollective":false,"title":"Boston Proper Printed Scarf Florence Fleur","type":"Promotions","untranslatedTitle":"Boston Proper Printed Scarf Florence Fleur","url":"\/products\/boston-proper-printed-scarf-florence-fleur","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"45993381560486","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8091_SET.jpg?v=1791008657"},"price":{"amount":50.0,"currencyCode":"USD"},"sku":"2CT8091000","title":"Florence Fleur \/ One Size","untranslatedTitle":"Florence Fleur \/ One Size"}]},{"id":"8464862806182","handle":"boston-proper-printed-scarf-flowers-of-hope","isCollective":false,"title":"Boston Proper Printed Scarf Flowers of Hope","type":"Promotions","untranslatedTitle":"Boston Proper Printed Scarf Flowers of Hope","url":"\/products\/boston-proper-printed-scarf-flowers-of-hope","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"46302477189286","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8070_SET_491d3f8a-0135-4d4a-b984-7131fa65c497.jpg?v=1791008846"},"price":{"amount":50.0,"currencyCode":"USD"},"sku":"2CT8070000","title":"Flowers of Hope \/ One Size","untranslatedTitle":"Flowers of Hope \/ One Size"}]},{"id":"8358199918758","handle":"boston-proper-printed-scarf-iris-garden","isCollective":false,"title":"Boston Proper Printed Scarf Iris Garden","type":"Promotions","untranslatedTitle":"Boston Proper Printed Scarf Iris Garden","url":"\/products\/boston-proper-printed-scarf-iris-garden","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"45993311436966","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8090_SET.jpg?v=1791008608"},"price":{"amount":50.0,"currencyCode":"USD"},"sku":"2CT8090000","title":"Iris Garden \/ One Size","untranslatedTitle":"Iris Garden \/ One Size"}]},{"id":"8595151159462","handle":"boston-proper-printed-scarf-party-polka","isCollective":false,"title":"Boston Proper Printed Scarf Party Polka","type":"Promotions","untranslatedTitle":"Boston Proper Printed Scarf Party Polka","url":"\/products\/boston-proper-printed-scarf-party-polka","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"46716370288806","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8020_SET_dc17f3cc-0922-44e3-b186-0430474125fb.jpg?v=1791009015"},"price":{"amount":50.0,"currencyCode":"USD"},"sku":"2CT8020000","title":"Party Polka \/ One Size","untranslatedTitle":"Party Polka \/ One Size"}]},{"id":"8622122041510","handle":"boston-proper-printed-scarf-stunning-sealife","isCollective":false,"title":"Boston Proper Printed Scarf Stunning Sealife","type":"Promotions","untranslatedTitle":"Boston Proper Printed Scarf Stunning Sealife","url":"\/products\/boston-proper-printed-scarf-stunning-sealife","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"46789620039846","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8030_SET.jpg?v=1791009065"},"price":{"amount":50.0,"currencyCode":"USD"},"sku":"2CT8030000","title":"Stunning Sealife \/ One Size","untranslatedTitle":"Stunning Sealife \/ One Size"}]}
12037,{"id":"15399681392806","handle":"leopard-print-skirt-brown-multi","isCollective":false,"title":"Leopard Print Skirt Brown Multi","type":"Skirts","untranslatedTitle":"Leopard Print Skirt Brown Multi","url":"\/products\/leopard-print-skirt-brown-multi","vendor":"Bagatelle","remoteShopId":null,"variants":[{"id":"56779671077030","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO3390_SET.jpg?v=1791009176"},"price":{"amount":110.0,"currencyCode":"USD"},"sku":"2DO3390800","title":"Brown Multi \/ L","untranslatedTitle":"Brown Multi \/ L"}]},{"id":"15399681360038","handle":"metallic-zebra-printed-dress-tan-multi","isCollective":false,"title":"Metallic Zebra Printed Dress Tan Multi","type":"Dresses","untranslatedTitle":"Metallic Zebra Printed Dress Tan Multi","url":"\/products\/metallic-zebra-printed-dress-tan-multi","vendor":"Bagatelle","remoteShopId":null,"variants":[{"id":"56779670782118","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO0590_SET.jpg?v=1791009160"},"price":{"amount":180.0,"currencyCode":"USD"},"sku":"2DO0590006","title":"Tan Multi \/ 6","untranslatedTitle":"Tan Multi \/ 6"}]},{"id":"15399680114854","handle":"sam-edelman-fur-lace-up-bootie-tan","isCollective":false,"title":"Sam Edelman Fur Lace Up Bootie Tan","type":"Shoes","untranslatedTitle":"Sam Edelman Fur Lace Up Bootie Tan","url":"\/products\/sam-edelman-fur-lace-up-bootie-tan","vendor":"Sam Edelman","remoteShopId":null,"variants":[{"id":"56779666161830","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO5680_SET.jpg?v=1791009185"},"price":{"amount":180.0,"currencyCode":"USD"},"sku":"2DO5680060","title":"Tan \/ 6.0","untranslatedTitle":"Tan \/ 6.0"}]},{"id":"15399680082086","handle":"ultimate-velvet-double-breasted-shaped-blazer-black","isCollective":false,"title":"Ultimate Velvet Double Breasted Shaped Blazer Black","type":"Jackets","untranslatedTitle":"Ultimate Velvet Double Breasted Shaped Blazer Black","url":"\/products\/ultimate-velvet-double-breasted-shaped-blazer-black","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56779665801382","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP1920_SET.jpg?v=1791009211"},"price":{"amount":150.0,"currencyCode":"USD"},"sku":"2DP1920002","title":"Black \/ 2","untranslatedTitle":"Black \/ 2"}]},{"id":"15371225596070","handle":"breast-cancer-awareness-graphic-sweatshirt-azalea","isCollective":false,"title":"Breast Cancer Awareness Graphic Sweatshirt Azalea","type":"Athleisure","untranslatedTitle":"Breast Cancer Awareness Graphic Sweatshirt Azalea","url":"\/products\/breast-cancer-awareness-graphic-sweatshirt-azalea","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56671921471654","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DR2070_SET.jpg?v=1791009256"},"price":{"amount":60.0,"currencyCode":"USD"},"sku":"2DR2070700","title":"Azalea \/ M","untranslatedTitle":"Azalea \/ M"}]},{"id":"15366923452582","handle":"mock-neck-intarsia-flare-sleeve-tunic-west-side-paisley","isCollective":false,"title":"Mock Neck Intarsia Flare Sleeve Tunic West Side Paisley","type":"Sweater Tops","untranslatedTitle":"Mock Neck Intarsia Flare Sleeve Tunic West Side Paisley","url":"\/products\/mock-neck-intarsia-flare-sleeve-tunic-west-side-paisley","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56658234933414","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DM9540_SET.jpg?v=1791009180"},"price":{"amount":100.0,"currencyCode":"USD"},"sku":"2DM9540400","title":"West Side Paisley \/ XXS","untranslatedTitle":"West Side Paisley \/ XXS"}]},{"id":"15364508745894","handle":"bcbgeneration-hardware-strap-to-the-knee-boot-cognac","isCollective":false,"title":"BCBGeneration Hardware Strap To The Knee Boot Cognac","type":"Shoes","untranslatedTitle":"BCBGeneration Hardware Strap To The Knee Boot Cognac","url":"\/products\/bcbgeneration-hardware-strap-to-the-knee-boot-cognac","vendor":"BCBG","remoteShopId":null,"variants":[{"id":"56648379236518","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO6680_SET_538a0547-6fc7-4be8-8b60-4ea8b9720f2e.jpg?v=1791009184"},"price":{"amount":89.0,"currencyCode":"USD"},"sku":"2DO6680060","title":"Cognac \/ 6.0","untranslatedTitle":"Cognac \/ 6.0"}]}
12037,{"id":"15363223355558","handle":"high-waisted-sport-legging-cherry-lacquer","isCollective":false,"title":"High Waisted Sport Legging Cherry Lacquer","type":"Athleisure","untranslatedTitle":"High Waisted Sport Legging Cherry Lacquer","url":"\/products\/high-waisted-sport-legging-cherry-lacquer","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56643511681190","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DB3271_SET.jpg?v=1791009254"},"price":{"amount":50.0,"currencyCode":"USD"},"sku":"2DB3271500","title":"Cherry Lacquer \/ XS","untranslatedTitle":"Cherry Lacquer \/ XS"}]},{"id":"15342913847462","handle":"herringbone-double-breasted-blazer-with-rhinestone-embellishment-gold-gray-multi","isCollective":false,"title":"Herringbone Double Breasted Blazer With Rhinestone Embellishment Gold\/Gray Multi","type":"Jackets","untranslatedTitle":"Herringbone Double Breasted Blazer With Rhinestone Embellishment Gold\/Gray Multi","url":"\/products\/herringbone-double-breasted-blazer-with-rhinestone-embellishment-gold-gray-multi","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56564923891878","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP1690_SET.jpg?v=1791009251"},"price":{"amount":250.0,"currencyCode":"USD"},"sku":"2DP1690006","title":"Gold\/Gray Multi \/ 6","untranslatedTitle":"Gold\/Gray Multi \/ 6"}]},{"id":"15336227864742","handle":"knit-suede-drape-front-jacket-stone","isCollective":false,"title":"Knit Suede Drape Front Jacket Stone","type":"Jackets","untranslatedTitle":"Knit Suede Drape Front Jacket Stone","url":"\/products\/knit-suede-drape-front-jacket-stone","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56545549123750","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DR1780_SET.jpg?v=1791009250"},"price":{"amount":125.0,"currencyCode":"USD"},"sku":"2DR1780400","title":"Stone \/ XXS","untranslatedTitle":"Stone \/ XXS"}]},{"id":"15336227831974","handle":"knit-suede-drape-front-jacket-blue","isCollective":false,"title":"Knit Suede Drape Front Jacket Blue","type":"Jackets","untranslatedTitle":"Knit Suede Drape Front Jacket Blue","url":"\/products\/knit-suede-drape-front-jacket-blue","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56545548927142","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DR1730_SET_9fea2518-0e42-496d-aca4-19f54a5af591.jpg?v=1791009249"},"price":{"amount":125.0,"currencyCode":"USD"},"sku":"2DR1730400","title":"Blue \/ XXS","untranslatedTitle":"Blue \/ XXS"}]},{"id":"15334258868390","handle":"half-zip-sparkle-snowflake-sweater-french-kiss","isCollective":false,"title":"Half Zip Sparkle Snowflake Sweater French Kiss","type":"Sweater Tops","untranslatedTitle":"Half Zip Sparkle Snowflake Sweater French Kiss","url":"\/products\/half-zip-sparkle-snowflake-sweater-french-kiss","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56539690696870","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ0611_SET.jpg?v=1791009258"},"price":{"amount":100.0,"currencyCode":"USD"},"sku":"2DQ0611500","title":"French Kiss \/ XS","untranslatedTitle":"French Kiss \/ XS"}]},{"id":"15321518833830","handle":"velvet-sequin-strapless-gown-with-scarf-emerald","isCollective":false,"title":"Velvet Sequin Strapless Gown with Scarf Emerald","type":"Dresses","untranslatedTitle":"Velvet Sequin Strapless Gown with Scarf Emerald","url":"\/products\/velvet-sequin-strapless-gown-with-scarf-emerald","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56499191120038","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DR1460_SET_2cbf8591-5dcd-479c-845e-834d7eb0cb64.jpg?v=1791009253"},"price":{"amount":220.0,"currencyCode":"USD"},"sku":"2DR1460400","title":"Emerald \/ XXS","untranslatedTitle":"Emerald \/ XXS"}]},{"id":"15317730918566","handle":"faux-fur-tote-bag-multi","isCollective":false,"title":"Faux Fur Tote Bag Multi","type":"Accessories","untranslatedTitle":"Faux Fur Tote Bag Multi","url":"\/products\/faux-fur-tote-bag-multi","vendor":"Daisy Rose","remoteShopId":null,"variants":[{"id":"56483682812070","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DR0290_SET.jpg?v=1791009247"},"price":{"amount":95.0,"currencyCode":"USD"},"sku":"2DR0290000","title":"Multi \/ One Size","untranslatedTitle":"Multi \/ One Size"}]}
12037,{"id":"15314674811046","handle":"ultimate-ponte-back-zip-skirt-proper-black","isCollective":false,"title":"Ultimate Ponte Back Zip Skirt Proper Black","type":"Skirts","untranslatedTitle":"Ultimate Ponte Back Zip Skirt Proper Black","url":"\/products\/ultimate-ponte-back-zip-skirt-proper-black","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56473775669414","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DN1520_SET_414c1527-6223-4932-ab01-9883dffc85b9.jpg?v=1791009230"},"price":{"amount":75.0,"currencyCode":"USD"},"sku":"2DN1520400","title":"Proper Black \/ XXS","untranslatedTitle":"Proper Black \/ XXS"}]},{"id":"15314674253990","handle":"printed-multi-ruffle-v-neck-blouse-leopard","isCollective":false,"title":"Printed Multi Ruffle V Neck Blouse Leopard","type":"Woven Tops","untranslatedTitle":"Printed Multi Ruffle V Neck Blouse Leopard","url":"\/products\/printed-multi-ruffle-v-neck-blouse-leopard","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56473771278502","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ6190_SET.jpg?v=1791009243"},"price":{"amount":100.0,"currencyCode":"USD"},"sku":"2DQ6190400","title":"Leopard \/ XXS","untranslatedTitle":"Leopard \/ XXS"}]},{"id":"15314673795238","handle":"belted-trench-luxe-wool-coat-chocolate-torte","isCollective":false,"title":"Belted Trench Luxe Wool Coat Chocolate Torte","type":"Outerwear","untranslatedTitle":"Belted Trench Luxe Wool Coat Chocolate Torte","url":"\/products\/belted-trench-luxe-wool-coat-chocolate-torte","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56473768427686","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP6680_SET_69366f09-7a73-492d-922f-e6e6a7f5d5f1.jpg?v=1791009236"},"price":{"amount":200.0,"currencyCode":"USD"},"sku":"2DP6680400","title":"Chocolate Torte \/ XXS","untranslatedTitle":"Chocolate Torte \/ XXS"}]},{"id":"15312523722918","handle":"cozy-faux-fur-slide-dove-grey","isCollective":false,"title":"Cozy Faux Fur Slide Dove Grey","type":"Shoes","untranslatedTitle":"Cozy Faux Fur Slide Dove Grey","url":"\/products\/cozy-faux-fur-slide-dove-grey","vendor":"Matisse","remoteShopId":null,"variants":[{"id":"56470391881894","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO5230_SET_6e2012f3-5f8c-4ecb-a141-34579cc2000c.jpg?v=1791009236"},"price":{"amount":65.0,"currencyCode":"USD"},"sku":"2DO5230060","title":"Dove Grey \/ 6.0","untranslatedTitle":"Dove Grey \/ 6.0"}]},{"id":"15311695413414","handle":"monterey-high-rise-faux-leather-trouser-gunmetal","isCollective":false,"title":"Monterey High Rise Faux Leather Trouser Gunmetal","type":"Pants","untranslatedTitle":"Monterey High Rise Faux Leather Trouser Gunmetal","url":"\/products\/monterey-high-rise-faux-leather-trouser-gunmetal","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56468015808678","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DN3090_SET.jpg?v=1791009234"},"price":{"amount":110.0,"currencyCode":"USD"},"sku":"2DN3090000","title":"Gunmetal \/ 0","untranslatedTitle":"Gunmetal \/ 0"}]},{"id":"15311695282342","handle":"beyond-travel-tunic-coordinate-set-jet-black","isCollective":false,"title":"Beyond Travel Tunic Coordinate Set Jet Black","type":"Athleisure","untranslatedTitle":"Beyond Travel Tunic Coordinate Set Jet Black","url":"\/products\/beyond-travel-tunic-coordinate-set-jet-black","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56468015022246","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DA2820_SET.jpg?v=1791009229"},"price":{"amount":150.0,"currencyCode":"USD"},"sku":"2DA2820400","title":"Jet Black \/ XXS","untranslatedTitle":"Jet Black \/ XXS"}]},{"id":"15309443694758","handle":"crystal-embellished-faux-fur-chubby-hunt-club","isCollective":false,"title":"Crystal Embellished Faux Fur Chubby Hunt Club","type":"Outerwear","untranslatedTitle":"Crystal Embellished Faux Fur Chubby Hunt Club","url":"\/products\/crystal-embellished-faux-fur-chubby-hunt-club","vendor":"Dolce Cabo","remoteShopId":null,"variants":[{"id":"56461571424422","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP9360_SET.jpg?v=1791009227"},"price":{"amount":190.0,"currencyCode":"USD"},"sku":"2DP9360500","title":"Hunt Club \/ XS","untranslatedTitle":"Hunt Club \/ XS"}]}
12037,{"id":"15309443661990","handle":"velvet-scoop-neck-tank-black","isCollective":false,"title":"Velvet Scoop Neck Tank Black","type":"Knit Tops","untranslatedTitle":"Velvet Scoop Neck Tank Black","url":"\/products\/velvet-scoop-neck-tank-black","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56461571195046","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP5920_SET_138cab40-f130-435d-9513-06df8f4abe2b.jpg?v=1791009226"},"price":{"amount":50.0,"currencyCode":"USD"},"sku":"2DP5920400","title":"Black \/ XXS","untranslatedTitle":"Black \/ XXS"}]},{"id":"15309443629222","handle":"embellished-cable-turtleneck-sweater-tank-airy-blue","isCollective":false,"title":"Embellished Cable Turtleneck Sweater Tank Airy Blue","type":"Sweater Tops","untranslatedTitle":"Embellished Cable Turtleneck Sweater Tank Airy Blue","url":"\/products\/embellished-cable-turtleneck-sweater-tank-airy-blue","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56461570998438","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CP9531_SET.jpg?v=1791009225"},"price":{"amount":95.0,"currencyCode":"USD"},"sku":"2CP9531400","title":"Airy Blue \/ XXS","untranslatedTitle":"Airy Blue \/ XXS"}]},{"id":"15309443596454","handle":"faux-fur-embellished-cable-duster-airy-blue","isCollective":false,"title":"Faux Fur Embellished Cable Duster Airy Blue","type":"Sweater Tops","untranslatedTitle":"Faux Fur Embellished Cable Duster Airy Blue","url":"\/products\/faux-fur-embellished-cable-duster-airy-blue","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56461570801830","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CQ1531_SET_ecd9640b-58df-465f-92d6-45d3dce125bc.jpg?v=1791009224"},"price":{"amount":190.0,"currencyCode":"USD"},"sku":"2CQ1531400","title":"Airy Blue \/ XXS","untranslatedTitle":"Airy Blue \/ XXS"}]},{"id":"15309443563686","handle":"scoop-neck-balloon-sleeve-sweater-dress-airy-blue","isCollective":false,"title":"Scoop Neck Balloon Sleeve Sweater Dress Airy Blue","type":"Dresses","untranslatedTitle":"Scoop Neck Balloon Sleeve Sweater Dress Airy Blue","url":"\/products\/scoop-neck-balloon-sleeve-sweater-dress-airy-blue","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56461570605222","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CG7532_SET_e76ef1c1-7fac-44ba-8a01-76aa20799aaa.jpg?v=1791009223"},"price":{"amount":120.0,"currencyCode":"USD"},"sku":"2CG7532700","title":"Airy Blue \/ M","untranslatedTitle":"Airy Blue \/ M"}]},{"id":"15300355522726","handle":"boucle-yarn-slouchy-sweater-ballerina","isCollective":false,"title":"Boucle Yarn Slouchy Sweater Ballerina","type":"Sweater Tops","untranslatedTitle":"Boucle Yarn Slouchy Sweater Ballerina","url":"\/products\/boucle-yarn-slouchy-sweater-ballerina","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56437744074918","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP7170_SET.jpg?v=1791009221"},"price":{"amount":75.0,"currencyCode":"USD"},"sku":"2DP7170400","title":"Ballerina \/ XXS","untranslatedTitle":"Ballerina \/ XXS"}]},{"id":"15300355489958","handle":"boucle-yarn-slouchy-sweater-off-white","isCollective":false,"title":"Boucle Yarn Slouchy Sweater Off White","type":"Sweater Tops","untranslatedTitle":"Boucle Yarn Slouchy Sweater Off White","url":"\/products\/boucle-yarn-slouchy-sweater-off-white","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56437743878310","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP7140_SET.jpg?v=1791009220"},"price":{"amount":75.0,"currencyCode":"USD"},"sku":"2DP7140400","title":"Off White \/ XXS","untranslatedTitle":"Off White \/ XXS"}]},{"id":"15298631663782","handle":"rhinestone-and-chain-statement-necklace-silver","isCollective":false,"title":"Rhinestone and Chain Statement Necklace Silver","type":"Accessories","untranslatedTitle":"Rhinestone and Chain Statement Necklace Silver","url":"\/products\/rhinestone-and-chain-statement-necklace-silver","vendor":"Noir Jewelry","remoteShopId":null,"variants":[{"id":"56433081352358","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ2390_SET.jpg?v=1791009231"},"price":{"amount":90.0,"currencyCode":"USD"},"sku":"2DQ2390000","title":"Silver \/ One Size","untranslatedTitle":"Silver \/ One Size"}]}
12037,{"id":"15298232746150","handle":"stone-detail-chain-belt-gold","isCollective":false,"title":"Stone Detail Chain Belt Gold","type":"Accessories","untranslatedTitle":"Stone Detail Chain Belt Gold","url":"\/products\/stone-detail-chain-belt-gold","vendor":"Noir Jewelry","remoteShopId":null,"variants":[{"id":"56430366195878","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ2250_SET.jpg?v=1791009228"},"price":{"amount":100.0,"currencyCode":"USD"},"sku":"2DQ2250600","title":"Gold \/ S","untranslatedTitle":"Gold \/ S"}]},{"id":"15297645117606","handle":"monterey-luxe-metallic-embroidered-bootcut-jean-proper-black","isCollective":false,"title":"Monterey Luxe Metallic Embroidered Bootcut Jean Proper Black","type":"Jeans","untranslatedTitle":"Monterey Luxe Metallic Embroidered Bootcut Jean Proper Black","url":"\/products\/monterey-luxe-metallic-embroidered-bootcut-jean-proper-black","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56425487270054","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ2020_SET_933e8aa4-ac0f-4bb2-8b47-093904f21fed.jpg?v=1791009226"},"price":{"amount":140.0,"currencyCode":"USD"},"sku":"2DQ2020004","title":"Proper Black \/ 4","untranslatedTitle":"Proper Black \/ 4"}]},{"id":"15295577850022","handle":"charmeuse-ruffle-collar-long-sleeve-blouse-proper-black","isCollective":false,"title":"Charmeuse Ruffle Collar Long Sleeve Blouse Proper Black","type":"Woven Tops","untranslatedTitle":"Charmeuse Ruffle Collar Long Sleeve Blouse Proper Black","url":"\/products\/charmeuse-ruffle-collar-long-sleeve-blouse-proper-black","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56414501273766","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP2020_SET_002f3099-0a4b-44ea-989c-a016142b9e8f.jpg?v=1791009225"},"price":{"amount":80.0,"currencyCode":"USD"},"sku":"2DP2020400","title":"Proper Black \/ XXS","untranslatedTitle":"Proper Black \/ XXS"}]},{"id":"15295577817254","handle":"charmeuse-ruffle-collar-long-sleeve-blouse-hunt-club","isCollective":false,"title":"Charmeuse Ruffle Collar Long Sleeve Blouse Hunt Club","type":"Woven Tops","untranslatedTitle":"Charmeuse Ruffle Collar Long Sleeve Blouse Hunt Club","url":"\/products\/charmeuse-ruffle-collar-long-sleeve-blouse-hunt-club","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56414501077158","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP2060_SET.jpg?v=1791009223"},"price":{"amount":80.0,"currencyCode":"USD"},"sku":"2DP2060400","title":"Hunt Club \/ XXS","untranslatedTitle":"Hunt Club \/ XXS"}]},{"id":"15293973856422","handle":"marilyn-cowl-neck-charmeuse-blouse-french-kiss","isCollective":false,"title":"Marilyn Cowl-Neck Charmeuse Blouse French Kiss","type":"Woven Tops","untranslatedTitle":"Marilyn Cowl-Neck Charmeuse Blouse French Kiss","url":"\/products\/marilyn-cowl-neck-charmeuse-blouse-french-kiss","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56408288198822","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2BK4516_SET.jpg?v=1791009189"},"price":{"amount":70.0,"currencyCode":"USD"},"sku":"2BK4516400","title":"French Kiss \/ XXS","untranslatedTitle":"French Kiss \/ XXS"}]},{"id":"15292963324070","handle":"printed-lurex-lace-up-tunic-golden-status","isCollective":false,"title":"Printed Lurex Lace Up Tunic Golden Status","type":"Sweater Tops","untranslatedTitle":"Printed Lurex Lace Up Tunic Golden Status","url":"\/products\/printed-lurex-lace-up-tunic-golden-status","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56404613333158","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ1980_SET_591f4bf8-5eaf-4477-8dd5-af53f3f7528f.jpg?v=1791009222"},"price":{"amount":110.0,"currencyCode":"USD"},"sku":"2DQ1980400","title":"Golden Status \/ XXS","untranslatedTitle":"Golden Status \/ XXS"}]},{"id":"15292963291302","handle":"stretch-velvet-puff-sleeve-trucker-champagne","isCollective":false,"title":"Stretch Velvet Puff Sleeve Trucker Champagne","type":"Jackets","untranslatedTitle":"Stretch Velvet Puff Sleeve Trucker Champagne","url":"\/products\/stretch-velvet-puff-sleeve-trucker-champagne","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56404613136550","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ0440_SET.jpg?v=1791009221"},"price":{"amount":150.0,"currencyCode":"USD"},"sku":"2DQ0440400","title":"Champagne \/ XXS","untranslatedTitle":"Champagne \/ XXS"}]}
12037,{"id":"15291328692390","handle":"sophia-pearl-embellished-charmeuse-shirt-proper-black","isCollective":false,"title":"Sophia Pearl Embellished Charmeuse Shirt Proper Black","type":"Woven Tops","untranslatedTitle":"Sophia Pearl Embellished Charmeuse Shirt Proper Black","url":"\/products\/sophia-pearl-embellished-charmeuse-shirt-proper-black","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56400671244454","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP7220_SET.jpg?v=1791009219"},"price":{"amount":100.0,"currencyCode":"USD"},"sku":"2DP7220000","title":"Proper Black \/ 0","untranslatedTitle":"Proper Black \/ 0"}]},{"id":"15291328659622","handle":"faux-fur-trimmed-cuff-shimmer-sweater-duster-coral-blush","isCollective":false,"title":"Faux Fur Trimmed Cuff Shimmer Sweater Duster Coral Blush","type":"Sweater Tops","untranslatedTitle":"Faux Fur Trimmed Cuff Shimmer Sweater Duster Coral Blush","url":"\/products\/faux-fur-trimmed-cuff-shimmer-sweater-duster-coral-blush","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56400671047846","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP5470_SET.jpg?v=1791009218"},"price":{"amount":140.0,"currencyCode":"USD"},"sku":"2DP5470500","title":"Coral Blush \/ XS","untranslatedTitle":"Coral Blush \/ XS"}]},{"id":"15291328594086","handle":"print-sophia-charmeuse-blouse-frozen-fleurs","isCollective":false,"title":"Print Sophia Charmeuse Blouse Frozen Fleurs","type":"Woven Tops","untranslatedTitle":"Print Sophia Charmeuse Blouse Frozen Fleurs","url":"\/products\/print-sophia-charmeuse-blouse-frozen-fleurs","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56400670392486","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CV2032_SET.jpg?v=1791009216"},"price":{"amount":90.0,"currencyCode":"USD"},"sku":"2CV2032008","title":"Frozen Fleurs \/ 8","untranslatedTitle":"Frozen Fleurs \/ 8"}]},{"id":"15288327766182","handle":"gold-hardware-leopard-belt-multi","isCollective":false,"title":"Gold Hardware Leopard Belt Multi","type":"Accessories","untranslatedTitle":"Gold Hardware Leopard Belt Multi","url":"\/products\/gold-hardware-leopard-belt-multi","vendor":"Jardin","remoteShopId":null,"variants":[{"id":"56483682680998","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ0990_SET_e3c6c6a7-db56-4b09-bbc2-71da6137b642.jpg?v=1791009225"},"price":{"amount":100.0,"currencyCode":"USD"},"sku":"2DQ0990600","title":"Multi \/ S","untranslatedTitle":"Multi \/ S"}]},{"id":"15288327733414","handle":"plaid-ultimate-ponte-wide-leg-pant-charcoal-gray-multi","isCollective":false,"title":"Plaid Ultimate Ponte Wide Leg Pant Charcoal Gray Multi","type":"Pants","untranslatedTitle":"Plaid Ultimate Ponte Wide Leg Pant Charcoal Gray Multi","url":"\/products\/plaid-ultimate-ponte-wide-leg-pant-charcoal-gray-multi","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56393534079142","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ0830_SET.jpg?v=1791009224"},"price":{"amount":100.0,"currencyCode":"USD"},"sku":"2DQ0830500","title":"Charcoal Gray Multi \/ XS","untranslatedTitle":"Charcoal Gray Multi \/ XS"}]},{"id":"15288327667878","handle":"straight-wideleg-denim-jean-winter-light-wash","isCollective":false,"title":"Straight Wideleg Denim Jean Winter Light Wash","type":"Jeans","untranslatedTitle":"Straight Wideleg Denim Jean Winter Light Wash","url":"\/products\/straight-wideleg-denim-jean-winter-light-wash","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56393533554854","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP5730_SET.jpg?v=1791009222"},"price":{"amount":90.0,"currencyCode":"USD"},"sku":"2DP5730002","title":"Winter Light Wash \/ 2","untranslatedTitle":"Winter Light Wash \/ 2"}]},{"id":"15287638065318","handle":"half-zip-sparkle-snowflake-sweater-hunt-club","isCollective":false,"title":"Half Zip Sparkle Snowflake Sweater Hunt Club","type":"Sweater Tops","untranslatedTitle":"Half Zip Sparkle Snowflake Sweater Hunt Club","url":"\/products\/half-zip-sparkle-snowflake-sweater-hunt-club","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56391359561894","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ0660_SET.jpg?v=1791009216"},"price":{"amount":100.0,"currencyCode":"USD"},"sku":"2DQ0660400","title":"Hunt Club \/ XXS","untranslatedTitle":"Hunt Club \/ XXS"}]}
12037,{"id":"15287638032550","handle":"mid-length-fur-trimmed-puffer-coat-warm-cheetah","isCollective":false,"title":"Mid Length Fur Trimmed Puffer Coat Warm Cheetah","type":"Outerwear","untranslatedTitle":"Mid Length Fur Trimmed Puffer Coat Warm Cheetah","url":"\/products\/mid-length-fur-trimmed-puffer-coat-warm-cheetah","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56391359365286","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ0590_SET.jpg?v=1791009214"},"price":{"amount":200.0,"currencyCode":"USD"},"sku":"2DQ0590400","title":"Warm Cheetah \/ XXS","untranslatedTitle":"Warm Cheetah \/ XXS"}]},{"id":"15287637999782","handle":"mid-length-fur-trimmed-puffer-coat-chocolate-torte","isCollective":false,"title":"Mid Length Fur Trimmed Puffer Coat Chocolate Torte","type":"Outerwear","untranslatedTitle":"Mid Length Fur Trimmed Puffer Coat Chocolate Torte","url":"\/products\/mid-length-fur-trimmed-puffer-coat-chocolate-torte","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56391359168678","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ0580_SET.jpg?v=1791009214"},"price":{"amount":200.0,"currencyCode":"USD"},"sku":"2DQ0580400","title":"Chocolate Torte \/ XXS","untranslatedTitle":"Chocolate Torte \/ XXS"}]},{"id":"15287637934246","handle":"novelty-velvet-burnout-mock-neck-proper-black","isCollective":false,"title":"Novelty Velvet Burnout Mock Neck Proper Black","type":"Knit Tops","untranslatedTitle":"Novelty Velvet Burnout Mock Neck Proper Black","url":"\/products\/novelty-velvet-burnout-mock-neck-proper-black","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56391358775462","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ0220_SET.jpg?v=1791009213"},"price":{"amount":65.0,"currencyCode":"USD"},"sku":"2DQ0220400","title":"Proper Black \/ XXS","untranslatedTitle":"Proper Black \/ XXS"}]},{"id":"15287637868710","handle":"pearl-and-bead-clutch-white","isCollective":false,"title":"Pearl and Bead Clutch White","type":"Accessories","untranslatedTitle":"Pearl and Bead Clutch White","url":"\/products\/pearl-and-bead-clutch-white","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56391358546086","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ0040_SET_904fd260-3453-4aed-8cba-110e8361e8f9.jpg?v=1791009212"},"price":{"amount":80.0,"currencyCode":"USD"},"sku":"2DQ0040000","title":"White \/ One Size","untranslatedTitle":"White \/ One Size"}]},{"id":"15287637835942","handle":"crystal-embellished-waist-belt-black-silver","isCollective":false,"title":"Crystal Embellished Waist Belt Black\/Silver","type":"Accessories","untranslatedTitle":"Crystal Embellished Waist Belt Black\/Silver","url":"\/products\/crystal-embellished-waist-belt-black-silver","vendor":"Noir Jewelry","remoteShopId":null,"variants":[{"id":"56391358480550","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP9920_SET.jpg?v=1791009211"},"price":{"amount":80.0,"currencyCode":"USD"},"sku":"2DP9920000","title":"Black\/Silver \/ One Size","untranslatedTitle":"Black\/Silver \/ One Size"}]},{"id":"15287637770406","handle":"fit-and-flare-sweater-dress-italian-plum","isCollective":false,"title":"Fit and Flare Sweater Dress Italian Plum","type":"Dresses","untranslatedTitle":"Fit and Flare Sweater Dress Italian Plum","url":"\/products\/fit-and-flare-sweater-dress-italian-plum","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56391358251174","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP7370_SET.jpg?v=1791009215"},"price":{"amount":120.0,"currencyCode":"USD"},"sku":"2DP7370400","title":"Italian Plum \/ XXS","untranslatedTitle":"Italian Plum \/ XXS"}]},{"id":"15287637672102","handle":"fit-and-flare-sweater-dress-black","isCollective":false,"title":"Fit and Flare Sweater Dress Black","type":"Dresses","untranslatedTitle":"Fit and Flare Sweater Dress Black","url":"\/products\/fit-and-flare-sweater-dress-black","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56391357989030","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP7320_SET.jpg?v=1791009213"},"price":{"amount":120.0,"currencyCode":"USD"},"sku":"2DP7320400","title":"Black \/ XXS","untranslatedTitle":"Black \/ XXS"}]}
12037,{"id":"15287637639334","handle":"sequin-scoop-neck-tank-hunt-club","isCollective":false,"title":"Sequin Scoop Neck Tank Hunt Club","type":"Knit Tops","untranslatedTitle":"Sequin Scoop Neck Tank Hunt Club","url":"\/products\/sequin-scoop-neck-tank-hunt-club","vendor":"Boston Proper","remoteShopId":null,"variants":[{"id":"56391357792422","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP6060_SET.jpg?v=1791009217"},"price":{"amount":60.0,"currencyCode":"USD"},"sku":"2DP6060400","title":"Hunt Club \/ XXS","untranslatedTitle":"Hunt Club \/ XXS"}]},{"id":"8529230004390","handle":"narvardeliveryprotection","isCollective":false,"title":"Shipping Protection","type":"insurance","untranslatedTitle":"Shipping Protection","url":"\/products\/narvardeliveryprotection","vendor":"NARVARDELIVERYPROTECTION","remoteShopId":null,"variants":[{"id":"46514716934310","image":{"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/ups-insureshield_5f014e53-930a-40e4-aeec-7d39ade750ef.png?v=1753728255"},"price":{"amount":0.0,"currencyCode":"USD"},"sku":"NARVARDELIVERYPROTECTION","title":"Default Title","untranslatedTitle":"Default Title"}]}],"purchasingCompany":null},},"https://www.bostonproper.com/cdn","5982071ew7ea472e3p69b68784m2150dfea",{"modern":"","legacy":""},{"trekkieShim":true,"agentContext":true,"apiClientId":"580111","facebookCapiEnabled":"false","themeId":"198106775718","themePublished":"true","eventMetadataId":"bd74b2c2-c5f8-444d-a394-a9f515df4e89","pageType":"product","resourceId":"15286962618534","shopId":"52960723110","storefrontBaseUrl":"https:\/\/www.bostonproper.com","extensionBaseUrl":"https:\/\/extensions.shopifycdn.com\/cdn\/shopifycloud\/web-pixels-manager","surface":"storefront-renderer","enabledBetaFlags":"[\"4c64608a\", \"16072cab\", \"8450a54b\", \"7ee89bf1\"]","isMerchantRequest":"false","hashVersion":"5982071ew7ea472e3p69b68784m2150dfea","publish":"custom","events":"[[\"page_viewed\",{}],[\"product_viewed\",{\"productVariant\":{\"price\":{\"amount\":50.0,\"currencyCode\":\"USD\"},\"product\":{\"title\":\"Boston Proper Printed Scarf With Love BP\",\"vendor\":\"Boston Proper\",\"id\":\"15286962618534\",\"untranslatedTitle\":\"Boston Proper Printed Scarf With Love BP\",\"url\":\"\/products\/boston-proper-printed-scarf-with-love-bp\",\"type\":\"Promotions\"},\"id\":\"56389031657638\",\"image\":{\"src\":\"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198\"},\"sku\":\"2CT8071000\",\"title\":\"With Love BP \/ One Size\",\"untranslatedTitle\":\"With Love BP \/ One Size\"}}]]"});})();</script>
12037<script>
12038  window.ShopifyAnalytics = window.ShopifyAnalytics || {};
12039  window.ShopifyAnalytics.meta = window.ShopifyAnalytics.meta || {};
12040  window.ShopifyAnalytics.meta.currency = 'USD';
12041  var meta = {"product":{"id":15286962618534,"gid":"gid:\/\/shopify\/Product\/15286962618534","vendor":"Boston Proper","type":"Promotions","handle":"boston-proper-printed-scarf-with-love-bp","variants":[{"id":56389031657638,"price":5000,"name":"Boston Proper Printed Scarf With Love BP - With Love BP \/ One Size","public_title":"With Love BP \/ One Size","sku":"2CT8071000"}],"remote":false},"page":{"pageType":"product","resourceType":"product","resourceId":15286962618534,"requestId":"366c6d67-7b42-4351-97e1-f226d34f308c-1791063068"}};
12042  for (var attr in meta) {
12043    window.ShopifyAnalytics.meta[attr] = meta[attr];
12044  }
12045</script>
vendor: 1 bytes, line 12045
12045
12046<script class="analytics">
12047  (function () {
12048    var customDocumentWrite = function(content) {
12049      var jquery = null;
12050
12051      if (window.jQuery) {
12052        jquery = window.jQuery;
12053      } else if (window.Checkout && window.Checkout.$) {
12054        jquery = window.Checkout.$;
12055      }
12056
12057      if (jquery) {
12058        jquery('body').append(content);
12059      }
12060    };
12061
12062    var hasLoggedConversion = function(token) {
12063      if (token) {
12064        return document.cookie.indexOf('loggedConversion=' + token) !== -1;
12065      }
12066      return false;
12067    }
12068
12069    var setCookieIfConversion = function(token) {
12070      if (token) {
12071        var twoMonthsFromNow = new Date(Date.now());
12072        twoMonthsFromNow.setMonth(twoMonthsFromNow.getMonth() + 2);
12073
12074        document.cookie = 'loggedConversion=' + token + '; expires=' + twoMonthsFromNow;
12075      }
12076    }
12077
12078    var trekkie = window.ShopifyAnalytics.lib = window.trekkie = window.trekkie || [];
12079    window.ShopifyAnalytics.lib.trekkie = window.trekkie;
12080    if (trekkie.integrations) {
12081      return;
12082    }
12083    trekkie.methods = [
12084      'identify',
12085      'page',
12086      'ready',
12087      'track',
12088      'trackForm',
12089      'trackLink'
12090    ];
12091    trekkie.factory = function(method) {
12092      return function() {
12093        var args = Array.prototype.slice.call(arguments);
12094        args.unshift(method);
12095        trekkie.push(args);
12096        if (method == 'track' || method == 'page') {
12097          var pageUrl;
12098          try {
12099            pageUrl = window.location.href;
12100          } catch (e) {}
12101          var pageReferrer;
12102          try {
12103            pageReferrer = document.referrer;
12104          } catch (e) {}
12105          try {
12106            if (window.__TREKKIE_SHIM_QUEUE == null) {
12107              window.__TREKKIE_SHIM_QUEUE = [];
12108            }
12109            window.__TREKKIE_SHIM_QUEUE.push({
12110              from: 'trekkie-stub',
12111              method: method,
12112              args: args.slice(1),
12113              pageContext: {
12114                url: pageUrl,
12115                referrer: pageReferrer
12116              }
12117            });
12118          } catch (e) {
12119            // no-op
12120          }
12121        }
12122        return trekkie;
12123      };
12124    };
12125    for (var i = 0; i < trekkie.methods.length; i++) {
12126      var key = trekkie.methods[i];
12127      trekkie[key] = trekkie.factory(key);
12128    }
12129    trekkie.load = function(config) {
12130      trekkie.config = config || {};
12131      trekkie.config.initialDocumentCookie = document.cookie;
12132      var first = document.getElementsByTagName('script')[0];
12133var script = document.createElement('script');
12134script.type = 'text/javascript';
12135script.onerror = function(e) {
12136  var scriptFallback = document.createElement('script');
12137  scriptFallback.type = 'text/javascript';
12138  scriptFallback.onerror = function(error) {
12139          var Monorail = {
12140      produce: function produce(monorailDomain, schemaId, payload) {
12141        var currentMs = new Date().getTime();
12142        var event = {
12143          schema_id: schemaId,
12144          payload: payload,
12145          metadata: {
12146            event_created_at_ms: currentMs,
12147            event_sent_at_ms: currentMs
12148          }
12149        };
12150        return Monorail.sendRequest("https://" + monorailDomain + "/v1/produce", JSON.stringify(event));
12151      },
12152      sendRequest: function sendRequest(endpointUrl, payload) {
12153        // Try the sendBeacon API
12154        if (window && window.navigator && typeof window.navigator.sendBeacon === 'function' && typeof window.Blob === 'function' && !Monorail.isIos12()) {
12155          var blobData = new window.Blob([payload], {
12156            type: 'text/plain'
12157          });
12158
12159          if (window.navigator.sendBeacon(endpointUrl, blobData)) {
12160            return true;
12161          } // sendBeacon was not successful
12162
12163        } // XHR beacon
12164
12165        var xhr = new XMLHttpRequest();
12166
12167        try {
12168          xhr.open('POST', endpointUrl);
12169          xhr.setRequestHeader('Content-Type', 'text/plain');
12170          xhr.send(payload);
12171        } catch (e) {
12172          console.log(e);
12173        }
12174
12175        return false;
12176      },
12177      isIos12: function isIos12() {
12178        return window.navigator.userAgent.lastIndexOf('iPhone; CPU iPhone OS 12_') !== -1 || window.navigator.userAgent.lastIndexOf('iPad; CPU OS 12_') !== -1;
12179      }
12180    };
12181    Monorail.produce('monorail-edge.shopifysvc.com',
12182      'trekkie_storefront_load_errors/1.1',
12183      {shop_id: 52960723110,
12184      theme_id: 198106775718,
12185      app_name: "storefront",
12186      context_url: window.location.href,
12187      source_url: "//www.bostonproper.com/cdn/s/trekkie.storefront.2f6d7d7ede7d24234881a9cd5f47e679642fa1f6.min.js"});
12188
12189  };
12190  scriptFallback.async = true;
12191  scriptFallback.src = '//www.bostonproper.com/cdn/s/trekkie.storefront.2f6d7d7ede7d24234881a9cd5f47e679642fa1f6.min.js';
12192  first.parentNode.insertBefore(scriptFallback, first);
12193};
12194script.async = true;
12195script.src = '//www.bostonproper.com/cdn/s/trekkie.storefront.2f6d7d7ede7d24234881a9cd5f47e679642fa1f6.min.js';
12196first.parentNode.insertBefore(script, first);
12197
12198    };
12199    trekkie.load(
12200      {"Trekkie":{"appName":"storefront","development":false,"defaultAttributes":{"shopId":52960723110,"isMerchantRequest":null,"themeId":198106775718,"themeCityHash":"14348548284193324120","contentLanguage":"en","currency":"USD","eventMetadataId":"bd74b2c2-c5f8-444d-a394-
12200a9f515df4e89"},"isServerSideCookieWritingEnabled":true,"monorailRegion":"shop_domain","enabledBetaFlags":["764d78cb","8450a54b","7ee89bf1","4c64608a"]},"Session Attribution":{},"S2S":{"facebookCapiEnabled":false,"source":"trekkie-storefront-renderer","apiClientId":580111}}
12201    );
12202
12203    var loaded = false;
12204    trekkie.ready(function() {
12205      if (loaded) return;
12206      loaded = true;
12207
12208      window.ShopifyAnalytics.lib = window.trekkie;
12209
12210      var originalDocumentWrite = document.write;
12211      document.write = customDocumentWrite;
12212      try { window.ShopifyAnalytics.merchantGoogleAnalytics.call(this); } catch(error) {};
12213      document.write = originalDocumentWrite;
12214
12215      var match = window.location.pathname.match(/checkouts\/(.+)\/(thank_you|post_purchase)/)
12216      var token = match? match[1]: undefined;
12217      if (!hasLoggedConversion(token)) {
12218        setCookieIfConversion(token);
12219        window.ShopifyAnalytics.lib.track("Viewed Product",{"currency":"USD","variantId":56389031657638,"productId":15286962618534,"productGid":"gid:\/\/shopify\/Product\/15286962618534","name":"Boston Proper Printed Scarf With Love BP - With Love BP \/ One Size","price":"50.00","sku":"2CT8071000","brand":"Boston Proper","variant":"With Love BP \/ One Size","category":"Promotions","nonInteraction":true,"remote":false,"available":true},undefined,undefined,{"shopifyEmitted":true});
12220      }
12221    });
12222
12223    window.ShopifyAnalytics.lib.page(null,{"pageType":"product","resourceType":"product","resourceId":15286962618534,"requestId":"366c6d67-7b42-4351-97e1-f226d34f308c-1791063068","shopifyEmitted":true});
12224
12225    var eventsListenerScript = document.createElement('script');
12226    eventsListenerScript.async = true;
12227    eventsListenerScript.src = "//www.bostonproper.com/cdn/shopifycloud/storefront/assets/shop_events_listener-4e26a9ce.js";
12228    document.getElementsByTagName('head')[0].appendChild(eventsListenerScript);
12229})();</script>
vendor: 1 bytes, line 12229
12229
12230<script
12231  defer
12232  src="https://www.bostonproper.com/cdn/shopifycloud/perf-kit/shopify-perf-kit-3.9.4.min.js"
12233  data-application="storefront-renderer"
12234  data-shop-id="52960723110"
12235  data-render-region="gcp-us-central1"
12236  data-page-type="product"
12237  data-theme-instance-id="198106775718"
12238  data-theme-name="Horizon"
12239  data-theme-version="3.5.0"
12240  data-monorail-region="shop_domain"
12241  data-resource-timing-sampling-rate="10"
12242  data-shs="true"
12243  data-shs-beacon="true"
12244  data-shs-export-with-fetch="true"
12245  data-shs-logs-sample-rate="1"
12246  data-shs-beacon-endpoint="https://www.bostonproper.com/api/collect"
12247></script>
vendor: 1 bytes, line 12247
12247
12248<script src="https://cdn.shopify.com/storefront/web-components/account.js" type="module" crossorigin fetchpriority="low" async></script>
12248<script id="shopify-customer-account-data" type="application/json">{"customer":null,"shop":{"id":"52960723110","customerAccountTranslations":[{"key":"account_menu.signed_out_state.sheet_title","value":"Sign in or create account"},{"key":"account_menu.signed_out_state.section_divider","value":"More ways to sign in"},{"key":"account_menu.signed_out_state.alternate_divider","value":"OR"},{"key":"account_menu.signed_out_state.email_field_label","value":"Email"},{"key":"account_menu.signed_out_state.orders_button","value":"Orders"},{"key":"account_menu.signed_out_state.profile_button","value":"Profile"},{"key":"account_menu.signed_out_state.shop_login_button","value":"Sign in with Shop"},{"key":"account_menu.signed_out_state.continue_with_google","value":"Continue with Google"},{"key":"account_menu.signed_out_state.continue_with_facebook","value":"Continue with Facebook"},{"key":"account_menu.signed_out_state.marketing_consent_label","value":"Email me with news and offers"},{"key":"account_menu.signed_in_state.greeting_with_name","value":"Hi, {{first_name}}"},{"key":"account_menu.signed_in_state.greeting_without_name","value":"Account"},{"key":"account_menu.signed_in_state.orders_button","value":"Orders"},{"key":"account_menu.signed_in_state.profile_button","value":"Profile"},{"key":"account_menu.location_picker.sheet_title","value":"Locations"},{"key":"account_menu.location_picker.search_field_placeholder","value":"Search"},{"key":"account_menu.aria_labels.close_menu","value":"Close menu"},{"key":"account_menu.aria_labels.back_to_main_menu","value":"Back to main menu from {{title}}"},{"key":"account_menu.aria_labels.open_submenu","value":"{{title}}, opens submenu"},{"key":"account_menu.aria_labels.loading_menu","value":"Loading menu"},{"key":"account_menu.aria_labels.account","value":"Account"},{"key":"account_menu.aria_labels.sign_in_with_email","value":"Sign in with email"},{"key":"account_menu.aria_labels.sign_in","value":"Sign in"}],"socialLoginProviders":[{"handle":"Shop"}],"legacyCustomerAccounts":false,"signInLinksVisible":true,"b2bEnabled":false,"marketingConsentSigninEnabled":true,"marketingConsentPreselected":true},"visitor":{"country":"US","language":"en"}}</script>
12248
12249<meta name="shopify-y" content="cfc59d5f-4991-493d-bf87-6366517f822f" data-expiration="1822620668000"><meta name="shopify-s" content="8599fad1-de9a-436d-a4a0-4f83079cfaff" data-expiration="1791064868000"><meta name="new-cookie-storage-activated" content="t">
12250</head>
12251
12252  <body class="page-width-narrow card-hover-effect-none"><noscript>
12253      <iframe
12254        src="https://sst.bostonproper.com/ns.html?id=GTM-NS3X79G&gtm_auth=288FkNoOr_QXQEJ-WPHnww&gtm_preview=env-1&gtm_cookies_win=x"
12255        height="0"
12256        width="0"
12257        style="display:none;visibility:hidden"
12258      ></iframe>
12259    </noscript><a
12260  class="skip-to-content-link button-secondary"
12261  href="#MainContent"
12262>
12263  Skip to content
12264</a>
12265
12266
12267
12268    <div id="header-group">
12269      <!-- BEGIN sections: header-group -->
12270<div id="shopify-section-sections--29563569635494__header_announcements_9jGBFp" class="shopify-section shopify-section-group-header-group">
12271
12272
12273  
12273<script
12274    src="//www.bostonproper.com/cdn/shop/t/1521/assets/announcement-bar.js?v=171930887109884936311790713714"
12275    type="module"
12276    fetchpriority="low"
12277  ></script>
12277
12278
12279
12280<div class="section-background color-scheme-3"></div>
12281<aside
12282  class="announcement-bar spacing-style section section--page-width color-scheme-3"
12283  style="--padding-block-start: 15px; --padding-block-end:15px; 
12284--padding-inline-start:0px; --padding-inline-end:0px; 
12285; --border-bottom-width: 0px;"
12286>
12287  
12288
12289  <announcement-bar-component
12290    class="announcement-bar__slider"
12291    
12292      autoplay="5" aria-live="polite"
12293    
12294  >
12295    
12296      <slideshow-arrows
12297  position="center"
12298  
12299><button
12300  class="
12301    slideshow-control slideshow-control--previous
12302    
12303    
12304    slideshow-control--style-chevron
12305    button button-unstyled button-unstyled--transparent
12306     flip-x
12307  "
12308  
12309  aria-label="Previous slide"
12310  
12311  on:click="/previous"
12312  ref="previous"
12313>
12314  <span class="svg-wrapper icon-caret"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12315  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12316</svg>
12317</span>
12318</button>
12319
12320
12321<button
12322  class="
12323    slideshow-control slideshow-control--next
12324    
12325    
12326    slideshow-control--style-chevron
12327    button button-unstyled button-unstyled--transparent
12328    
12329  "
12330  
12331  aria-label="Next slide"
12332  
12333  on:click="/next"
12334  ref="next"
12335>
12336  <span class="svg-wrapper icon-caret"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12337  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12338</svg>
12339</span>
12340</button>
12341
12342
12343</slideshow-arrows>
12344
12345
12346
12347    
12348
12349    <div class="announcement-bar__slides">
12350      
12351<slideshow-slide
12352    ref="slides[]"
12353    class="
12354      announcement-bar__slide
12355      text-block
12356      text-block--AY1VLbVN4UEc4c01tT__announcement_ahaFK3
12357      text-block--align-center
12358      text-block--full-width
12359      custom-typography
12360      custom-font-size
12361      
12362    "
12363    style="
12364      
12365--color: ;--font-size: 0.75rem;      --font-weight: var(--font-subheading--weight);--font-family: var(--font-subheading--family);    --text-transform: none;    --text-wrap: pretty;          --line-height: var(--line-height--body-);        --letter-spacing: var(--letter-spacing--body-normal);
12366      --width: 100%;
12367      --text-align: center;
12368      --line-height: 1;
12369    "
12370    
12371    aria-hidden="false"
12372  >
12373    <p class="announcement-bar__text">
12374      20% Off $175+ Plus Free Shipping | Code: STYLE20
12375    </p>
12376
12377    
12378      <a
12379        class="announcement-bar__link"
12380        href="/collections/new-arrivals"
12381      >
12382        <span class="visually-hidden">
12383          20% Off $175+ Plus Free Shipping | Code: STYLE20
12384        </span>
12385      </a>
12386    
12387  </slideshow-slide>
12388
12389
12390
12391<slideshow-slide
12392    ref="slides[]"
12393    class="
12394      announcement-bar__slide
12395      text-block
12396      text-block--ANk9YK3Z6SHBQcFBJe__announcement_XRMPWL
12397      text-block--align-center
12398      text-block--full-width
12399      custom-typography
12400      custom-font-size
12401      
12402    "
12403    style="
12404      
12405--color: ;--font-size: 0.75rem;      --font-weight: var(--font-subheading--weight);--font-family: var(--font-subheading--family);    --text-transform: none;    --text-wrap: pretty;          --line-height: var(--line-height--body-);        --letter-spacing: var(--letter-spacing--body-normal);
12406      --width: 100%;
12407      --text-align: center;
12408      --line-height: 1;
12409    "
12410    
12411    aria-hidden="true"inert
12412  >
12413    <p class="announcement-bar__text">
12414      Shop $400+ to receive an exclusive scarf | Shop
12415    </p>
12416
12417    
12418      <a
12419        class="announcement-bar__link"
12420        href="/collections/new-arrivals"
12421      >
12422        <span class="visually-hidden">
12423          Shop $400+ to receive an exclusive scarf | Shop
12424        </span>
12425      </a>
12426    
12427  </slideshow-slide>
12428
12429
12430
12431    </div>
12432      <button
12433        type="button"
12434        class="bp-announcement-playpause"
12435        data-bp-ann-playpause
12436        aria-label="Pause announcements"
12437        aria-pressed="false"
12438      >
12439        <svg class="bp-announcement-playpause__pause" width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
12440          <rect x="2" y="1.5" width="2.6" height="9" rx="0.4" fill="currentColor"/>
12441          <rect x="7.4" y="1.5" width="2.6" height="9" rx="0.4" fill="currentColor"/>
12442        </svg>
12443        <svg class="bp-announcement-playpause__play" width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true" hidden>
12444          <path d="M2.5 1.5l8 4.5-8 4.5z" fill="currentColor"/>
12445        </svg>
12446      </button>
12447    
12448  </announcement-bar-component>
12449</aside>
12449<script>
12450  (function () {
12451    if (window.__bpAnnPlayPauseWired) return;
12452    window.__bpAnnPlayPauseWired = true;
12453
12454    // Which GLYPH shows is driven purely by CSS off the bar's `[paused]`
12455    // attribute (see bp-fonts.liquid) — that survives Horizon's re-render of the
12456    // bar, which was resetting the JS-toggled `hidden` and leaving the wrong (or
12457    // both) icons showing. Here we only (a) toggle play/pause on click and
12458    // (b) keep aria-pressed/label in sync with the actual state (incl. any
12459    // auto-pause Horizon does), which CSS can't express.
12460    function syncAria(bar, btn) {
12461      var paused = bar.hasAttribute('paused');
12462      btn.setAttribute('aria-pressed', paused ? 'true' : 'false');
12463      btn.setAttribute('aria-label', paused ? 'Play announcements' : 'Pause announcements');
12464    }
12465
12466    document.addEventListener('click', function (e) {
12467      var btn = e.target.closest && e.target.closest('[data-bp-ann-playpause]');
12468      if (!btn) return;
12469      var bar = btn.closest('announcement-bar-component');
12470      if (!bar) return;
12471      if (bar.hasAttribute('paused')) {
12472        if (typeof bar.play === 'function') bar.play();
12473        else bar.removeAttribute('paused');
12474      } else {
12475        if (typeof bar.pause === 'function') bar.pause();
12476        else bar.setAttribute('paused', '');
12477      }
12478      syncAria(bar, btn);
12479    });
12480
12481    document.querySelectorAll('announcement-bar-component').forEach(function (bar) {
12482      var btn = bar.querySelector('[data-bp-ann-playpause]');
12483      if (!btn) return;
12484      syncAria(bar, btn); // initial state on load
12485      try {
12486        new MutationObserver(function () { syncAria(bar, btn); })
12487          .observe(bar, { attributes: true, attributeFilter: ['paused'] });
12488      } catch (e) {}
12489    });
12490  })();
12491</script>
12491
12492
12493
12494
12495
12496</div><header id="shopify-section-sections--29563569635494__header_section" class="shopify-section shopify-section-group-header-group header-section">
12497
12498
12499
12500
12501
12502
12503
12504
12505<header-component
12506  id="header-component"
12507  class="header"
12508  data-theme-color="rgb(254 255 250)"
12509  
12510  
12511    sticky="always"
12512  
12513  data-skip-node-update
12514  data-scroll-direction="none"
12515  
12516  
12517  style="
12518    --color-scheme-top-row: rgba(254 255 250 / 1.0);
12519    --color-scheme-bottom-row: rgba(254 255 250 / 1.0);
12520    
12521  "
12522>
12523  <div class="header__underlay header__underlay-closed"></div>
12524  <div
12525    class="header__underlay header__underlay-open"
12526  ></div>
12527    
12528
12529    
12530
12531    
12532    
12533      <div
12534        class="header__row header__row--top color-scheme-1 section section--full-width-margin section--page-width"
12535        ref="headerRowTop"style="--border-bottom-width: 0px; --border-bottom-width-mobile: 0px;">
12536        <div class="header__columns spacing-style">
12537          <div
12538      class="header__column header__column--left"
12539      data-testid="header-top-left"
12540    >
12541      
12542        
12543          
12544              
12545
12546
12547<div
12548      class="header__drawer"
12549      ref="headerDrawerContainer"
12550      data-hydration-key="header-drawer-mobile"
12551      
12552    ><bp-mobile-drawer class="bp-mobile-drawer" data-hydration-key="bp-mobile-drawer" data-skip-subtree-update>
12553        <details class="bp-mobile-drawer__details" ref="details" scroll-lock>
12554          <summary class="bp-mobile-drawer__trigger" aria-label="Menu">
12555            <span class="bp-mobile-drawer__trigger-icon" aria-hidden="true"><svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
12556<path d="M31.9999 14.75C32.2499 14.7559 32.4999 14.7617 32.7499 14.7676C32.7499 14.2559 32.7499 13.7441 32.7499 13.2324C32.4999 13.2383 32.2499 13.2441 31.9999 13.25C31.6666 13.2578 31.3333 13.2656 30.9999 13.2734C25 13.4141 19 13.5547 13 13.6953C12.6667 13.7031 12.3333 13.7109 12 13.7188C11.9084 13.7209 11.8168 13.723 11.7253 13.7252C11.7253 13.9084 11.7253 14.0916 11.7253 14.2748C11.8168 14.277 11.9084 14.2791 12 14.2812C12.3333 14.2891 12.6667 14.2969 13 14.3047C19 14.4453 25 14.5859 30.9999 14.7266C31.3333 14.7344 31.6666 14.7422 31.9999 14.75Z" fill="currentColor"/>
12557<path d="M12.0001 14.75C11.7501 14.7559 11.5001 14.7617 11.2501 14.7676C11.2501 14.2559 11.2501 13.7441 11.2501 13.2324C11.5001 13.2383 11.7501 13.2441 12.0001 13.25C12.3334 13.2578 12.6667 13.2656 13.0001 13.2734C19 13.4141 25 13.5547 31 13.6953C31.3333 13.7031 31.6667 13.7109 32 13.7188C32.0916 13.7209 32.1832 13.723 32.2747 13.7252C32.2747 13.9084 32.2747 14.0916 32.2747 14.2748C32.1832 14.277 32.0916 14.2791 32 14.2812C31.6667 14.2891 31.3333 14.2969 31 14.3047C25 14.4453 19 14.5859 13.0001 14.7266C12.6667 14.7344 12.3334 14.7422 12.0001 14.75Z" fill="currentColor"/>
12558<path d="M31.9999 22.75C32.2499 22.7559 32.4999 22.7617 32.7499 22.7676C32.7499 22.2559 32.7499 21.7441 32.7499 21.2324C32.4999 21.2383 32.2499 21.2441 31.9999 21.25C31.6666 21.2578 31.3333 21.2656 30.9999 21.2734C25 21.4141 19 21.5547 13 21.6953C12.6667 21.7031 12.3333 21.7109 12 21.7188C11.9084 21.7209 11.8168 21.723 11.7253 21.7252C11.7253 21.9084 11.7253 22.0916 11.7253 22.2748C11.8168 22.277 11.9084 22.2791 12 22.2812C12.3333 22.2891 12.6667 22.2969 13 22.3047C19 22.4453 25 22.5859 30.9999 22.7266C31.3333 22.7344 31.6666 22.7422 31.9999 22.75Z" fill="currentColor"/>
12559<path d="M12.0001 22.75C11.7501 22.7559 11.5001 22.7617 11.2501 22.7676C11.2501 22.2559 11.2501 21.7441 11.2501 21.2324C11.5001 21.2383 11.7501 21.2441 12.0001 21.25C12.3334 21.2578 12.6667 21.2656 13.0001 21.2734C19 21.4141 25 21.5547 31 21.6953C31.3333 21.7031 31.6667 21.7109 32 21.7188C32.0916 21.7209 32.1832 21.723 32.2747 21.7252C32.2747 21.9084 32.2747 22.0916 32.2747 22.2748C32.1832 22.277 32.0916 22.2791 32 22.2812C31.6667 22.2891 31.3333 22.2969 31 22.3047C25 22.4453 19 22.5859 13.0001 22.7266C12.6667 22.7344 12.3334 22.7422 12.0001 22.75Z" fill="currentColor"/>
12560<path d="M31.9999 30.75C32.2499 30.7559 32.4999 30.7617 32.7499 30.7676C32.7499 30.2559 32.7499 29.7441 32.7499 29.2324C32.4999 29.2383 32.2499 29.2441 31.9999 29.25C31.6666 29.2578 31.3333 29.2656 30.9999 29.2734C25 29.4141 19 29.5547 13 29.6953C12.6667 29.7031 12.3333 29.7109 12 29.7188C11.9084 29.7209 11.8168 29.723 11.7253 29.7252C11.7253 29.9084 11.7253 30.0916 11.7253 30.2748C11.8168 30.277 11.9
12560084 30.2791 12 30.2812C12.3333 30.2891 12.6667 30.2969 13 30.3047C19 30.4453 25 30.5859 30.9999 30.7266C31.3333 30.7344 31.6666 30.7422 31.9999 30.75Z" fill="currentColor"/>
12561<path d="M12.0001 30.75C11.7501 30.7559 11.5001 30.7617 11.2501 30.7676C11.2501 30.2559 11.2501 29.7441 11.2501 29.2324C11.5001 29.2383 11.7501 29.2441 12.0001 29.25C12.3334 29.2578 12.6667 29.2656 13.0001 29.2734C19 29.4141 25 29.5547 31 29.6953C31.3333 29.7031 31.6667 29.7109 32 29.7188C32.0916 29.7209 32.1832 29.723 32.2747 29.7252C32.2747 29.9084 32.2747 30.0916 32.2747 30.2748C32.1832 30.277 32.0916 30.2791 32 30.2812C31.6667 30.2891 31.3333 30.2969 31 30.3047C25 30.4453 19 30.5859 13.0001 30.7266C12.6667 30.7344 12.3334 30.7422 12.0001 30.75Z" fill="currentColor"/>
12562</svg>
12563</span>
12564            <span class="bp-mobile-drawer__trigger-icon bp-mobile-drawer__trigger-icon--close" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12565  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12566  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12567</svg>
12568</span>
12569          </summary>
12570
12571          <div class="bp-mobile-drawer__panel" data-active-view="root">
12572            <section class="bp-mobile-drawer__view bp-mobile-drawer__view--active" data-view="root">
12573              <header class="bp-mobile-drawer__header">
12574                <h2 class="bp-mobile-drawer__title">Menu</h2>
12575                <button type="button" class="bp-mobile-drawer__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12576  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12577  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12578</svg>
12579</button>
12580              </header>
12581
12582              <ul class="bp-mobile-drawer__list">
12583                <li
12584  role="presentation"
12585  class="menu-list__list-item bp-menu-item-li"
12586  data-bp-menu-item
12587  
12588><a
12589      href="/collections/new-arrivals"
12590      data-skip-node-update="true"
12591      class="menu-list__link"
12592      aria-controls="bp-submenu-AR2Y1MTEyN25uOTEyM__bp_menu_new_arrivals-1"
12593      aria-haspopup="true"
12594      aria-expanded="false"
12595      ref="menuitem"
12596    >
12597      <span class="menu-list__link-title">New Arrivals</span>
12598    </a>
12599    <div class="bp-mega-submenu" id="bp-submenu-AR2Y1MTEyN25uOTEyM__bp_menu_new_arrivals-1">
12600      <div class="bp-mega-submenu__inner">
12601        <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column">
12602                  <p class="bp-mega__heading"><a href="/collections/new-arrivals">New Arrivals</a></p><ul class="bp-mega__links"><li><a href="/collections/new-arrivals">Shop All</a></li><li><a href="/pages/digital-catalog">Digital Catalog</a></li><li><a href="/collections/new-arrivals-athleisure">Athleisure</a></li><li><a href="/collections/new-arrivals-coats">Coats</a></li><li><a href="/collections/new-arrivals-dresses">Dresses</a></li><li><a href="/collections/new-arrivals-jackets-blazers">Jackets & Blazers</a></li><li><a href="/collections/new-arrivals-jeans">Jeans</a></li><li><a href="/collections/new-arrivals-loungewear">Loungewear</a></li><li><a href="/collections/new-arrivals-pants-leggings">Pants & Leggings</a></li><li><a href="/collections/new-arrivals-shoes-accessories">Shoes & Accessories</a></li><li><a href="/collections/new-arrivals-skirts-shorts">Skirts & Shorts</a></li><li><a href="/collections/new-arrivals-sweaters">Sweaters</a></li><li><a href="/collections/new-arrivals-swimsuits-swimwear">Swimwear</a></li><li><a href="/collections/new-arrivals-tops-blouses-tees">Tops</a></li></ul></div><div class="bp-mega__column">
12603                  <p class="bp-mega__heading"><a href="/collections/new-arrivals">Featured Shops</a></p><ul class="bp-mega__links"><li><a href="/collections/featured-shop-animal-prints">Animal Prints</a></li><li><a href="/collections/editors-picks">Editor's Picks</a></li><li><a href="/collections/featured-shops-fall-colors">Fall Colors</a></li><li><a href="/collections/featured-shop-intricate-details">Intricate Details</a></li><li><a href="/collections/featured-shops-matching-sets">Matching Sets</a></li><li><a href="/collections/breast-cancer-awareness">Power in Pink</a></li><li><a href="/collections/featured-shops-layering">The Layering Shop</a></li><li><a href="https://www.bostonproper.com/collections/featured-shops-suede-leather">Suede & Leather</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li><li><a href="/pages/the-sweater-edit">Style Guide: The Sweater Edit</a></li><li><a href="/pages/new-to-boston-proper">New to Boston Proper? </a></li></ul></div><div class="bp-mega__column">
12604                  <p class="bp-mega__heading"><a href="/pages/the-beyond-travel-collection">Beyond Travel Collection</a></p><ul class="bp-mega__links"><li><a href="/collections/travel">Shop All </a></li><li><a href="/pages/the-beyond-travel-collection">The Travel Collection</a></li><li><a href="/collections/travel-bottoms">Beyond Travel Bottoms</a></li><li><a href="/collections/travel-dresses">Beyond Travel Dresses</a></li><li><a href="/collections/travel-jackets">Beyond Travel Jackets</a></li><li><a href="/collections/travel-tops">Beyond Travel Tops</a></li><li><a href="/collections/travel-sets">Beyond Travel Sets</a></li></ul></div><div class="bp-mega__column">
12605                  <p class="bp-mega__heading"><a href="/collections/all-brands-we-love">Brands We Love</a></p><ul class="bp-mega__links"><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-becca">Becca By Rebecca Virtue</a></li><li><a href="/collections/brands-we-love-carmen-marc-valvo">Carmen Marc Valvo</a></li><li><a href="/collections/brands-we-love-change-of-scenery">
12605Change of Scenery</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini X Boston Proper</a></li><li><a href="/collections/brands-we-love-saint-jo">Saint Jō</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li><li><a href="/collections/brands-we-love-walter-baker">Walter Baker</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></div></div><div class="bp-mega__promos"><div class="bp-mega__promo">
12606  <a href="/collections/new-arrivals" class="bp-mega__promo-link">
12607    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_73.jpg?v=1790714514&amp;width=400" alt="New Season. New Statements." srcset="//www.bostonproper.com/cdn/shop/files/Image_73.jpg?v=1790714514&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_73.jpg?v=1790714514&amp;width=400 400w" width="400" height="500" loading="lazy">
12608</div>
12609    <h4 class="bp-mega__promo-title">New Season. New Statements.</h4><div class="bp-mega__promo-copy"><p>Enjoy 20% Off $175+ Plus Free Shipping. Limited Time. Use code: STYLE20</p></div><span class="bp-mega__promo-cta">Shop Now</span>
12610  </a>
12611</div>
12612
12613<div class="bp-mega__promo">
12614  <a href="/pages/the-dress-code" class="bp-mega__promo-link">
12615    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_New_Arrivals_Image-6.jpg?v=1790707073&amp;width=400" alt="The Dress Code" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_New_Arrivals_Image-6.jpg?v=1790707073&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_New_Arrivals_Image-6.jpg?v=1790707073&amp;width=400 400w" width="400" height="500" loading="lazy">
12616</div>
12617    <h4 class="bp-mega__promo-title">The Dress Code</h4><div class="bp-mega__promo-copy"><p>The one-piece solution. Simple to style, flattering to wear, and ready for every plan.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
12618  </a>
12619</div>
12620
12621</div></div>
12622      </div>
12623    </div></li><li class="bp-mm-item" data-bp-mm-id="AR2Y1MTEyN25uOTEyM__bp_menu_new_arrivals-1"><button type="button" class="bp-mm-item__row" data-open-view="AR2Y1MTEyN25uOTEyM__bp_menu_new_arrivals-1">
12624      <span class="bp-mm-item__label">New Arrivals</span>
12625      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12626  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12627</svg>
12628</span>
12629    </button>
12630
12631    <section class="bp-mm-view" data-view="AR2Y1MTEyN25uOTEyM__bp_menu_new_arrivals-1" hidden>
12632      <header class="bp-mm-view__header">
12633        <button type="button" class="bp-mm-view__back" data-back>
12634          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12635  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12636</svg>
12637</span>
12638          <span>New Arrivals</span>
12639        </button>
12640        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12641  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12642  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12643</svg>
12644</button>
12645      </header><div class="bp-mm-view__sections"><section class="bp-mm-section">
12646              <p class="bp-mm-section__heading"><a href="/collections/new-arrivals">New Arrivals</a></p><ul class="bp-mm-section__links"><li><a href="/collections/new-arrivals">Shop All</a></li><li><a href="/pages/digital-catalog">Digital Catalog</a></li><li><a href="/collections/new-arrivals-athleisure">Athleisure</a></li><li><a href="/collections/new-arrivals-coats">Coats</a></li><li><a href="/collections/new-arrivals-dresses">Dresses</a></li><li><a href="/collections/new-arrivals-jackets-blazers">Jackets & Blazers</a></li><li><a href="/collections/new-arrivals-jeans">Jeans</a></li><li><a href="/collections/new-arrivals-loungewear">Loungewear</a></li><li><a href="/collections/new-arrivals-pants-leggings">Pants & Leggings</a></li><li><a href="/collections/new-arrivals-shoes-accessories">Shoes & Accessories</a></li><li><a href="/collections/new-arrivals-skirts-shorts">Skirts & Shorts</a></li><li><a href="/collections/new-arrivals-sweaters">Sweaters</a></li><li><a href="/collections/new-arrivals-swimsuits-swimwear">Swimwear</a></li><li><a href="/collections/new-arrivals-tops-blouses-tees">Tops</a></li></ul></section><section class="bp-mm-section">
12647              <p class="bp-mm-section__heading"><a href="/collections/new-arrivals">Featured Shops</a></p><ul class="bp-mm-section__links"><li><a href="/collections/featured-shop-animal-prints">Animal Prints</a></li><li><a href="/collections/editors-picks">Editor's Picks</a></li><li><a href="/collections/featured-shops-fall-colors">Fall Colors</a></li><li><a href="/collections/featured-shop-intricate-details">Intricate Details</a></li><li><a href="/collections/featured-shops-matching-sets">Matching Sets</a></li><li><a href="/collections/breast-cancer-awareness">Power in Pink</a></li><li><a href="/collections/featured-shops-layering">The Layering Shop</a></li><li><a href="https://www.bostonproper.com/collections/featured-shops-suede-leather">Suede & Leather</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li><li><a href="/pages/the-sweater-edit">Style Guide: The Sweater Edit</a></li><li><a href="/pages/new-to-boston-proper">New to Boston Proper? </a></li></ul></section><section class="bp-mm-section">
12648              <p class="bp-mm-section__heading"><a href="/pages/the-beyond-travel-collection">Beyond Travel Collection</a></p><ul class="bp-mm-section__links"><li><a href="/collections/travel">Shop All </a></li><li><a href="/pages/the-beyond-travel-collection">The Travel Collection</a></li><li><a href="/collections/travel-bottoms">Beyond Travel Bottoms</a></li><li><a href="/collections/travel-dresses">Beyond Travel Dresses</a></li><li><a href="/collections/travel-jackets">Beyond Travel Jackets</a></li><li><a href="/collections/travel-tops">Beyond Travel Tops</a></li><li><a href="/collections/travel-sets">Beyond Travel Sets</a></li></ul></section><section class="bp-mm-section">
12649              <p class="bp-mm-section__heading"><a href="/collections/all-brands-we-love">Brands We Love</a></p><ul class="bp-mm-section__links"><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-becca">Becca By Rebecca Virtue</a></li><li><a href="/collections/brands-we-love-carmen-marc-valvo">Carmen Marc Valvo</a></li><li><a href="/collections/brands-we-love-change-of-scenery">
12649Change of Scenery</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini X Boston Proper</a></li><li><a href="/collections/brands-we-love-saint-jo">Saint Jō</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li><li><a href="/collections/brands-we-love-walter-baker">Walter Baker</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo">
12650  <a href="/collections/new-arrivals" class="bp-mega__promo-link">
12651    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_73.jpg?v=1790714514&amp;width=400" alt="New Season. New Statements." srcset="//www.bostonproper.com/cdn/shop/files/Image_73.jpg?v=1790714514&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_73.jpg?v=1790714514&amp;width=400 400w" width="400" height="500" loading="lazy">
12652</div>
12653    <h4 class="bp-mega__promo-title">New Season. New Statements.</h4><div class="bp-mega__promo-copy"><p>Enjoy 20% Off $175+ Plus Free Shipping. Limited Time. Use code: STYLE20</p></div><span class="bp-mega__promo-cta">Shop Now</span>
12654  </a>
12655</div>
12656
12657<div class="bp-mega__promo">
12658  <a href="/pages/the-dress-code" class="bp-mega__promo-link">
12659    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_New_Arrivals_Image-6.jpg?v=1790707073&amp;width=400" alt="The Dress Code" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_New_Arrivals_Image-6.jpg?v=1790707073&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_New_Arrivals_Image-6.jpg?v=1790707073&amp;width=400 400w" width="400" height="500" loading="lazy">
12660</div>
12661    <h4 class="bp-mega__promo-title">The Dress Code</h4><div class="bp-mega__promo-copy"><p>The one-piece solution. Simple to style, flattering to wear, and ready for every plan.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
12662  </a>
12663</div>
12664
12665</div></section></li>
12666
12667
12668
12669<li
12670  role="presentation"
12671  class="menu-list__list-item bp-menu-item-li"
12672  data-bp-menu-item
12673  
12674><a
12675      href="/collections/clothing"
12676      data-skip-node-update="true"
12677      class="menu-list__link"
12678      aria-controls="bp-submenu-AUjR2VlEyVFlTbXhaM__bp_menu_clothing-1"
12679      aria-haspopup="true"
12680      aria-expanded="false"
12681      ref="menuitem"
12682    >
12683      <span class="menu-list__link-title">Clothing</span>
12684    </a>
12685    <div class="bp-mega-submenu" id="bp-submenu-AUjR2VlEyVFlTbXhaM__bp_menu_clothing-1">
12686      <div class="bp-mega-submenu__inner">
12687        <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column">
12688                  <p class="bp-mega__heading"><a href="/collections/clothing">Clothing</a></p><ul class="bp-mega__links"><li><a href="/collections/clothing">All Clothing</a></li><li><a href="/collections/clothing-athleisure">Athleisure</a></li><li><a href="/collections/clothing-bottoms">Bottoms</a></li><li><a href="/collections/clothing-jeans">Denim & Jeans</a></li><li><a href="/collections/clothing-dresses">Dresses</a></li><li><a href="/collections/clothing-intimates">Intimates</a></li><li><a href="/collections/clothing-jackets-blazers">Jackets & Blazers</a></li><li><a href="/collections/clothing-loungewear">Loungewear</a></li><li><a href="/collections/clothing-pants-leggings">Pants & Leggings</a></li><li><a href="/collections/clothing-shirts-blouses">Shirts & Blouses</a></li><li><a href="/collections/clothing-skirts-shorts">Skirts & Shorts</a></li><li><a href="/collections/clothing-sweaters">Sweaters</a></li><li><a href="/collections/clothing-swimsuits-swimwear">Swimwear</a></li><li><a href="/collections/clothing-tops-blouses-tees">Tops</a></li></ul></div><div class="bp-mega__column">
12689                  <p class="bp-mega__heading"><a href="/pages/all-occasions">Occasions</a></p><ul class="bp-mega__links"><li><a href="/collections/occasions-everyday-style">Casual Chic</a></li><li><a href="/collections/occasions-night-out">Own the Evening</a></li><li><a href="/collections/occasions-special-occasion">RSVP Ready</a></li><li><a href="/collections/occasions-vacation">Escape in Style</a></li><li><a href="/collections/occasions-work">Power Moves</a></li><li><a href="/collections/occasions-wedding">Celebrate Beautifully</a></li></ul></div><div class="bp-mega__column">
12690                  <p class="bp-mega__heading"><a href="/collections/clothing">Shops</a></p><ul class="bp-mega__links"><li><a href="/collections/clothing-pants-leggings">
12690The Bottoms Guide</a></li><li><a href="/collections/clothing-jeans">The Denim Guide</a></li><li><a href="/pages/essentials-collection">The Essentials Edit</a></li><li><a href="/collections/essentials">The Tops Collection</a></li><li><a href="/collections/the-suiting-shop">The Suiting Shop</a></li><li><a href="/pages/the-dress-code">Style Guide: The Dress Code</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li><li><a href="/pages/the-sweater-edit">Style Guide: The Sweater Edit</a></li></ul></div><div class="bp-mega__column">
12691                  <p class="bp-mega__heading"><a href="/collections/all-brands-we-love">Brands We Love</a></p><ul class="bp-mega__links"><li><a href="/collections/brands-we-love-becca">Becca By Rebecca Virtue</a></li><li><a href="/collections/brands-we-love-carmen-marc-valvo">Carmen Marc Valvo</a></li><li><a href="/collections/brands-we-love-change-of-scenery">Change of Scenery</a></li><li><a href="/collections/brands-we-love-mimosa-lane">Mimosa Lane</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini X Boston Proper</a></li><li><a href="/collections/brands-we-love-saint-jo">Saint Jō</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li><li><a href="/collections/brands-we-love-walter-baker">Walter Baker</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li></ul></div></div><div class="bp-mega__promos"><div class="bp-mega__promo">
12692  <a href="/collections/breast-cancer-awareness" class="bp-mega__promo-link">
12693    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_69.jpg?v=1790780283&amp;width=400" alt="Power In Pink" srcset="//www.bostonproper.com/cdn/shop/files/Image_69.jpg?v=1790780283&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_69.jpg?v=1790780283&amp;width=400 400w" width="400" height="500" loading="lazy">
12694</div>
12695    <h4 class="bp-mega__promo-title">Power In Pink</h4><div class="bp-mega__promo-copy"><p>Wearing pink never felt so powerful. Shop our curated Power in Pink Collection and join us in supporting the Lynn Cancer Institute.</p></div><span class="bp-mega__promo-cta">Shop With Purpose</span>
12696  </a>
12697</div>
12698
12699<div class="bp-mega__promo">
12700  <a href="/collections/knit-tops" class="bp-mega__promo-link">
12701    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Clothing_Image-8.jpg?v=1790707168&amp;width=400" alt="Knit Tops" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Clothing_Image-8.jpg?v=1790707168&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Clothing_Image-8.jpg?v=1790707168&amp;width=400 400w" width="400" height="500" loading="lazy">
12702</div>
12703    <h4 class="bp-mega__promo-title">Knit Tops</h4><div class="bp-mega__promo-copy"><p>From everyday to unforgettable. Flattering knits made for denim, jackets, and everything after.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
12704  </a>
12705</div>
12706
12707</div></div>
12708      </div>
12709    </div></li><li class="bp-mm-item" data-bp-mm-id="AUjR2VlEyVFlTbXhaM__bp_menu_clothing-1"><button type="button" class="bp-mm-item__row" data-open-view="AUjR2VlEyVFlTbXhaM__bp_menu_clothing-1">
12710      <span class="bp-mm-item__label">Clothing</span>
12711      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12712  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12713</svg>
12714</span>
12715    </button>
12716
12717    <section class="bp-mm-view" data-view="AUjR2VlEyVFlTbXhaM__bp_menu_clothing-1" hidden>
12718      <header class="bp-mm-view__header">
12719        <button type="button" class="bp-mm-view__back" data-back>
12720          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12721  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12722</svg>
12723</span>
12724          <span>Clothing</span>
12725        </button>
12726        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12727  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12728  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12729</svg>
12730</button>
12731      </header><div class="bp-mm-view__sections"><section class="bp-mm-section">
12732              <p class="bp-mm-section__heading"><a href="/collections/clothing">Clothing</a></p><ul class="bp-mm-section__links"><li><a href="/collections/clothing">All Clothing</a></li><li><a href="/collections/clothing-athleisure">Athleisure</a></li><li><a href="/collections/clothing-bottoms">Bottoms</a></li><li><a href="/collections/clothing-jeans">Denim & Jeans</a></li><li><a href="/collections/clothing-dresses">Dresses</a></li><li><a href="/collections/clothing-intimates">Intimates</a></li><li><a href="/collections/clothing-jackets-blazers">Jackets & Blazers</a></li><li><a href="/collections/clothing-loungewear">Loungewear</a></li><li><a href="/collections/clothing-pants-leggings">Pants & Leggings</a></li><li><a href="/collections/clothing-shirts-blouses">Shirts & Blouses</a></li><li><a href="/collections/clothing-skirts-shorts">Skirts & Shorts</a></li><li><a href="/collections/clothing-sweaters">Sweaters</a></li><li><a href="/collections/clothing-swimsuits-swimwear">Swimwear</a></li><li><a href="/collections/clothing-tops-blouses-tees">Tops</a></li></ul></section><section class="bp-mm-section">
12733              <p class="bp-mm-section__heading"><a href="/pages/all-occasions">Occasions</a></p><ul class="bp-mm-section__links"><li><a href="/collections/occasions-everyday-style">Casual Chic</a></li><li><a href="/collections/occasions-night-out">Own the Evening</a></li><li><a href="/collections/occasions-special-occasion">RSVP Ready</a></li><li><a href="/collections/occasions-vacation">Escape in Style</a></li><li><a href="/collections/occasions-work">Power Moves</a></li><li><a href="/collections/occasions-wedding">Celebrate Beautifully</a></li></ul></section><section class="bp-mm-section">
12734              <p class="bp-mm-section__heading"><a href="/collections/clothing">Shops</a></p><ul class="bp-mm-section__links"><li><a href="/collections/clothing-pants-leggings">The Bottoms Guide</a></li><li><a href="/collections/clothing-jeans">The Denim Guide</a></li><li><a href="/pages/essentials-collection">The Essentials Edit</a></li><li><a href="/collections/essentials">The Tops Collection</a></li><li><a href="/collections/the-suiting-shop">The Suiting Shop</a></li><li><a href="/pages/the-dress-code">Style Guide: The Dress Code</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li><li><a href="/pages/the-sweater-edit">Style Guide: The Sweater Edit</a></li></ul></section><section class="bp-mm-section">
12735              <p class="bp-mm-section__heading"><a href="/collections/all-brands-we-love">Brands We Love</a></p><ul class="bp-mm-section__links"><li><a href="/collections/brands-we-love-becca">Becca By Rebecca Virtue</a></li><li><a href="/collections/brands-we-love-carmen-marc-valvo">Carmen Marc Valvo</a></li><li><a href="/collections/brands-we-love-change-of-scenery">Change of Scenery</a></li><li><a href="/collections/brands-we-love-mimosa-lane">Mimosa Lane</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini X Boston Proper</a></li><li><a href="/collections/brands-we-love-saint-jo">Saint Jō</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li><li><a href="/collections/brands-we-love-walter-baker">Walter Baker</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo">
12736  <a href="/collections/breast-cancer-awareness" class="bp-mega__promo-link">
12737    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_69.jpg?v=1790780283&amp;width=400" alt="Power In Pink" srcset="//www.bostonproper.com/cdn/shop/files/Image_69.jpg?v=1790780283&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_69.jpg?v=1790780283&amp;width=400 400w" width="400" height="500" loading="lazy">
12738</div>
12739    <h4 class="bp-mega__promo-title">Power In Pink</h4><div class="bp-mega__promo-copy"><p>Wearing pink never felt so powerful. Shop our curated Power in Pink Collection and join us in supporting the Lynn Cancer Institute.</p></div><span class="bp-mega__promo-cta">Shop With Purpose</span>
12740  </a>
12741</div>
12742
12743<div class="bp-mega__promo">
12744  <a href="/collections/knit-tops" class="bp-mega__promo-link">
12745    <div class="bp-mega__promo-image">
12745<img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Clothing_Image-8.jpg?v=1790707168&amp;width=400" alt="Knit Tops" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Clothing_Image-8.jpg?v=1790707168&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Clothing_Image-8.jpg?v=1790707168&amp;width=400 400w" width="400" height="500" loading="lazy">
12746</div>
12747    <h4 class="bp-mega__promo-title">Knit Tops</h4><div class="bp-mega__promo-copy"><p>From everyday to unforgettable. Flattering knits made for denim, jackets, and everything after.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
12748  </a>
12749</div>
12750
12751</div></section></li>
12752
12753
12754
12755<li
12756  role="presentation"
12757  class="menu-list__list-item bp-menu-item-li"
12758  data-bp-menu-item
12759  
12760><a
12761      href="/pages/all-occasions"
12762      data-skip-node-update="true"
12763      class="menu-list__link"
12764      aria-controls="bp-submenu-AWlVkd2t4OFJocXpVU__bp_menu_occasions-1"
12765      aria-haspopup="true"
12766      aria-expanded="false"
12767      ref="menuitem"
12768    >
12769      <span class="menu-list__link-title">Occasions</span>
12770    </a>
12771    <div class="bp-mega-submenu" id="bp-submenu-AWlVkd2t4OFJocXpVU__bp_menu_occasions-1">
12772      <div class="bp-mega-submenu__inner">
12773        <div class="bp-mega bp-mega--image-tiles"><div class="bp-mega__tiles"><a class="bp-mega__tile" href="/collections/occasions-everyday-style">
12774                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-10.jpg?v=1790701815&amp;width=400" alt="Casual Chic" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-10.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-10.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12775</div>
12776                  <p class="bp-mega__tile-title">Casual Chic</p>
12777                  <span class="bp-mega__tile-cta">Shop Now</span>
12778                </a><a class="bp-mega__tile" href="/collections/occasions-vacation">
12779                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-14.jpg?v=1790701815&amp;width=400" alt="Escape in Style" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-14.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-14.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12780</div>
12781                  <p class="bp-mega__tile-title">Escape in Style</p>
12782                  <span class="bp-mega__tile-cta">Shop Now</span>
12783                </a><a class="bp-mega__tile" href="/collections/occasions-special-occasion">
12784                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-16.jpg?v=1790701815&amp;width=400" alt="RSVP Ready" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-16.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-16.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12785</div>
12786                  <p class="bp-mega__tile-title">RSVP Ready</p>
12787                  <span class="bp-mega__tile-cta">Shop Now</span>
12788                </a><a class="bp-mega__tile" href="/collections/occasions-work">
12789                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-12.jpg?v=1790701815&amp;width=400" alt="Power Moves" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-12.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-12.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12790</div>
12791                  <p class="bp-mega__tile-title">Power Moves</p>
12792                  <span class="bp-mega__tile-cta">Shop Now</span>
12793                </a><a class="bp-mega__tile" href="/collections/occasions-night-out">
12794                  <div class="bp-mega__tile-image">
12794<img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-18_9dd5998e-01cb-46c4-a182-cd9be31c2c67.jpg?v=1790701815&amp;width=400" alt="Own the Evening" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-18_9dd5998e-01cb-46c4-a182-cd9be31c2c67.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-18_9dd5998e-01cb-46c4-a182-cd9be31c2c67.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12795</div>
12796                  <p class="bp-mega__tile-title">Own the Evening</p>
12797                  <span class="bp-mega__tile-cta">Shop Now</span>
12798                </a><a class="bp-mega__tile" href="/collections/occasions-wedding">
12799                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-20_6043da00-6dae-4bd6-9c2c-e935f58f8b4c.jpg?v=1790701815&amp;width=400" alt="Celebrate Beautifully" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-20_6043da00-6dae-4bd6-9c2c-e935f58f8b4c.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-20_6043da00-6dae-4bd6-9c2c-e935f58f8b4c.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12800</div>
12801                  <p class="bp-mega__tile-title">Celebrate Beautifully</p>
12802                  <span class="bp-mega__tile-cta">Shop Now</span>
12803                </a></div></div>
12804      </div>
12805    </div></li><li class="bp-mm-item" data-bp-mm-id="AWlVkd2t4OFJocXpVU__bp_menu_occasions-1"><button type="button" class="bp-mm-item__row" data-open-view="AWlVkd2t4OFJocXpVU__bp_menu_occasions-1">
12806      <span class="bp-mm-item__label">Occasions</span>
12807      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12808  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12809</svg>
12810</span>
12811    </button>
12812
12813    <section class="bp-mm-view" data-view="AWlVkd2t4OFJocXpVU__bp_menu_occasions-1" hidden>
12814      <header class="bp-mm-view__header">
12815        <button type="button" class="bp-mm-view__back" data-back>
12816          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12817  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12818</svg>
12819</span>
12820          <span>Occasions</span>
12821        </button>
12822        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12823  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12824  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12825</svg>
12826</button>
12827      </header><div class="bp-mm-view__tiles"><a class="bp-mm-tile" href="/collections/occasions-everyday-style">
12828              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-10.jpg?v=1790701815&amp;width=400" alt="Casual Chic" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-10.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-10.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12829</span>
12830              <span class="bp-mm-tile__title">Casual Chic</span>
12831              <span class="bp-mm-tile__cta">Shop Now</span>
12832            </a><a class="bp-mm-tile" href="/collections/occasions-vacation">
12833              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-14.jpg?v=1790701815&amp;width=400" alt="Escape in Style" srcset="//www.bostonproper.com/cdn/shop/files/Fl
12833y_Downs_Occasions_Image-14.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-14.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12834</span>
12835              <span class="bp-mm-tile__title">Escape in Style</span>
12836              <span class="bp-mm-tile__cta">Shop Now</span>
12837            </a><a class="bp-mm-tile" href="/collections/occasions-special-occasion">
12838              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-16.jpg?v=1790701815&amp;width=400" alt="RSVP Ready" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-16.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-16.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12839</span>
12840              <span class="bp-mm-tile__title">RSVP Ready</span>
12841              <span class="bp-mm-tile__cta">Shop Now</span>
12842            </a><a class="bp-mm-tile" href="/collections/occasions-work">
12843              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-12.jpg?v=1790701815&amp;width=400" alt="Power Moves" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-12.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-12.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12844</span>
12845              <span class="bp-mm-tile__title">Power Moves</span>
12846              <span class="bp-mm-tile__cta">Shop Now</span>
12847            </a><a class="bp-mm-tile" href="/collections/occasions-night-out">
12848              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-18_9dd5998e-01cb-46c4-a182-cd9be31c2c67.jpg?v=1790701815&amp;width=400" alt="Own the Evening" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-18_9dd5998e-01cb-46c4-a182-cd9be31c2c67.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-18_9dd5998e-01cb-46c4-a182-cd9be31c2c67.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12849</span>
12850              <span class="bp-mm-tile__title">Own the Evening</span>
12851              <span class="bp-mm-tile__cta">Shop Now</span>
12852            </a><a class="bp-mm-tile" href="/collections/occasions-wedding">
12853              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-20_6043da00-6dae-4bd6-9c2c-e935f58f8b4c.jpg?v=1790701815&amp;width=400" alt="Celebrate Beautifully" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-20_6043da00-6dae-4bd6-9c2c-e935f58f8b4c.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-20_6043da00-6dae-4bd6-9c2c-e935f58f8b4c.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12854</span>
12855              <span class="bp-mm-tile__title">Celebrate Beautifully</span>
12856              <span class="bp-mm-tile__cta">Shop Now</span>
12857            </a></div></section></li>
12858
12859
12860
12861<li
12862  role="presentation"
12863  class="menu-list__list-item bp-menu-item-li"
12864  data-bp-menu-item
12865  
12866><a
12867      href="/pages/essentials-collection"
12868      data-skip-node-update="true"
12869      class="menu-list__link"
12870      aria-controls="bp-submenu-ARTdKY3Jpczg4VVVHb__bp_menu_collections-1"
12871      aria-haspopup="true"
12872      aria-expanded="false"
12873      ref="menuitem"
12874    >
12875      <span class="menu-list__link-title">Collections</span>
12876    </a>
12877    <div class="bp-mega-submenu" id="bp-submenu-ARTdKY3Jpczg4VVVHb__bp_menu_collections-1">
12878      <div class="bp-mega-submenu__inner">
12879        <div class="bp-mega bp-mega--image-tiles"><div class="bp-mega__tiles"><a class="bp-mega__tile" href="/collections/charmeuse">
12880                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-11.jpg?v=1790701815&amp;width=400" alt="Charmeuse" srcset="//www.bostonproper.com/cdn/shop/files/Fl
12880y_Downs_Collections_Image-11.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-11.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12881</div>
12882                  <p class="bp-mega__tile-title">Charmeuse</p>
12883                  <span class="bp-mega__tile-cta">Shop Now</span>
12884                </a><a class="bp-mega__tile" href="/collections/chic-zip">
12885                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_76_c1e341e6-f12c-49d5-bc88-54e2673f3c30.jpg?v=1790802160&amp;width=400" alt="Chic Zip" srcset="//www.bostonproper.com/cdn/shop/files/Image_76_c1e341e6-f12c-49d5-bc88-54e2673f3c30.jpg?v=1790802160&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_76_c1e341e6-f12c-49d5-bc88-54e2673f3c30.jpg?v=1790802160&amp;width=400 400w" width="400" height="500" loading="lazy">
12886</div>
12887                  <p class="bp-mega__tile-title">Chic Zip</p>
12888                  <span class="bp-mega__tile-cta">Shop Now</span>
12889                </a><a class="bp-mega__tile" href="/collections/clothing-jeans">
12890                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-17.jpg?v=1790701815&amp;width=400" alt="Denim" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-17.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-17.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12891</div>
12892                  <p class="bp-mega__tile-title">Denim</p>
12893                  <span class="bp-mega__tile-cta">Shop Now</span>
12894                </a><a class="bp-mega__tile" href="/collections/the-suiting-shop">
12895                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-13.jpg?v=1790701815&amp;width=400" alt="Modern Suiting" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-13.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-13.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12896</div>
12897                  <p class="bp-mega__tile-title">Modern Suiting</p>
12898                  <span class="bp-mega__tile-cta">Shop Now</span>
12899                </a><a class="bp-mega__tile" href="/collections/travel">
12900                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-19.jpg?v=1790701815&amp;width=400" alt="Beyond Travel" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-19.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-19.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12901</div>
12902                  <p class="bp-mega__tile-title">Beyond Travel</p>
12903                  <span class="bp-mega__tile-cta">Shop Now</span>
12904                </a><a class="bp-mega__tile" href="/collections/athleisure-luxe-lounge">
12905                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-21.jpg?v=1790701815&amp;width=400" alt="Luxe Lounge" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-21.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-21.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12906</div>
12907                  <p class="bp-mega__tile-title">Luxe Lounge</p>
12908                  <span class="bp-mega__tile-cta">Shop Now</span>
12909                </a></div></div>
12910      </div>
12911    </div></li><li class="bp-mm-item" data-bp-mm-id="ARTdKY3Jpczg4VVVHb__bp_menu_collections-1"><button type="button" class="bp-mm-item__row" data-open-view="ARTdKY3Jpczg4VVVHb__bp_menu_collections-1">
12912      <span class="bp-mm-item__label">Collections</span>
12913      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12914  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12915</svg>
12916</span>
12917    </button>
12918
12919    <section class="bp-mm-view" data-view="ARTdKY3Jpczg4VVVHb__bp_menu_collections-1" hidden>
12920      <header class="bp-mm-view__header">
12921        <button type="button" class="bp-mm-view__back" data-back>
12922          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12923  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12924</svg>
12925</span>
12926          <span>Collections</span>
12927        </button>
12928        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
12929  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12930  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
12931</svg>
12932</button>
12933      </header><div class="bp-mm-view__tiles"><a class="bp-mm-tile" href="/collections/charmeuse">
12934              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-11.jpg?v=1790701815&amp;width=400" alt="Charmeuse" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-11.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-11.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12935</span>
12936              <span class="bp-mm-tile__title">Charmeuse</span>
12937              <span class="bp-mm-tile__cta">Shop Now</span>
12938            </a><a class="bp-mm-tile" href="/collections/chic-zip">
12939              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_76_c1e341e6-f12c-49d5-bc88-54e2673f3c30.jpg?v=1790802160&amp;width=400" alt="Chic Zip" srcset="//www.bostonproper.com/cdn/shop/files/Image_76_c1e341e6-f12c-49d5-bc88-54e2673f3c30.jpg?v=1790802160&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_76_c1e341e6-f12c-49d5-bc88-54e2673f3c30.jpg?v=1790802160&amp;width=400 400w" width="400" height="500" loading="lazy">
12940</span>
12941              <span class="bp-mm-tile__title">Chic Zip</span>
12942              <span class="bp-mm-tile__cta">Shop Now</span>
12943            </a><a class="bp-mm-tile" href="/collections/clothing-jeans">
12944              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-17.jpg?v=1790701815&amp;width=400" alt="Denim" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-17.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-17.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12945</span>
12946              <span class="bp-mm-tile__title">Denim</span>
12947              <span class="bp-mm-tile__cta">Shop Now</span>
12948            </a><a class="bp-mm-tile" href="/collections/the-suiting-shop">
12949              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-13.jpg?v=1790701815&amp;width=400" alt="Modern Suiting" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-13.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-13.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12950</span>
12951              <span class="bp-mm-tile__title">Modern Suiting</span>
12952              <span class="bp-mm-tile__cta">Shop Now</span>
12953            </a><a class="bp-mm-tile" href="/collections/travel">
12954              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-19.jpg?v=1790701815&amp;width=400" alt="Beyond Travel" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-19.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-19.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12955</span>
12956              <span class="bp-mm-tile__title">Beyond Travel</span>
12957              <span class="bp-mm-tile__cta">Shop Now</span>
12958            </a><a class="bp-mm-tile" href="/collections/athleisure-luxe-lounge">
12959              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-21.jpg?v=1790701815&amp;width=400" alt="Luxe Lounge" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-21.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-21.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
12960</span>
12961              <span class="bp-mm-tile__title">Luxe Lounge</span>
12962              <span class="bp-mm-tile__cta">Shop Now</span>
12963            </a></div></section></li>
12964
12965
12966
12967<li
12968  role="presentation"
12969  class="menu-list__list-item bp-menu-item-li"
12970  data-bp-menu-item
12971  
12972><a
12973      href="/collections/shoes-accessories"
12974      data-skip-node-update="true"
12975      class="menu-list__link"
12976      aria-controls="bp-submenu-AdVdsY2tEV2JFWlVvV__bp_menu_shoes-1"
12977      aria-haspopup="true"
12978      aria-expanded="false"
12979      ref="menuitem"
12980    >
12981      <span class="menu-list__link-title">Shoes & Accessories</span>
12982    </a>
12983    <div class="bp-mega-submenu" id="bp-submenu-AdVdsY2tEV2JFWlVvV__bp_menu_shoes-1">
12984      <div class="bp-mega-submenu__inner">
12985        <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column">
12986                  <p class="bp-mega__heading"><a href="/collections/shoes">Shoes</a></p><ul class="bp-mega__links"><li><a href="/collections/shoes">All Shoes</a></li><li><a href="/collections/shoes-boots">Boots & Booties</a></li><li><a href="/collections/shoes-heels">Heels</a></li><li><a href="/collections/shoes-sandals">Sandals</a></li><li><a href="/collections/shoes-sneakers">Sneakers</a></li><li><a href="/collections/shoes-wedges">Wedges</a></li></ul></div><div class="bp-mega__column">
12987                  <p class="bp-mega__heading"><a href="/collections/accessories">Accessories</a></p><ul class="bp-mega__links"><li><a href="/collections/accessories">All Accessories</a></li><li><a href="/collections/accessories-bags">Bags</a></li><li><a href="/collections/accessories-belts">Belts</a></li><li><a href="/collections/accessories-hats">Hats</a></li><li><a href="/collections/accessories-jewelry">Jewelry</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Sunglasses</a></li></ul></div><div class="bp-mega__column">
12988                  <p class="bp-mega__heading"><a href="/collections/all-brands-we-love">Brands We Love</a></p><ul class="bp-mega__links"><li><a href="/collections/brands-we-love-amsterdam-heritage">Amsterdam Heritage</a></li><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-ettika">Ettika</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-hanky-panky">Hanky Panky</a></li><li><a href="/collections/brands-we-love-hat-attack-new-york">Hat Attack</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-miami-chains-co">Miami Chains & Co.</a></li><li><a href="/collections/brands-we-love-st-moran">St. Moran</a></li><li><a href="/collections/brands-we-love-the-sak">The Sak</a></li><li><a href="/collections/brands-we-love-t-jazelle">T. Jazelle</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></div></div><div class="bp-mega__promos"><div class="bp-mega__promo">
12989  <a href="/collections/shoes-boots" class="bp-mega__promo-link">
12990    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_63.jpg?v=1790780283&amp;width=400" alt="Boots" srcset="//www.bostonproper.com/cdn/shop/files/Image_63.jpg?v=1790780283&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_63.jpg?v=1790780283&amp;width=400 400w" width="400" height="500" loading="lazy">
12991</div>
12992    <h4 class="bp-mega__promo-title">Boots</h4><div class="bp-mega__promo-copy"><p>These boots are going places. Wild prints. Rich color stories. Versatile lengths. A new look for every mood.<br/><br/></p></div><span class="bp-mega__promo-cta">Shop Now</span>
12993  </a>
12994</div>
12995
12996<div class="bp-mega__promo">
12997  <a href="/collections/accessories-jewelry" class="bp-mega__promo-link">
12998    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_74.jpg?v=1790800759&amp;width=400" alt="Jewelry" srcset="//www.bostonproper.com/cdn/shop/files/Image_74.jpg?v=1790800759&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_74.jpg?v=1790800759&amp;width=400 400w" width="400" height="500" loading="lazy">
12999</div>
13000    <h4 class="bp-mega__promo-title">Jewelry</h4><div class="bp-mega__promo-copy"><p>Drenched in the&nbsp;details&nbsp;that define Boston Proper. Layered jewels&nbsp;and accent pieces&nbsp;that set the tone.&nbsp;&nbsp;</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13001  </a>
13002</div>
13003
13004</div></div>
13005      </div>
13006    </div></li><li class="bp-mm-item" data-bp-mm-id="AdVdsY2tEV2JFWlVvV__bp_menu_shoes-1"><button type="button" class="bp-mm-item__row" data-open-view="AdVdsY2tEV2JFWlVvV__bp_menu_shoes-1">
13007      <span class="bp-mm-item__label">Shoes & Accessories</span>
13008      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13009  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13010</svg>
13011</span>
13012    </button>
13013
13014    <section class="bp-mm-view" data-view="AdVdsY2tEV2JFWlVvV__bp_menu_shoes-1" hidden>
13015      <header class="bp-mm-view__header">
13016        <button type="button" class="bp-mm-view__back" data-back>
13017          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13018  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13019</svg>
13020</span>
13021          <span>Shoes & Accessories</span>
13022        </button>
13023        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13024  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13025  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13026</svg>
13027</button>
13028      </header><div class="bp-mm-view__sections"><section class="bp-mm-section">
13029              <p class="bp-mm-section__heading"><a href="/collections/shoes">Shoes</a></p><ul class="bp-mm-section__links"><li><a href="/collections/shoes">All Shoes</a></li><li><a href="/collections/shoes-boots">Boots & Booties</a></li><li><a href="/collections/shoes-heels">Heels</a></li><li><a href="/collections/shoes-sandals">Sandals</a></li><li><a href="/collections/shoes-sneakers">Sneakers</a></li><li><a href="/collections/shoes-wedges">Wedges</a></li></ul></section><section class="bp-mm-section">
13030              <p class="bp-mm-section__heading"><a href="/collections/accessories">Accessories</a></p><ul class="bp-mm-section__links"><li><a href="/collections/accessories">All Accessories</a></li><li><a href="/collections/accessories-bags">Bags</a></li><li><a href="/collections/accessories-belts">Belts</a></li><li><a href="/collections/accessories-hats">Hats</a></li><li><a href="/collections/accessories-jewelry">Jewelry</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Sunglasses</a></li></ul></section><section class="bp-mm-section">
13031              <p class="bp-mm-section__heading"><a href="/collections/all-brands-we-love">Brands We Love</a></p><ul class="bp-mm-section__links"><li><a href="/collections/brands-we-love-amsterdam-heritage">Amsterdam Heritage</a></li><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-ettika">Ettika</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-hanky-panky">Hanky Panky</a></li><li><a href="/collections/brands-we-love-hat-attack-new-york">Hat Attack</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-miami-chains-co">Miami Chains & Co.</a></li><li><a href="/collections/brands-we-love-st-moran">St. Moran</a></li><li><a href="/collections/brands-we-love-the-sak">The Sak</a></li><li><a href="/collections/brands-we-love-t-jazelle">T. Jazelle</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo">
13032  <a href="/collections/shoes-boots" class="bp-mega__promo-link">
13033    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_63.jpg?v=1790780283&amp;width=400" alt="Boots" srcset="//www.bostonproper.com/cdn/shop/files/Image_63.jpg?v=1790780283&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_63.jpg?v=1790780283&amp;width=400 400w" width="400" height="500" loading="lazy">
13034</div>
13035    <h4 class="bp-mega__promo-title">Boots</h4><div class="bp-mega__promo-copy"><p>These boots are going places. Wild prints. Rich color stories. Versatile lengths. A new look for every mood.<br/><br/></p></div><span class="bp-mega__promo-cta">Shop Now</span>
13036  </a>
13037</div>
13038
13039<div class="bp-mega__promo">
13040  <a href="/collections/accessories-jewelry" class="bp-mega__promo-link">
13041    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_74.jpg?v=1790800759&amp;width=400" alt="Jewelry" srcset="//www.bostonproper.com/cdn/shop/files/Image_74.jpg?v=1790800759&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_74.jpg?v=1790800759&amp;width=400 400w" width="400" height="500" loading="lazy">
13042</div>
13043    <h4 class="bp-mega__promo-title">Jewelry</h4><div class="bp-mega__promo-copy"><p>Drenched in the&nbsp;details&nbsp;that define Boston Proper. Layered jewels&nbsp;and accent pieces&nbsp;that set the tone.&nbsp;&nbsp;</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13044  </a>
13045</div>
13046
13047</div></section></li>
13048
13049
13050
13051<li
13052  role="presentation"
13053  class="menu-list__list-item bp-menu-item-li"
13054  data-bp-menu-item
13055  
13056><a
13057      href="/collections/sale-clearance"
13058      data-skip-node-update="true"
13059      class="menu-list__link"
13060      aria-controls="bp-submenu-AVFlZUDZaR3FYUVAyd__bp_menu_sale-1"
13061      aria-haspopup="true"
13062      aria-expanded="false"
13063      ref="menuitem"
13064    >
13065      <span class="menu-list__link-title">Sale & Clearance</span>
13066    </a>
13067    <div class="bp-mega-submenu" id="bp-submenu-AVFlZUDZaR3FYUVAyd__bp_menu_sale-1">
13068      <div class="bp-mega-submenu__inner">
13069        <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column">
13070                  <p class="bp-mega__heading"><a href="/collections/sale-clearance">Sale & Clearance</a></p><ul class="bp-mega__links"><li><a href="/collections/sale-clearance">Shop All</a></li><li><a href="/collections/new-markdowns">New Markdowns</a></li><li><a href="/collections/sale">Sale</a></li><li><a href="/collections/clearance">Clearance</a></li></ul></div><div class="bp-mega__column">
13071                  <p class="bp-mega__heading"><a href="/collections/sale-clearance">Shop By Category</a></p><ul class="bp-mega__links"><li><a href="/collections/sale-clearance-accessories">Accessories</a></li><li><a href="/collections/sale-clearance-athleisure">Athleisure</a></li><li><a href="/collections/sale-clearance-dresses">Dresses</a></li><li><a href="/collections/sale-clearance-jackets">Jackets & Blazers</a></li><li><a href="/collections/sale-clearance-jeans">Jeans</a></li><li><a href="/collections/sale-clearance-outerwear">Outerwear</a></li><li><a href="/collections/sale-clearance-pants-leggings">Pants & Leggings</a></li><li><a href="/collections/sale-clearance-shoes">Shoes</a></li><li><a href="/collections/sale-clearance-shorts">Shorts</a></li><li><a href="/collections/sale-clearance-skirts">Skirts</a></li><li><a href="/collections/sale-clearance-sweaters">Sweaters</a></li><li><a href="/collections/sale-clearance-swimwear">Swimwear</a></li><li><a href="/collections/sale-clearance-tops">Tops</a></li></ul></div><div class="bp-mega__column">
13072                  <p class="bp-mega__heading"><a href="/collections/sale-clearance">Promotions</a></p><ul class="bp-mega__links"><li><a href="/collections/new-arrivals">20% off $175+ plus free shipping</a></li><li><a href="/collections/winter-classic-rib-styles">Save $45 on 3 or $25 on 2</a></li><li><a href="/products/boston-proper-printed-scarf-with-love-bp">Free gift with  purchase of $400+</a></li></ul></div></div><div class="bp-mega__promos"><div class="bp-mega__promo">
13073  <a href="/collections/new-markdowns" class="bp-mega__promo-link">
13074    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_b520536c-2111-43e4-b1e8-166793f8fe43.jpg?v=1790704244&amp;width=400" alt="New Markdowns" srcset="//www.bostonproper.com/cdn/shop/files/Image_b520536c-2111-43e4-b1e8-166793f8fe43.jpg?v=1790704244&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_b520536c-2111-43e4-b1e8-166793f8fe43.jpg?v=1790704244&amp;width=400 400w" width="400" height="500" loading="lazy">
13075</div>
13076    <h4 class="bp-mega__promo-title">New Markdowns</h4><div class="bp-mega__promo-copy"><p>Rare finds.&nbsp;Newly reduced.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13077  </a>
13078</div>
13079
13080<div class="bp-mega__promo">
13081  <a href="/collections/clearance" class="bp-mega__promo-link">
13082    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image-1.jpg?v=1790780282&amp;width=400" alt="Clearance" srcset="//www.bostonproper.com/cdn/shop/files/Image-1.jpg?v=1790780282&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image-1.jpg?v=1790780282&amp;width=400 400w" width="400" height="500" loading="lazy">
13083</div>
13084    <h4 class="bp-mega__promo-title">Clearance</h4><div class="bp-mega__promo-copy"><p>Your size won’t stay here long.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13085  </a>
13086</div>
13087
13088</div></div>
13089      </div>
13090    </div></li><li class="bp-mm-item" data-bp-mm-id="AVFlZUDZaR3FYUVAyd__bp_menu_sale-1"><button type="button" class="bp-mm-item__row" data-open-view="AVFlZUDZaR3FYUVAyd__bp_menu_sale-1">
13091      <span class="bp-mm-item__label">Sale & Clearance</span>
13092      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13093  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13094</svg>
13095</span>
13096    </button>
13097
13098    <section class="bp-mm-view" data-view="AVFlZUDZaR3FYUVAyd__bp_menu_sale-1" hidden>
13099      <header class="bp-mm-view__header">
13100        <button type="button" class="bp-mm-view__back" data-back>
13101          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13102  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13103</svg>
13104</span>
13105          <span>Sale & Clearance</span>
13106        </button>
13107        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13108  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13109  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13110</svg>
13111</button>
13112      </header><div class="bp-mm-view__sections"><section class="bp-mm-section">
13113              <p class="bp-mm-section__heading"><a href="/collections/sale-clearance">Sale & Clearance</a></p><ul class="bp-mm-section__links"><li><a href="/collections/sale-clearance">Shop All</a></li><li><a href="/collections/new-markdowns">New Markdowns</a></li><li><a href="/collections/sale">Sale</a></li><li><a href="/collections/clearance">Clearance</a></li></ul></section><section class="bp-mm-section">
13114              <p class="bp-mm-section__heading"><a href="/collections/sale-clearance">Shop By Category</a></p><ul class="bp-mm-section__links"><li><a href="/collections/sale-clearance-accessories">Accessories</a></li><li><a href="/collections/sale-clearance-athleisure">Athleisure</a></li><li><a href="/collections/sale-clearance-dresses">Dresses</a></li><li><a href="/collections/sale-clearance-jackets">Jackets & Blazers</a></li><li><a href="/collections/sale-clearance-jeans">Jeans</a></li><li><a href="/collections/sale-clearance-outerwear">Outerwear</a></li><li><a href="/collections/sale-clearance-pants-leggings">Pants & Leggings</a></li><li><a href="/collections/sale-clearance-shoes">Shoes</a></li><li><a href="/collections/sale-clearance-shorts">Shorts</a></li><li><a href="/collections/sale-clearance-skirts">Skirts</a></li><li><a href="/collections/sale-clearance-sweaters">Sweaters</a></li><li><a href="/collections/sale-clearance-swimwear">Swimwear</a></li><li><a href="/collections/sale-clearance-tops">Tops</a></li></ul></section><section class="bp-mm-section">
13115              <p class="bp-mm-section__heading"><a href="/collections/sale-clearance">Promotions</a></p><ul class="bp-mm-section__links"><li><a href="/collections/new-arrivals">20% off $175+ plus free shipping</a></li><li><a href="/collections/winter-classic-rib-styles">Save $45 on 3 or $25 on 2</a></li><li><a href="/products/boston-proper-printed-scarf-with-love-bp">Free gift with  purchase of $400+</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo">
13116  <a href="/collections/new-markdowns" class="bp-mega__promo-link">
13117    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_b520536c-2111-43e4-b1e8-166793f8fe43.jpg?v=1790704244&amp;width=400" alt="New Markdowns" srcset="//www.bostonproper.com/cdn/shop/files/Image_b520536c-2111-43e4-b1e8-166793f8fe43.jpg?v=1790704244&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_b520536c-2111-43e4-b1e8-166793f8fe43.jpg?v=1790704244&amp;width=400 400w" width="400" height="500" loading="lazy">
13118</div>
13119    <h4 class="bp-mega__promo-title">New Markdowns</h4><div class="bp-mega__promo-copy"><p>Rare finds.&nbsp;Newly reduced.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13120  </a>
13121</div>
13122
13123<div class="bp-mega__promo">
13124  <a href="/collections/clearance" class="bp-mega__promo-link">
13125    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image-1.jpg?v=1790780282&amp;width=400" alt="Clearance" srcset="//www.bostonproper.com/cdn/shop/files/Image-1.jpg?v=1790780282&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image-1.jpg?v=1790780282&amp;width=400 400w" width="400" height="500" loading="lazy">
13126</div>
13127    <h4 class="bp-mega__promo-title">Clearance</h4><div class="bp-mega__promo-copy"><p>Your size won’t stay here long.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13128  </a>
13129</div>
13130
13131</div></section></li>
13132
13133
13134
13135<li
13136  role="presentation"
13137  class="menu-list__list-item bp-menu-item-li"
13138  data-bp-menu-item
13139  
13140><a
13141      href="/blogs/styleedit"
13142      data-skip-node-update="true"
13143      class="menu-list__link"
13144      aria-controls="bp-submenu-ATVRxYnVkRFJjc0I3R__bp_menu_styleedit-1"
13145      aria-haspopup="true"
13146      aria-expanded="false"
13147      ref="menuitem"
13148    >
13149      <span class="menu-list__link-title">styleEDIT</span>
13150    </a>
13151    <div class="bp-mega-submenu" id="bp-submenu-ATVRxYnVkRFJjc0I3R__bp_menu_styleedit-1">
13152      <div class="bp-mega-submenu__inner">
13153        <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column">
13154                  <p class="bp-mega__heading"><a href="/blogs/styleedit">styleEDIT: What's New</a></p><ul class="bp-mega__links"><li><a href="/pages/new-to-boston-proper">New to Boston Proper? Start Here</a></li><li><a href="/blogs/styleedit/defy-all-expectations-why-style-doesn-t-expire-it-evolves">Why Style Doesn't Expire. It Evolves.</a></li><li><a href="https://www.bostonproper.com/blogs/styleedit/denim-dresses-are-back-here-s-how-to-wear-them-now">How to Wear Denim Dresses</a></li><li><a href="/blogs/styleedit">Read All</a></li></ul></div><div class="bp-mega__column">
13155                  <p class="bp-mega__heading"><a href="/collections/new-arrivals">Trending Now</a></p><ul class="bp-mega__links"><li><a href="/collections/featured-shop-animal-prints">Animal Prints</a></li><li><a href="/collections/featured-shops-matching-sets">Matching Sets</a></li><li><a href="/collections/color-crush-wine">Trending Color: Wine</a></li><li><a href="/collections/featured-shop-intricate-details">Intricate Details</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li></ul></div><div class="bp-mega__column">
13156                  <p class="bp-mega__heading"><a href="/blogs/styleedit">Discover</a></p><ul class="bp-mega__links"><li><a href="/pages/behind-the-seams">Behind the Seams</a></li><li><a href="/pages/sheryls-loves">Sheryl's Loves</a></li><li><a href="/pages/digital-catalog">Digital Catalog</a></li></ul></div></div><div class="bp-mega__promos"><div class="bp-mega__promo">
13157  <a href="/pages/sheryls-loves" class="bp-mega__promo-link">
13158    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_65.jpg?v=1790780283&amp;width=400" alt="Sheryl’s Loves" srcset="//www.bostonproper.com/cdn/shop/files/Image_65.jpg?v=1790780283&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_65.jpg?v=1790780283&amp;width=400 400w" width="400" height="500" loading="lazy">
13159</div>
13160    <h4 class="bp-mega__promo-title">Sheryl’s Loves</h4><div class="bp-mega__promo-copy"><p>“These pieces feel so me. Feminine, confident, and exactly how I want to show up right now.”&nbsp;
—Sheryl, Editor-in-Chic&nbsp;</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13161  </a>
13162</div>
13163
13164<div class="bp-mega__promo">
13165  <a href="/pages/digital-catalog" class="bp-mega__promo-link">
13166    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_75.jpg?v=1790800820&amp;width=400" alt="Digital Catalog" srcset="//www.bostonproper.com/cdn/shop/files/Image_75.jpg?v=1790800820&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_75.jpg?v=1790800820&amp;width=400 400w" width="400" height="500" loading="lazy">
13167</div>
13168    <h4 class="bp-mega__promo-title">Digital Catalog</h4><div class="bp-mega__promo-copy"><p>Turn the page. Your best style era starts here.&nbsp;</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13169  </a>
13170</div>
13171
13172</div></div>
13173      </div>
13174    </div></li><li class="bp-mm-item" data-bp-mm-id="ATVRxYnVkRFJjc0I3R__bp_menu_styleedit-1"><button type="button" class="bp-mm-item__row" data-open-view="ATVRxYnVkRFJjc0I3R__bp_menu_styleedit-1">
13175      <span class="bp-mm-item__label">styleEDIT</span>
13176      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13177  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13178</svg>
13179</span>
13180    </button>
13181
13182    <section class="bp-mm-view" data-view="ATVRxYnVkRFJjc0I3R__bp_menu_styleedit-1" hidden>
13183      <header class="bp-mm-view__header">
13184        <button type="button" class="bp-mm-view__back" data-back>
13185          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13186  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13187</svg>
13188</span>
13189          <span>styleEDIT</span>
13190        </button>
13191        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13192  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13193  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13194</svg>
13195</button>
13196      </header><div class="bp-mm-view__sections"><section class="bp-mm-section">
13197              <p class="bp-mm-section__heading"><a href="/blogs/styleedit">styleEDIT: What's New</a></p><ul class="bp-mm-section__links"><li><a href="/pages/new-to-boston-proper">New to Boston Proper? Start Here</a></li><li><a href="/blogs/styleedit/defy-all-expectations-why-style-doesn-t-expire-it-evolves">Why Style Doesn't Expire. It Evolves.</a></li><li><a href="https://www.bostonproper.com/blogs/styleedit/denim-dresses-are-back-here-s-how-to-wear-them-now">How to Wear Denim Dresses</a></li><li><a href="/blogs/styleedit">Read All</a></li></ul></section><section class="bp-mm-section">
13198              <p class="bp-mm-section__heading"><a href="/collections/new-arrivals">Trending Now</a></p><ul class="bp-mm-section__links"><li><a href="/collections/featured-shop-animal-prints">Animal Prints</a></li><li><a href="/collections/featured-shops-matching-sets">Matching Sets</a></li><li><a href="/collections/color-crush-wine">Trending Color: Wine</a></li><li><a href="/collections/featured-shop-intricate-details">Intricate Details</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li></ul></section><section class="bp-mm-section">
13199              <p class="bp-mm-section__heading"><a href="/blogs/styleedit">Discover</a></p><ul class="bp-mm-section__links"><li><a href="/pages/behind-the-seams">Behind the Seams</a></li><li><a href="/pages/sheryls-loves">Sheryl's Loves</a></li><li><a href="/pages/digital-catalog">Digital Catalog</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo">
13200  <a href="/pages/sheryls-loves" class="bp-mega__promo-link">
13201    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_65.jpg?v=1790780283&amp;width=400" alt="Sheryl’s Loves" srcset="//www.bostonproper.com/cdn/shop/files/Image_65.jpg?v=1790780283&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_65.jpg?v=1790780283&amp;width=400 400w" width="400" height="500" loading="lazy">
13202</div>
13203    <h4 class="bp-mega__promo-title">Sheryl’s Loves</h4><div class="bp-mega__promo-copy"><p>“These pieces feel so me. Feminine, confident, and exactly how I want to show up right now.”&nbsp;
—Sheryl, Editor-in-Chic&nbsp;</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13204  </a>
13205</div>
13206
13207<div class="bp-mega__promo">
13208  <a href="/pages/digital-catalog" class="bp-mega__promo-link">
13209    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_75.jpg?v=1790800820&amp;width=400" alt="Digital Catalog" srcset="//www.bostonproper.com/cdn/shop/files/Image_75.jpg?v=1790800820&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_75.jpg?v=1790800820&amp;width=400 400w" width="400" height="500" loading="lazy">
13210</div>
13211    <h4 class="bp-mega__promo-title">Digital Catalog</h4><div class="bp-mega__promo-copy"><p>Turn the page. Your best style era starts here.&nbsp;</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13212  </a>
13213</div>
13214
13215</div></section></li>
13216
13217
13218
13219<li
13220  role="presentation"
13221  class="menu-list__list-item bp-menu-item-li"
13222  data-bp-menu-item
13223  
13224><a
13225      href="/collections/brands-we-love"
13226      data-skip-node-update="true"
13227      class="menu-list__link"
13228      aria-controls="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1"
13229      aria-haspopup="true"
13230      aria-expanded="false"
13231      ref="menuitem"
13232    >
13233      <span class="menu-list__link-title">Brands We Love</span>
13234    </a>
13235    <div class="bp-mega-submenu" id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1">
13236      <div class="bp-mega-submenu__inner">
13237        <div class="bp-mega bp-mega--tabs-promos"><div class="bp-mega__tabs" data-bp-mega-tabs data-bp-tab-columns="2">
13238              <ul class="bp-mega__tabs-list" role="tablist"><li role="presentation">
13239                    <button
13240                      type="button"
13241                      role="tab"
13242                      id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-tab-0"
13243                      class="bp-mega__tab is-active"
13244                      aria-controls="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-panel-0"
13245                      aria-selected="true"
13246                      data-bp-mega-tab
13247                    >
13248                      <span class="bp-mega__tab-label">BRANDS WE LOVE</span>
13249                      <span class="bp-mega__tab-chevron" aria-hidden="true">
13250                        <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
13251                          <path d="M23.8674 11.8674C23.9116 11.8244 23.9558 11.7814 24 11.7385C24.0872 11.8256 24.1744 11.9128 24.2615 12C24.2186 12.0442 24.1756 12.0884 24.1326 12.1326C23.8696 12.4029 23.6066 12.6733 23.3436 12.9436C20.9768 15.3768 18.6099 17.8099 16.2431 20.2431V19.7569C18.6762 22.1238 21.1094 24.4906 23.5425 26.8575C23.8129 27.1205 24.0832 27.3835 24.3536 27.6464C24.473 27.7627 24.5925 27.8789 24.712 27.9951C24.473 28.2341 24.2341 28.473 23.9951 28.712C23.8789 28.5925 23.7627 28.473 23.6464 28.3536C23.3835 28.0832 23.1205 27.8129 22.8575 27.5425C20.4906 25.1094 18.1238 22.6762 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1901 17.3901 20.6232 15.0232 23.0564 12.6564C23.3267 12.3934 23.5971 12.1304 23.8674 11.8674Z" fill="currentColor"/>
13252                          <path d="M23.6464 11.6464C23.7627 11.527 23.8789 11.4075 23.9951 11.288C24.2341 11.527 24.473 11.7659 24.712 12.0049C24.5925 12.1211 24.473 12.2373 24.3536 12.3536C24.0832 12.6165 23.8129 12.8795 23.5425 13.1425C21.1094 15.5094 18.6762 17.8762 16.2431 20.2431V19.7569C18.6099 22.1901 20.9768 24.6232 23.3436 27.0564C23.6066 27.3267 23.8696 27.5971 24.1326 27.8674C24.1756 27.9116 24.2186 27.9558 24.2615 28C24.1744 28.0872 24.0872 28.1744 24 28.2615C23.9558 28.2186 23.9116 28.1756 23.8674 28.1326C23.5971 27.8696 23.3267 27.6066 23.0564 27.3436C20.6232 24.9768 18.1901 22.6099 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1238 17.3238 20.4906 14.8906 22.8575 12.4575C23.1205 12.1871 23.3835 11.9168 23.6464 11.6464Z" fill="currentColor"/>
13253                        </svg>
13254                      </span>
13255                    </button>
13256                  </li><li role="presentation">
13257                    <button
13258                      type="button"
13259                      role="tab"
13260                      id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-tab-1"
13261                      class="bp-mega__tab"
13262                      aria-controls="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-panel-1"
13263                      aria-selected="false"
13264                      data-bp-mega-tab
13265                    >
13266                      <span class="bp-mega__tab-label">JEWELRY & ACCESSORIES</span>
13267                      <span class="bp-mega__tab-chevron" aria-hidden="true">
13268                        <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
13269                          <path d="M23.8674 11.8674C23.9116 11.8244 23.9558 11.7814 24 11.7385C24.0872 11.8256 24.1744 11.9128 24.2615 12C24.2186 12.0442 24.1756 12.0884 24.1326 12.1326C23.8696 12.4029 23.6066 12.6733 23.3436 12.9436C20.9768 15.3768 18.6099 17.8099 16.2431 20.2431V19.7569C18.6762 22.1238 21.1094 24.4906 23.5425 26.8575C23.8129 27.1205 24.0832 27.3835 24.3536 27.6464C24.473 27.7627 24.5925 27.8789 24.712 27.9951C24.473 28.2341 24.2341 28.473 23.9951 28.712C23.8789 28.5925 23.7627 28.473 23.6464 28.3536C23.3835 28.0832 23.1205 27.8129 22.8575 27.5425C20.4906 25.1094 18.1238 22.6762 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1901 17.3901 20.6232 15.0232 23.0564 12.6564C23.3267 12.3934 23.5971 12.1304 23.8674 11.8674Z" fill="currentColor"/>
13270                          <path d="M23.6464 11.6464C23.7627 11.527 23.8789 11.4075 23.9951 11.288C24.2341 11.527 24.473 11.7659 24.712 12.0049C24.5925 12.1211 24.473 12.2373 24.3536 12.3536C24.0832 12.6165 23.8129 12.8795 23.5425 13.1425C21.1094 15.5094 18.6762 17.8762 16.2431 20.2431V19.7569C18.6099 22.1901 20.9768 24.6232 23.3436 27.0564C23.6066 27.3267 23.8696 27.5971 24.1326 27.8674C24.1756 27.9116 24.2186 27.9558 24.2615 28C24.1744 28.0872 24.0872 28.1744 24 28.2615C23.9558 28.2186 23.9116 28.1756 23.8674 28.1326C23.5971 27.8696 23.3267 27.6066 23.0564 27.3436C20.6232 24.9768 18.1901 22.6099 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1238 17.3238 20.4906 14.8906 22.8575 12.4575C23.1205 12.1871 23.3835 11.9168 23.6464 11.6464Z" fill="currentColor"/>
13271                        </svg>
13272                      </span>
13273                    </button>
13274                  </li><li role="presentation">
13275                    <button
13276                      type="button"
13277                      role="tab"
13278                      id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-tab-2"
13279                      class="bp-mega__tab"
13280                      aria-controls="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-panel-2"
13281                      aria-selected="false"
13282                      data-bp-mega-tab
13283                    >
13284                      <span class="bp-mega__tab-label">ATHLEISURE</span>
13285                      <span class="bp-mega__tab-chevron" aria-hidden="true">
13286                        <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
13287                          <path d="M23.8674 11.8674C23.9116 11.8244 23.9558 11.7814 24 11.7385C24.0872 11.8256 24.1744 11.9128 24.2615 12C24.2186 12.0442 24.1756 12.0884 24.1326 12.1326C23.8696 12.4029 23.6066 12.6733 23.3436 12.9436C20.9768 15.3768 18.6099 17.8099 16.2431 20.2431V19.7569C18.6762 22.1238 21.1094 24.4906 23.5425 26.8575C23.8129 27.1205 24.0832 27.3835 24.3536 27.6464C24.473 27.7627 24.5925 27.8789 24.712 27.9951C24.473 28.2341 24.2341 28.473 23.9951 28.712C23.8789 28.5925 23.7627 28.473 23.6464 28.3536C23.3835 28.0832 23.1205 27.8129 22.8575 27.5425C20.4906 25.1094 18.1238 22.6762 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1901 17.3901 20.6232 15.0232 23.0564 12.6564C23.3267 12.3934 23.5971 12.1304 23.8674 11.8674Z" fill="currentColor"/>
13288                          <path d="M23.6464 11.6464C23.7627 11.527 23.8789 11.4075 23.9951 11.288C24.2341 11.527 24.473 11.7659 24.712 12.0049C24.5925 12.1211 24.473 12.2373 24.3536 12.3536C24.0832 12.6165 23.8129 12.8795 23.5425 13.1425C21.1094 15.5094 18.6762 17.8762 16.2431 20.2431V19.7569C18.6099 22.1901 20.9768 24.6232 23.3436 27.0564C23.6066 27.3267 23.8696 27.5971 24.1326 27.8674C24.1756 27.9116 24.2186 27.9558 24.2615 28C24.1744 28.0872 24.0872 28.1744 24 28.2615C23.9558 28.2186 23.9116 28.1756 23.8674 28.1326C23.5971 27.8696 23.3267 27.6066 23.0564 27.3436C20.6232 24.9768 18.1901 22.6099 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1238 17.3238 20.4906 14.8906 22.8575 12.4575C23.1205 12.1871 23.3835 11.9168 23.6464 11.6464Z" fill="currentColor"/>
13289                        </svg>
13290                      </span>
13291                    </button>
13292                  </li><li role="presentation">
13293                    <button
13294                      type="button"
13295                      role="tab"
13296                      id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-tab-3"
13297                      class="bp-mega__tab"
13298                      aria-controls="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-panel-3"
13299                      aria-selected="false"
13300                      data-bp-mega-tab
13301                    >
13302                      <span class="bp-mega__tab-label">HEALTH & BEAUTY</span>
13303                      <span class="bp-mega__tab-chevron" aria-hidden="true">
13304                        <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
13305                          <path d="M23.8674 11.8674C23.9116 11.8244 23.9558 11.7814 24 11.7385C24.0872 11.8256 24.1744 11.9128 24.2615 12C24.2186 12.0442 24.1756 12.0884 24.1326 12.1326C23.8696 12.4029 23.6066 12.6733 23.3436 12.9436C20.9768 15.3768 18.6099 17.8099 16.2431 20.2431V19.7569C18.6762 22.1238 21.1094 24.4906 23.5425 26.8575C23.8129 27.1205 24.0832 27.3835 24.3536 27.6464C24.473 27.7627 24.5925 27.8789 24.712 27.9951C24.473 28.2341 24.2341 28.473 23.9951 28.712C23.8789 28.5925 23.7627 28.473 23.6464 28.3536C23.3835 28.0832 23.1205 27.8129 22.8575 27.5425C20.4906 25.1094 18.1238 22.6762 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1901 17.3901 20.6232 15.0232 23.0564 12.6564C23.3267 12.3934 23.5971 12.1304 23.8674 11.8674Z" fill="currentColor"/>
13306                          <path d="M23.6464 11.6464C23.7627 11.527 23.8789 11.4075 23.9951 11.288C24.2341 11.527 24.473 11.7659 24.712 12.0049C24.5925 12.1211 24.473 12.2373 24.3536 12.3536C24.0832 12.6165 23.8129 12.8795 23.5425 13.1425C21.1094 15.5094 18.6762 17.8762 16.2431 20.2431V19.7569C18.6099 22.1901 20.9768 24.6232 23.3436 27.0564C23.6066 27.3267 23.8696 27.5971 24.1326 27.8674C24.1756 27.9116 24.2186 27.9558 24.2615 28C24.1744 28.0872 24.0872 28.1744 24 28.2615C23.9558 28.2186 23.9116 28.1756 23.8674 28.1326C23.5971 27.8696 23.3267 27.6066 23.0564 27.3436C20.6232 24.9768 18.1901 22.6099 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1238 17.3238 20.4906 14.8906 22.8575 12.4575C23.1205 12.1871 23.3835 11.9168 23.6464 11.6464Z" fill="currentColor"/>
13307                        </svg>
13308                      </span>
13309                    </button>
13310                  </li></ul>
13311
13312              <div class="bp-mega__tabs-panels"><div
13313                    id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-panel-0"
13314                    role="tabpanel"
13315                    aria-labelledby="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-tab-0"
13316                    class="bp-mega__tab-panel is-active"
13317                    data-bp-mega-panel
13318                    
13319                  >
13320                    <p class="bp-mega__heading"><a href="/pages/brands-we-love">BRANDS WE LOVE</a></p><ul class="bp-mega__links"><li><a href="/pages/brands-we-love">View All Brands</a></li><li><a href="/collections/all-brands-we-love">Shop All</a></li><li><a href="/collections/brands-we-love-amsterdam-heritage">Amsterdam Heritage</a></li><li><a href="/collections/brands-we-love-a-rose">A.Rose</a></li><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-anatomie">Anatomie</a></li><li><a href="/collections/brands-we-love-becca">Becca By Rebecca Virtue</a></li><li><a href="/collections/brands-we-love-carmen-marc-valvo">Carmen Marc Valvo</a></li><li><a href="/collections/brands-we-love-change-of-scenery">
13320Change of Scenery</a></li><li><a href="/collections/brands-we-love-ettika">Ettika</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-hanky-panky">Hanky Panky</a></li><li><a href="/collections/brands-we-love-hat-attack-new-york">Hat Attack</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-mdaire">MDAiRE</a></li><li><a href="/collections/brands-we-love-miami-chains-co">Miami Chains & Co.</a></li><li><a href="/collections/brands-we-love-mimosa-lane">Mimosa Lane</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini x Boston Proper</a></li><li><a href="/collections/brands-we-love-prolon-life">Prolon Life</a></li><li><a href="/collections/brands-we-love-pq-swim">PQ Swim X Boston Proper</a></li><li><a href="/collections/brands-we-love-saint-jo">Saint Jō</a></li><li><a href="/collections/brands-we-love-st-moran">St. Moran</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li><li><a href="/collections/brands-we-love-the-sak">The Sak</a></li><li><a href="/collections/brands-we-love-t-jazelle">T. Jazelle</a></li><li><a href="/collections/brands-we-love-trina-turk">Trina Turk</a></li><li><a href="/collections/brands-we-love-walter-baker">Walter Baker</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></div><div
13321                    id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-panel-1"
13322                    role="tabpanel"
13323                    aria-labelledby="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-tab-1"
13324                    class="bp-mega__tab-panel"
13325                    data-bp-mega-panel
13326                    hidden
13327                  >
13328                    <p class="bp-mega__heading"><a href="/collections/brands-we-love-jewelry">JEWELRY & ACCESSORIES</a></p><ul class="bp-mega__links"><li><a href="/collections/brands-we-love-jewelry">Shop All</a></li><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-amsterdam-heritage">Amsterdam Heritage</a></li><li><a href="/collections/brands-we-love-ettika">Ettika</a></li><li><a href="/collections/brands-we-love-st-moran">St. Moran</a></li><li><a href="/collections/brands-we-love-t-jazelle">T. Jazelle</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-hat-attack-new-york">Hat Attack</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-miami-chains-co">Miami Chains & Co.</a></li><li><a href="/collections/brands-we-love-the-sak">The Sak</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></div><div
13329                    id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-panel-2"
13330                    role="tabpanel"
13331                    aria-labelledby="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-tab-2"
13332                    class="bp-mega__tab-panel"
13333                    data-bp-mega-panel
13334                    hidden
13335                  >
13336                    <p class="bp-mega__heading"><a href="/collections/all-brands-we-love">ATHLEISURE</a></p><ul class="bp-mega__links"><li><a href="/collections/brands-we-love-anatomie">Anatomie</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini X Boston Proper</a></li></ul></div><div
13337                    id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-panel-3"
13338                    role="tabpanel"
13339                    aria-labelledby="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-1-tab-3"
13340                    class="bp-mega__tab-panel"
13341                    data-bp-mega-panel
13342                    hidden
13343                  >
13344                    <p class="bp-mega__heading"><a href="/collections/brands-we-love-health-and-beauty">HEALTH & BEAUTY</a></p><ul class="bp-mega__links"><li><a href="/collections/brands-we-love-health-and-beauty">Shop All</a></li><li><a href="/collections/brands-we-love-mdaire">MDAiRE</a></li><li><a href="/collections/brands-we-love-mimosa-lane">Mimosa Lane</a></li><li><a href="/collections/brands-we-love-prolon-life">Prolon Life</a></li><li><a href="/collections/brands-we-love-saint-jo">SAINT Jō</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li></ul></div></div><div class="bp-mega__promos bp-mega__promos--tabs"><div class="bp-mega__promo">
13345  <a href="/collections/brands-we-love-ettika" class="bp-mega__promo-link">
13346    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&amp;width=400" alt="Ettika" srcset="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&amp;width=400 400w" width="400" height="625" loading="lazy">
13347</div>
13348    <h4 class="bp-mega__promo-title">Ettika</h4><span class="bp-mega__promo-cta">Shop Now</span>
13349  </a>
13350</div>
13351
13352<div class="bp-mega__promo">
13353  <a href="/collections/brands-we-love-saint-jo" class="bp-mega__promo-link">
13354    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&amp;width=400" alt="SAINT Jō" srcset="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&amp;width=400 400w" width="400" height="501" loading="lazy" style="object-position:50.0% 75.781%;">
13355</div>
13356    <h4 class="bp-mega__promo-title">SAINT Jō</h4><span class="bp-mega__promo-cta">Shop Now</span>
13357  </a>
13358</div>
13359
13360</div></div></div>
13361      </div>
13362    </div></li><li class="bp-mm-item" data-bp-mm-id="AUm5TVW95VENzMmkzb__bp_menu_brands-1"><button type="button" class="bp-mm-item__row" data-open-view="AUm5TVW95VENzMmkzb__bp_menu_brands-1">
13363      <span class="bp-mm-item__label">Brands We Love</span>
13364      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13365  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13366</svg>
13367</span>
13368    </button>
13369
13370    <section class="bp-mm-view" data-view="AUm5TVW95VENzMmkzb__bp_menu_brands-1" hidden>
13371      <header class="bp-mm-view__header">
13372        <button type="button" class="bp-mm-view__back" data-back>
13373          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13374  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13375</svg>
13376</span>
13377          <span>Brands We Love</span>
13378        </button>
13379        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13380  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13381  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13382</svg>
13383</button>
13384      </header><div class="bp-mm-view__sections"><section class="bp-mm-section">
13385              <p class="bp-mm-section__heading"><a href="/pages/brands-we-love">BRANDS WE LOVE</a></p><ul class="bp-mm-section__links"><li><a href="/pages/brands-we-love">View All Brands</a></li><li><a href="/collections/all-brands-we-love">Shop All</a></li><li><a href="/collections/brands-we-love-amsterdam-heritage">Amsterdam Heritage</a></li><li><a href="/collections/brands-we-love-a-rose">A.Rose</a></li><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-anatomie">Anatomie</a></li><li><a href="/collections/brands-we-love-becca">Becca By Rebecca Virtue</a></li><li><a href="/collections/brands-we-love-carmen-marc-valvo">Carmen Marc Valvo</a></li><li><a href="/collections/brands-we-love-change-of-scenery">Change of Scenery</a></li><li><a href="/collections/brands-we-love-ettika">Ettika</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-hanky-panky">Hanky Panky</a></li><li><a href="/collections/brands-we-love-hat-attack-new-york">Hat Attack</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-mdaire">MDAiRE</a></li><li><a href="/collections/brands-we-love-miami-chains-co">Miami Chains & Co.</a></li><li><a href="/collections/brands-we-love-mimosa-lane">Mimosa Lane</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini x Boston Proper</a></li><li><a href="/collections/brands-we-love-prolon-life">Prolon Life</a></li><li><a href="/collections/brands-we-love-pq-swim">PQ Swim X Boston Proper</a></li><li><a href="/collections/brands-we-love-saint-jo">Saint Jō</a></li><li><a href="/collections/brands-we-love-st-moran">St. Moran</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li><li><a href="/collections/brands-we-love-the-sak">The Sak</a></li><li><a href="/collections/brands-we-love-t-jazelle">T. Jazelle</a></li><li><a href="/collections/brands-we-love-trina-turk">Trina Turk</a></li><li><a href="/collections/brands-we-love-walter-baker">Walter Baker</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></section><section class="bp-mm-section">
13386              <p class="bp-mm-section__heading"><a href="/collections/brands-we-love-jewelry">JEWELRY & ACCESSORIES</a></p><ul class="bp-mm-section__links"><li><a href="/collections/brands-we-love-jewelry">Shop All</a></li><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-amsterdam-heritage">Amsterdam Heritage</a></li><li><a href="/collections/brands-we-love-ettika">Ettika</a></li><li><a href="/collections/brands-we-love-st-moran">St. Moran</a></li><li><a href="/collections/brands-we-love-t-jazelle">T. Jazelle</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-hat-attack-new-york">Hat Attack</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-miami-chains-co">Miami Chains & Co.</a></li><li><a href="/collections/brands-we-love-the-sak">The Sak</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></section><section class="bp-mm-section">
13387              <p class="bp-mm-section__heading"><a href="/collections/all-brands-we-love">ATHLEISURE</a></p><ul class="bp-mm-section__links"><li><a href="/collections/brands-we-love-anatomie">Anatomie</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini X Boston Proper</a></li></ul></section><section class="bp-mm-section">
13388              <p class="bp-mm-section__heading"><a href="/collections/brands-we-love-health-and-beauty">HEALTH & BEAUTY</a></p><ul class="bp-mm-section__links"><li><a href="/collections/brands-we-love-health-and-beauty">Shop All</a></li><li><a href="/collections/brands-we-love-mdaire">MDAiRE</a></li><li><a href="/collections/brands-we-love-mimosa-lane">Mimosa Lane</a></li><li><a href="/collections/brands-we-love-prolon-life">Prolon Life</a></li><li><a href="/collections/brands-we-love-saint-jo">SAINT Jō</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo">
13389  <a href="/collections/brands-we-love-ettika" class="bp-mega__promo-link">
13390    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&amp;width=400" alt="Ettika" srcset="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&amp;width=400 400w" width="400" height="625" loading="lazy">
13391</div>
13392    <h4 class="bp-mega__promo-title">Ettika</h4><span class="bp-mega__promo-cta">Shop Now</span>
13393  </a>
13394</div>
13395
13396<div class="bp-mega__promo">
13397  <a href="/collections/brands-we-love-saint-jo" class="bp-mega__promo-link">
13398    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&amp;width=400" alt="SAINT Jō" srcset="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&amp;width=400 400w" width="400" height="501" loading="lazy" style="object-position:50.0% 75.781%;">
13399</div>
13400    <h4 class="bp-mega__promo-title">SAINT Jō</h4><span class="bp-mega__promo-cta">Shop Now</span>
13401  </a>
13402</div>
13403
13404</div></section></li>
13405
13406
13407
13408
13409
13410              </ul>
13411
13412              <ul class="bp-mobile-drawer__rail">
13413                <li>
13414                  <a class="bp-mobile-drawer__rail-link" href="/account">
13415                    <span class="bp-mobile-drawer__rail-icon" aria-hidden="true"><svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
13416<path d="M16.2227 15.2379C16.2134 12.9677 17.7898 11.0652 19.936 10.3449C23.4796 9.10175 27.7591 11.331 27.7783 15.2379C27.7587 19.1448 23.4796 21.374 19.936 20.1309C17.7903 19.4105 16.2134 17.5081 16.2227 15.2379ZM18.0005 15.2379C17.992 16.8309 18.828 18.4907 20.3231 19.2146C21.3583 19.7286 22.6431 19.7286 23.6783 19.2146C25.1729 18.4907 26.0094 16.8309 26.0009 15.2379C26.0094 13.6448 25.1734 11.985 23.6783 11.2612C22.6431 10.7472 21.3583 10.7472 20.3231 11.2612C18.8285 11.985 17.992 13.6448 18.0005 15.2379Z" fill="currentColor"/>
13417<path d="M12 34C12.28 29.7933 13.4618 25.0731 17.7702 23.2244C19.1058 22.6506 20.5636 22.4433 22 22.4372C24.3076 22.4241 26.7129 23.0455 28.4364 24.6324C29.9582 26.0034 30.8698 27.9263 31.3693 29.8649C31.6809 31.0482 31.8529 32.2665 31.9596 33.4808C31.972 33.6536 31.9853 33.8268 32 34H29.7778C29.7956 33.733 29.8182 33.3246 29.824 33.051C29.8591 30.5425 29.4138 27.8399 27.6716 25.9069C26.6804 24.8318 25.348 24.1738 23.8938 23.9146C22.0573 23.6027 20.0453 23.6973 18.336 24.4605C17.4333 24.8698 16.6467 25.4863 16.0364 26.2503L15.9004 26.431C15.784 26.5771 15.6858 26.7421 15.5796 26.8965C15.5347 26.9698 15.4516 27.1186 15.408 27.191C15.3351 27.308 15.2636 27.4738 15.1973 27.5951C14.3849 29.2863 14.1489 31.1922 14.176 33.0514C14.1871 33.3176 14.1987 33.7352 14.2222 34.0004H12V34Z" fill="currentColor"/>
13418</svg>
13419</span>
13420                    <span>Login</span>
13421                  </a>
13422                </li>
13423                <li>
13424                  <a class="bp-mobile-drawer__rail-link" href="/pages/favorites">
13425                    <span class="bp-mobile-drawer__rail-icon" aria-hidden="true"><svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
13426<path d="M22.1364 34C22.0452 33.9982 21.9449 33.964 21.8658 33.9141L21.8316 33.8952L21.7642 33.8575C21.4558 33.6826 21.1514 33.4983 20.8515 33.3099C15.6957 30.0059 10.1181 24.467 10.0003 17.9623C9.97376 14.3139 11.7681 10.6318 15.693 10.0815C16.2307 10.0038 16.7679 9.98353 17.311 10.0127C19.188 10.1018 20.6434 11.2765 21.4931 12.8915C21.8946 13.6378 22.1791 14.4241 22.3608 15.2504L21.9202 14.8926H22.3527L21.9121 15.2504C22.0937 14.4245 22.3783 13.6378 22.7802 12.8919C23.393 11.7378 24.3673 10.7119 25.6338 10.2771C26.372 10.011 27.1588 9.97409 27.9316 10.0163C28.1434 10.0262 28.37 10.0537 28.5804 10.0829C32.3843 10.6147 34.184 14.0775 34.273 17.6341C34.3472 24.275 28.6604 29.9519 23.4218 33.3094C23.1646 33.4704 22.9057 33.6291 22.6427 33.7815L22.5096 33.857L22.4422 33.8948C22.3527 33.951 22.2416 33.9955 22.1373 33.9995L22.1364 34ZM22.1364 33.1008C22.0735 33.0891 21.9665 33.1211 21.9359 33.1426L21.9431 33.1377C21.9728 33.1175 22.0982 33.0248 22.1333 32.9997C27.2231 29.1984 33.9673 22.4766 32.1775 15.5337C31.6438 13.4328 30.4057 11.8228 28.2045 11.3727C27.4753 11.2325 26.6975 11.1511 25.975 11.3507C24.5561 11.732 23.6255 13.0434 23.1179 14.3621C22.9371 14.8166 22.8113 15.3147 22.7164 15.7926H22.3527C22.1558 15.7926 21.7525 15.7926 21.5569 15.7926C21.4621 15.3152 21.3362 14.8166 21.155 14.3621C20.3821 12.3938 18.9893 10.9663 16.7391 11.2711C15.8701 11.3597 14.9934 11.6223 14.2727 12.1182C12.8008 13.1113 12.1241 14.893 11.8872 16.596C10.9885 23.1456 17.307 29.3895 22.14 32.9997L22.2574 33.0855L22.3158 33.1278L22.3446 33.1485L22.3518 33.1534C22.3482 33.1521 22.3738 33.166 22.3316 33.1426C22.274 33.1125 22.2007 33.0972 22.1373 33.1017L22.1364 33.1008Z" fill="currentColor"/>
13427</svg>
13428</span>
13429                    <span>Favorites</span>
13430                  </a>
13431                </li>
13432              </ul>
13433            </section>
13434          </div>
13435
13436          <div class="bp-mobile-drawer__backdrop" data-close></div>
13437        </details>
13438      </bp-mobile-drawer>
13438<script type="module">
13439  if (!customElements.get('bp-mobile-drawer')) {
13440    class BPMobileDrawer extends HTMLElement {
13441      connectedCallback() {
13442        // a11y: mark the panel as a modal dialog with an accessible name.
13443        const panel = this.querySelector('.bp-mobile-drawer__panel');
13444        if (panel) {
13445          panel.setAttribute('role', 'dialog');
13446          panel.setAttribute('aria-modal', 'true');
13447          if (!panel.hasAttribute('aria-label')) panel.setAttribute('aria-label', 'Menu');
13448          panel.tabIndex = -1;
13449          // Move the sub-views to be DIRECT children of the panel. They
13450          // render nested inside the scrolling root <section> (as siblings
13451          // of their .bp-mm-item opener); as a direct panel child a
13452          // sub-view positions cleanly against the panel (full-width
13453          // overlay) and doesn't scroll with the root list. The opener
13454          // still targets it by data-view/data-open-view (block id), not
13455          // DOM nesting, so navigation is unaffected.
13456          panel.querySelectorAll('.bp-mm-view').forEach((view) => {
13457            if (view.parentElement !== panel) panel.appendChild(view);
13458          });
13459        }
13460        this.addEventListener('click', (e) => {
13461          const opener = e.target.closest('[data-open-view]');
13462          const back = e.target.closest('[data-back]');
13463          const close = e.target.closest('[data-close]');
13464          if (opener) { e.preventDefault(); this.showView(opener.dataset.openView); this._focusActiveView(); return; }
13465          if (back) { this.showView('root'); this._focusActiveView(); return; }
13466          if (close) { this.close(); return; }
13467        });
13468        const details = this.querySelector('details');
13469        this._summary = details?.querySelector('summary') || null;
13470        // a11y: Escape closes the drawer.
13471        this._onKeydown = (e) => {
13472          if (e.key === 'Escape' && this.querySelector('details')?.open) {
13473            e.preventDefault();
13474            this.close();
13475          }
13476        };
13477        details?.addEventListener('toggle', () => {
13478          if (details.open) this._onOpen();
13479          else this._onClose();
13480        });
13481      }
13482      _onOpen() {
13483        this.showView('root');
13484        document.documentElement.style.overflow = 'hidden';
13485        // a11y: make the rest of the page inert so focus + AT stay in the
13486        // drawer instead of tabbing into the hidden page behind it. Track
13487        // only the elements WE inert (skip any already inert from another
13488        // overlay) so _onClose doesn't un-inert something it didn't set.
13489        this._inerted = [];
13490        document.querySelectorAll('#MainContent, footer, .footer, .bp-footer').forEach((el) => {
13491          if (!el.hasAttribute('inert')) { el.setAttribute('inert', ''); this._inerted.push(el); }
13492        });
13493        document.addEventListener('keydown', this._onKeydown);
13494        const panel = this.querySelector('.bp-mobile-drawer__panel');
13495        requestAnimationFrame(() => {
13496          (panel?.querySelector('[data-close], a[href], button') || panel)?.focus();
13497        });
13498      }
13499      _onClose() {
13500        // Reset to the top-level nav so reopening never lands mid-sub-view.
13501        this.showView('root');
13502        document.documentElement.style.overflow = '';
13503        (this._inerted || []).forEach((el) => el.removeAttribute('inert'));
13504        this._inerted = [];
13505        document.removeEventListener('keydown', this._onKeydown);
13506        // a11y: return focus to the hamburger that opened the drawer.
13507        if (this._summary && typeof this._summary.focus === 'function') this._summary.focus();
13508      }
13509      // a11y: after a sub-view / Back navigation, move focus into the newly
13510      // active view — otherwise the inert we set on the outgoing view drops
13511      // focus to <body> (the opener/back button that was just focused is
13512      // inside the now-inert view).
13513      _focusActiveView() {
13514        const panel = this.querySelector('.bp-mobile-drawer__panel');
13515        if (!panel) return;
13516        const active = panel.querySelector('.bp-mm-view:not([hidden])')
13517          || panel.querySelector('.bp-mobile-drawer__view[data-view="root"]');
13518        if (!active) return;
13519        const target = active.querySelector('[data-back], a[href], button, [tabindex]:not
13519([tabindex="-1"])');
13520        requestAnimationFrame(() => { (target || panel).focus(); });
13521      }
13522      showView(name) {
13523        const panel = this.querySelector('.bp-mobile-drawer__panel');
13524        if (!panel) return;
13525        panel.dataset.activeView = name;
13526        // Simple in-place swap: exactly ONE view is shown at a time, filling
13527        // the whole panel at full width. The native `hidden` attribute both
13528        // removes the inactive views from layout AND drops them from the
13529        // focus order — so there's no overlay slide, no transform, and no
13530        // `inert` bookkeeping (all of which caused the side-by-side /
13531        // trapped-focus bugs). Root and every sub-view are position:absolute
13532        // inset:0 in the panel, so the shown one covers it completely.
13533        const root = this.querySelector('.bp-mobile-drawer__view[data-view="root"]');
13534        if (root) root.hidden = name !== 'root';
13535        this.querySelectorAll('.bp-mm-view').forEach((view) => {
13536          view.hidden = view.dataset.view !== name;
13537        });
13538        panel.scrollTop = 0;
13539      }
13540      close() {
13541        const details = this.querySelector('details');
13542        if (details) details.open = false;
13543      }
13544    }
13545    customElements.define('bp-mobile-drawer', BPMobileDrawer);
13546  }
13547</script>
13547
13548
13549
13550
13551    </div>
13552
13553  
13554
13555<style data-shopify>
13556  .header__underlay {
13557    --color-submenu: rgb(254 255 250 / 1.0);
13558  }
13559</style>
13560
13561
13562
13563
13564            
13565        
13566      
13567        
13568          
13569              
13570  <search-button
13571    class="search-action search-action--hidden-on-menu"
13572  >
13573    <button
13574      on:click="#search-modal/showDialog"
13575      class="button-unstyled header-actions__action"
13576      aria-label="Search"
13577      aria-haspopup="dialog"
13578    >
13579      <span class="hidden">
13580        Search
13581      </span>
13582
13583      <span class="svg-wrapper ">
13584        <svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
13585<path d="M30.6967 19.7055C30.7183 23.8405 27.932 27.3926 24.0949 28.7508C17.6703 31.1232 10.0267 26.8687 10 19.7055C10.0272 12.5414 17.6703 8.28779 24.0953 10.6602C27.932 12.0184 30.7187 15.5704 30.6967 19.7055ZM28.5408 19.7055C28.5477 16.9739 27.3344 14.2088 25.1509 12.5164C22.4003 10.326 18.2959 10.3256 15.5454 12.5164C13.3619 14.2088 12.1486 16.9735 12.1555 19.7055C12.1486 22.437 13.3619 25.2022 15.5454 26.8946C18.2959 29.085 22.4003 29.0854 25.1509 26.8946C27.3344 25.2022 28.5477 22.4374 28.5408 19.7055Z" fill="currentColor"/>
13586<path d="M33.1718 33.9998C31.5945 32.7679 30.2255 31.2984 28.9126 29.7966C28.4814 29.2934 28.0606 28.7816 27.6699 28.2439L28.9794 27.1216C29.4511 27.5898 29.8927 28.084 30.3238 28.5872C31.3971 29.854 32.4207 31.1661 33.3132 32.5696C33.4917 32.8528 33.6659 33.1396 33.8263 33.4388L33.1714 34.0002L33.1718 33.9998Z" fill="currentColor"/>
13587</svg>
13588
13589      </span>
13590    </button>
13591  </search-button>
13592
13593
13594
13595
13596            
13597        
13598      
13599        
13600          
13601              
13602
13603
13604
13605
13606<a
13607  
13608  href="/"
13609  class="size-style spacing-style header-logo"
13610  style="
13611    --size-style-width: ;--size-style-height: ;
13612    --padding-block-start: 0px;--padding-block-end: 0px;
13613    --font-family: var(--font-body--family);
13614    --font-style: var(--font-body--style);
13615    --font-weight: 600;
13616  "
13617  
13618>
13619  
13620
13621  <span
13622    class="header-logo__image-container header-logo__image-container--original"
13623    data-testid="header-logo"
13624  >
13625    
13626      
13627  
13628  
13629  
13630  
13631
13632  
13633
13634  
13635
13636  
13637
13638  <img src="//www.bostonproper.com/cdn/shop/files/BOS-Logotype-Charcoal_1.png?height=24&amp;v=1785187523" alt="Translation missing: en.Boston Proper accessibility.home" width="267" height="24" class="header-logo__image" srcset="//www.bostonproper.com/cdn/shop/files/BOS-Logotype-Charcoal_1.png?height=24&amp;v=1785187523 1x, //www.bostonproper.com/cdn/shop/files/BOS-Logotype-Charcoal_1.png?height=48&amp;v=1785187523 2x, //www.bostonproper.com/cdn/shop/files/BOS-Logotype-Charcoal_1.png?height=72&amp;v=1785187523 3x" style="object-position:3.613% 50.0%;--header-logo-image-width: 267px;--header-logo-image-width-mobile: 312px; --header-logo-image-height: 24px; --header-logo-image-height-mobile: 28px;">
13639
13640
13641    
13642  </span>
13643
13644  
13645
13646  
13647  <span
13648    class="header-logo__image-container header-logo__image-container--scroll"
13649    data-testid="header-logo-scroll"
13650  >
13651    
13652      <span
13653        class="header-logo__image header-logo__image--svg"
13654        role="img"
13655        aria-label="Translation missing: en.Boston Proper accessibility.home"
13656        style="--header-logo-image-height: 24px; --header-logo-image-height-mobile: 18px; --header-logo-image-width: 30px; --header-logo-image-width-mobile: 23px;"
13657      ><svg width="30" height="24" viewBox="0 0 30 24" fill="none" xmlns="http://www.w3.org/2000/svg">
13658<g clip-path="url(#clip0_152_25204)">
13659<g clip-path="url(#clip1_152_25204)">
13660<path d="M15 0C6.71573 0 0 6.83029 0 15.2558C0 18.509 1.00189 21.5238 2.70797 24H5.08833C3.0014 21.6099 1.92308 18.4465 1.92308 14.9768C1.92308 7.52731 7.77782 1.4884 15 1.4884C22.2222 1.4884 28.0769 7.52732 28.0769 14.9768C28.0769 18.4465 26.9986 21.6099 24.9117 24H27.2921C28.9981 21.5238 30 18.509 30 15.2558C30 6.83029 23.2843 0 15 0Z" fill="#171609"/>
13661<path d="M18.2832 13.1981C19.393 12.568 20.0718 11.4106 20.16 10.3019C20.3637 7.74079 18.2279 5.49321 15.0642 5.25773C11.9005 5.02219 9.43446 6.92717 9.23075 9.48835L8.0769 24H10.1923L11.3461 9.48835C11.5091 7.43939 12.8193 6.0236 15.0891 6.19257C17.1955 6.34941 18.2138 8.09599 18.0508 10.145C17.9311 11.6507 17.2051 12.6304 15.7692 13.3677C13.6619 14.4498 12.2037 15.6336 11.997 18.2326L11.5384 24H13.6538L14.1 18.3891C14.2996 15.8792 15.8461 13.9474 18.2092 14.1234C20.5723 14.2993 21.592 16.422 21.3923 18.9319C21.1927 21.4419 19.7263 23.0698 17.3816 23.0698L17.3077 24C21.25 24 23.2611 22.1112 23.5015 19.089C23.7396 16.0945 21.8614 13.509 18.2832 13.1981Z" fill="#171609"/>
13662</g>
13663</g>
13664<defs>
13665<clipPath id="clip0_152_25204">
13666<rect width="30" height="24" fill="white"/>
13667</clipPath>
13668<clipPath id="clip1_152_25204">
13669<rect width="30" height="24" fill="white"/>
13670</clipPath>
13671</defs>
13672</svg>
13673</span>
13674    
13675  </span>
13676</a>
13677
13678
13679
13680
13681
13682            
13683        
13684      
13685    </div><div
13686      class="header__column header__column--center"
13687      data-testid="header-top-center"
13688    >
13689      
13690        
13691          
13692              
13693
13694
13695    
13696
13697    
13698
13699    <header-menu
13700      ref="headerMenu"
13701      class="header-menu"
13702      
13703      data-hydration-key="header-menu"
13704    >
13705      <div class="header-menu__inner">
13706        <nav
13707          class="menu-list"
13708          aria-label="Primary"
13709          style="--menu-top-level-font-family: var(--font-body--family);
13710--menu-top-level-font-size-desktop: 0.875rem; --menu-top-level-font-style: var(--font-body--style);
13710 --menu-top-level-font-weight: var(--font-body--weight); --menu-top-level-font-case:none;
13711
13712  --menu-top-level-font-size: var(--menu-font-sm--size); --menu-top-level-font-line-height:
13713  var(--menu-font-sm--line-height);
13714
13715--menu-top-level-font-color: var(--color-foreground); --menu-top-level-font-color-rgb: var(--color-foreground-rgb);
13716"
13717        >
13718          
13719          <overflow-list
13720  
13721    ref="overflowMenu"
13722  
13723  
13724    class="overflow-menu color-scheme-matches-parent"
13725  
13726  
13727    minimum-items="2"
13728  
13729  
13730    data-testid="header-menu-overflow-list"
13731  
13732  
13733    data-skip-node-update
13734  
13735>
13736  <template shadowrootmode="open">
13737    <link href="//www.bostonproper.com/cdn/shop/t/1521/assets/overflow-list.css?v=16727044177065489451790713714" rel="stylesheet" type="text/css" media="all" />
13738
13739    <ul part="list">
13740      <slot></slot>
13741      <slot
13742        name="more"
13743        part="more"
13744        hidden
13745        
13746      >
13747        <li
13748          part="more"
13749        >
13750          <button
13751            class="button"
13752            type="button"
13753            tabindex="0"
13754            
13755          >
13756            More
13757          </button>
13758        </li>
13759      </slot>
13760      <li
13761        part="placeholder"
13762        hidden
13763      ></li>
13764    </ul>
13765
13766    <div part="overflow">
13767      <ul part="overflow-list">
13768        <slot name="overflow"></slot>
13769      </ul>
13770    </div>
13771  </template>
13772
13773  
13774      
13775      <li
13776  role="presentation"
13777  class="menu-list__list-item bp-menu-item-li"
13778  data-bp-menu-item
13779  
13780><a
13781      href="/collections/new-arrivals"
13782      data-skip-node-update="true"
13783      class="menu-list__link"
13784      aria-controls="bp-submenu-AR2Y1MTEyN25uOTEyM__bp_menu_new_arrivals"
13785      aria-haspopup="true"
13786      aria-expanded="false"
13787      ref="menuitem"
13788    >
13789      <span class="menu-list__link-title">New Arrivals</span>
13790    </a>
13791    <div class="bp-mega-submenu" id="bp-submenu-AR2Y1MTEyN25uOTEyM__bp_menu_new_arrivals">
13792      <div class="bp-mega-submenu__inner">
13793        <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column">
13794                  <p class="bp-mega__heading"><a href="/collections/new-arrivals">New Arrivals</a></p><ul class="bp-mega__links"><li><a href="/collections/new-arrivals">Shop All</a></li><li><a href="/pages/digital-catalog">Digital Catalog</a></li><li><a href="/collections/new-arrivals-athleisure">Athleisure</a></li><li><a href="/collections/new-arrivals-coats">Coats</a></li><li><a href="/collections/new-arrivals-dresses">Dresses</a></li><li><a href="/collections/new-arrivals-jackets-blazers">Jackets & Blazers</a></li><li><a href="/collections/new-arrivals-jeans">Jeans</a></li><li><a href="/collections/new-arrivals-loungewear">Loungewear</a></li><li><a href="/collections/new-arrivals-pants-leggings">Pants & Leggings</a></li><li><a href="/collections/new-arrivals-shoes-accessories">Shoes & Accessories</a></li><li><a href="/collections/new-arrivals-skirts-shorts">Skirts & Shorts</a></li><li><a href="/collections/new-arrivals-sweaters">Sweaters</a></li><li><a href="/collections/new-arrivals-swimsuits-swimwear">Swimwear</a></li><li><a href="/collections/new-arrivals-tops-blouses-tees">Tops</a></li></ul></div><div class="bp-mega__column">
13795                  <p class="bp-mega__heading"><a href="/collections/new-arrivals">Featured Shops</a></p><ul class="bp-mega__links"><li><a href="/collections/featured-shop-animal-prints">Animal Prints</a></li><li><a href="/collections/editors-picks">Editor's Picks</a></li><li><a href="/collections/featured-shops-fall-colors">Fall Colors</a></li><li><a href="/collections/featured-shop-intricate-details">Intricate Details</a></li><li><a href="/collections/featured-shops-matching-sets">Matching Sets</a></li><li><a href="/collections/breast-cancer-awareness">Power in Pink</a></li><li><a href="/collections/featured-shops-layering">The Layering Shop</a></li><li><a href="https://www.bostonproper.com/collections/featured-shops-suede-leather">Suede & Leather</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li><li><a href="/pages/the-sweater-edit">Style Guide: The Sweater Edit</a></li><li><a href="/pages/new-to-boston-proper">New to Boston Proper? </a></li></ul></div><div class="bp-mega__column">
13796                  <p class="bp-mega__heading"><a href="/pages/the-beyond-travel-collection">Beyond Travel Collection</a></p><ul class="bp-mega__links"><li><a href="/collections/travel">Shop All </a></li><li><a href="/pages/the-beyond-travel-collection">The Travel Collection</a></li><li><a href="/collections/travel-bottoms">Beyond Travel Bottoms</a></li><li><a href="/collections/travel-dresses">Beyond Travel Dresses</a></li><li><a href="/collections/travel-jackets">Beyond Travel Jackets</a></li><li><a href="/collections/travel-tops">Beyond Travel Tops</a></li><li><a href="/collections/travel-sets">Beyond Travel Sets</a></li></ul></div><div class="bp-mega__column">
13797                  <p class="bp-mega__heading"><a href="/collections/all-brands-we-love">Brands We Love</a></p><ul class="bp-mega__links"><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-becca">Becca By Rebecca Virtue</a></li><li><a href="/collections/brands-we-love-carmen-marc-valvo">Carmen Marc Valvo</a></li><li><a href="/collections/brands-we-love-change-of-scenery">
13797Change of Scenery</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini X Boston Proper</a></li><li><a href="/collections/brands-we-love-saint-jo">Saint Jō</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li><li><a href="/collections/brands-we-love-walter-baker">Walter Baker</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></div></div><div class="bp-mega__promos"><div class="bp-mega__promo">
13798  <a href="/collections/new-arrivals" class="bp-mega__promo-link">
13799    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_73.jpg?v=1790714514&amp;width=400" alt="New Season. New Statements." srcset="//www.bostonproper.com/cdn/shop/files/Image_73.jpg?v=1790714514&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_73.jpg?v=1790714514&amp;width=400 400w" width="400" height="500" loading="lazy">
13800</div>
13801    <h4 class="bp-mega__promo-title">New Season. New Statements.</h4><div class="bp-mega__promo-copy"><p>Enjoy 20% Off $175+ Plus Free Shipping. Limited Time. Use code: STYLE20</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13802  </a>
13803</div>
13804
13805<div class="bp-mega__promo">
13806  <a href="/pages/the-dress-code" class="bp-mega__promo-link">
13807    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_New_Arrivals_Image-6.jpg?v=1790707073&amp;width=400" alt="The Dress Code" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_New_Arrivals_Image-6.jpg?v=1790707073&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_New_Arrivals_Image-6.jpg?v=1790707073&amp;width=400 400w" width="400" height="500" loading="lazy">
13808</div>
13809    <h4 class="bp-mega__promo-title">The Dress Code</h4><div class="bp-mega__promo-copy"><p>The one-piece solution. Simple to style, flattering to wear, and ready for every plan.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13810  </a>
13811</div>
13812
13813</div></div>
13814      </div>
13815    </div></li><li class="bp-mm-item" data-bp-mm-id="AR2Y1MTEyN25uOTEyM__bp_menu_new_arrivals"><button type="button" class="bp-mm-item__row" data-open-view="AR2Y1MTEyN25uOTEyM__bp_menu_new_arrivals">
13816      <span class="bp-mm-item__label">New Arrivals</span>
13817      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13818  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13819</svg>
13820</span>
13821    </button>
13822
13823    <section class="bp-mm-view" data-view="AR2Y1MTEyN25uOTEyM__bp_menu_new_arrivals" hidden>
13824      <header class="bp-mm-view__header">
13825        <button type="button" class="bp-mm-view__back" data-back>
13826          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13827  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13828</svg>
13829</span>
13830          <span>New Arrivals</span>
13831        </button>
13832        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13833  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13834  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13835</svg>
13836</button>
13837      </header><div class="bp-mm-view__sections"><section class="bp-mm-section">
13838              <p class="bp-mm-section__heading"><a href="/collections/new-arrivals">New Arrivals</a></p><ul class="bp-mm-section__links"><li><a href="/collections/new-arrivals">Shop All</a></li><li><a href="/pages/digital-catalog">Digital Catalog</a></li><li><a href="/collections/new-arrivals-athleisure">Athleisure</a></li><li><a href="/collections/new-arrivals-coats">Coats</a></li><li><a href="/collections/new-arrivals-dresses">Dresses</a></li><li><a href="/collections/new-arrivals-jackets-blazers">Jackets & Blazers</a></li><li><a href="/collections/new-arrivals-jeans">Jeans</a></li><li><a href="/collections/new-arrivals-loungewear">Loungewear</a></li><li><a href="/collections/new-arrivals-pants-leggings">Pants & Leggings</a></li><li><a href="/collections/new-arrivals-shoes-accessories">Shoes & Accessories</a></li><li><a href="/collections/new-arrivals-skirts-shorts">Skirts & Shorts</a></li><li><a href="/collections/new-arrivals-sweaters">Sweaters</a></li><li><a href="/collections/new-arrivals-swimsuits-swimwear">Swimwear</a></li><li><a href="/collections/new-arrivals-tops-blouses-tees">Tops</a></li></ul></section><section class="bp-mm-section">
13839              <p class="bp-mm-section__heading"><a href="/collections/new-arrivals">Featured Shops</a></p><ul class="bp-mm-section__links"><li><a href="/collections/featured-shop-animal-prints">Animal Prints</a></li><li><a href="/collections/editors-picks">Editor's Picks</a></li><li><a href="/collections/featured-shops-fall-colors">Fall Colors</a></li><li><a href="/collections/featured-shop-intricate-details">Intricate Details</a></li><li><a href="/collections/featured-shops-matching-sets">Matching Sets</a></li><li><a href="/collections/breast-cancer-awareness">Power in Pink</a></li><li><a href="/collections/featured-shops-layering">The Layering Shop</a></li><li><a href="https://www.bostonproper.com/collections/featured-shops-suede-leather">Suede & Leather</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li><li><a href="/pages/the-sweater-edit">Style Guide: The Sweater Edit</a></li><li><a href="/pages/new-to-boston-proper">New to Boston Proper? </a></li></ul></section><section class="bp-mm-section">
13840              <p class="bp-mm-section__heading"><a href="/pages/the-beyond-travel-collection">Beyond Travel Collection</a></p><ul class="bp-mm-section__links"><li><a href="/collections/travel">Shop All </a></li><li><a href="/pages/the-beyond-travel-collection">The Travel Collection</a></li><li><a href="/collections/travel-bottoms">Beyond Travel Bottoms</a></li><li><a href="/collections/travel-dresses">Beyond Travel Dresses</a></li><li><a href="/collections/travel-jackets">Beyond Travel Jackets</a></li><li><a href="/collections/travel-tops">Beyond Travel Tops</a></li><li><a href="/collections/travel-sets">Beyond Travel Sets</a></li></ul></section><section class="bp-mm-section">
13841              <p class="bp-mm-section__heading"><a href="/collections/all-brands-we-love">Brands We Love</a></p><ul class="bp-mm-section__links"><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-becca">Becca By Rebecca Virtue</a></li><li><a href="/collections/brands-we-love-carmen-marc-valvo">Carmen Marc Valvo</a></li><li><a href="/collections/brands-we-love-change-of-scenery">
13841Change of Scenery</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini X Boston Proper</a></li><li><a href="/collections/brands-we-love-saint-jo">Saint Jō</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li><li><a href="/collections/brands-we-love-walter-baker">Walter Baker</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo">
13842  <a href="/collections/new-arrivals" class="bp-mega__promo-link">
13843    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_73.jpg?v=1790714514&amp;width=400" alt="New Season. New Statements." srcset="//www.bostonproper.com/cdn/shop/files/Image_73.jpg?v=1790714514&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_73.jpg?v=1790714514&amp;width=400 400w" width="400" height="500" loading="lazy">
13844</div>
13845    <h4 class="bp-mega__promo-title">New Season. New Statements.</h4><div class="bp-mega__promo-copy"><p>Enjoy 20% Off $175+ Plus Free Shipping. Limited Time. Use code: STYLE20</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13846  </a>
13847</div>
13848
13849<div class="bp-mega__promo">
13850  <a href="/pages/the-dress-code" class="bp-mega__promo-link">
13851    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_New_Arrivals_Image-6.jpg?v=1790707073&amp;width=400" alt="The Dress Code" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_New_Arrivals_Image-6.jpg?v=1790707073&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_New_Arrivals_Image-6.jpg?v=1790707073&amp;width=400 400w" width="400" height="500" loading="lazy">
13852</div>
13853    <h4 class="bp-mega__promo-title">The Dress Code</h4><div class="bp-mega__promo-copy"><p>The one-piece solution. Simple to style, flattering to wear, and ready for every plan.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13854  </a>
13855</div>
13856
13857</div></section></li>
13858
13859
13860
13861<li
13862  role="presentation"
13863  class="menu-list__list-item bp-menu-item-li"
13864  data-bp-menu-item
13865  
13866><a
13867      href="/collections/clothing"
13868      data-skip-node-update="true"
13869      class="menu-list__link"
13870      aria-controls="bp-submenu-AUjR2VlEyVFlTbXhaM__bp_menu_clothing"
13871      aria-haspopup="true"
13872      aria-expanded="false"
13873      ref="menuitem"
13874    >
13875      <span class="menu-list__link-title">Clothing</span>
13876    </a>
13877    <div class="bp-mega-submenu" id="bp-submenu-AUjR2VlEyVFlTbXhaM__bp_menu_clothing">
13878      <div class="bp-mega-submenu__inner">
13879        <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column">
13880                  <p class="bp-mega__heading"><a href="/collections/clothing">Clothing</a></p><ul class="bp-mega__links"><li><a href="/collections/clothing">All Clothing</a></li><li><a href="/collections/clothing-athleisure">Athleisure</a></li><li><a href="/collections/clothing-bottoms">Bottoms</a></li><li><a href="/collections/clothing-jeans">Denim & Jeans</a></li><li><a href="/collections/clothing-dresses">Dresses</a></li><li><a href="/collections/clothing-intimates">Intimates</a></li><li><a href="/collections/clothing-jackets-blazers">Jackets & Blazers</a></li><li><a href="/collections/clothing-loungewear">Loungewear</a></li><li><a href="/collections/clothing-pants-leggings">Pants & Leggings</a></li><li><a href="/collections/clothing-shirts-blouses">Shirts & Blouses</a></li><li><a href="/collections/clothing-skirts-shorts">Skirts & Shorts</a></li><li><a href="/collections/clothing-sweaters">Sweaters</a></li><li><a href="/collections/clothing-swimsuits-swimwear">Swimwear</a></li><li><a href="/collections/clothing-tops-blouses-tees">Tops</a></li></ul></div><div class="bp-mega__column">
13881                  <p class="bp-mega__heading"><a href="/pages/all-occasions">Occasions</a></p><ul class="bp-mega__links"><li><a href="/collections/occasions-everyday-style">Casual Chic</a></li><li><a href="/collections/occasions-night-out">Own the Evening</a></li><li><a href="/collections/occasions-special-occasion">RSVP Ready</a></li><li><a href="/collections/occasions-vacation">Escape in Style</a></li><li><a href="/collections/occasions-work">Power Moves</a></li><li><a href="/collections/occasions-wedding">Celebrate Beautifully</a></li></ul></div><div class="bp-mega__column">
13882                  <p class="bp-mega__heading"><a href="/collections/clothing">Shops</a></p><ul class="bp-mega__links"><li><a href="/collections/clothing-pants-leggings">
13882The Bottoms Guide</a></li><li><a href="/collections/clothing-jeans">The Denim Guide</a></li><li><a href="/pages/essentials-collection">The Essentials Edit</a></li><li><a href="/collections/essentials">The Tops Collection</a></li><li><a href="/collections/the-suiting-shop">The Suiting Shop</a></li><li><a href="/pages/the-dress-code">Style Guide: The Dress Code</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li><li><a href="/pages/the-sweater-edit">Style Guide: The Sweater Edit</a></li></ul></div><div class="bp-mega__column">
13883                  <p class="bp-mega__heading"><a href="/collections/all-brands-we-love">Brands We Love</a></p><ul class="bp-mega__links"><li><a href="/collections/brands-we-love-becca">Becca By Rebecca Virtue</a></li><li><a href="/collections/brands-we-love-carmen-marc-valvo">Carmen Marc Valvo</a></li><li><a href="/collections/brands-we-love-change-of-scenery">Change of Scenery</a></li><li><a href="/collections/brands-we-love-mimosa-lane">Mimosa Lane</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini X Boston Proper</a></li><li><a href="/collections/brands-we-love-saint-jo">Saint Jō</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li><li><a href="/collections/brands-we-love-walter-baker">Walter Baker</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li></ul></div></div><div class="bp-mega__promos"><div class="bp-mega__promo">
13884  <a href="/collections/breast-cancer-awareness" class="bp-mega__promo-link">
13885    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_69.jpg?v=1790780283&amp;width=400" alt="Power In Pink" srcset="//www.bostonproper.com/cdn/shop/files/Image_69.jpg?v=1790780283&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_69.jpg?v=1790780283&amp;width=400 400w" width="400" height="500" loading="lazy">
13886</div>
13887    <h4 class="bp-mega__promo-title">Power In Pink</h4><div class="bp-mega__promo-copy"><p>Wearing pink never felt so powerful. Shop our curated Power in Pink Collection and join us in supporting the Lynn Cancer Institute.</p></div><span class="bp-mega__promo-cta">Shop With Purpose</span>
13888  </a>
13889</div>
13890
13891<div class="bp-mega__promo">
13892  <a href="/collections/knit-tops" class="bp-mega__promo-link">
13893    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Clothing_Image-8.jpg?v=1790707168&amp;width=400" alt="Knit Tops" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Clothing_Image-8.jpg?v=1790707168&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Clothing_Image-8.jpg?v=1790707168&amp;width=400 400w" width="400" height="500" loading="lazy">
13894</div>
13895    <h4 class="bp-mega__promo-title">Knit Tops</h4><div class="bp-mega__promo-copy"><p>From everyday to unforgettable. Flattering knits made for denim, jackets, and everything after.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13896  </a>
13897</div>
13898
13899</div></div>
13900      </div>
13901    </div></li><li class="bp-mm-item" data-bp-mm-id="AUjR2VlEyVFlTbXhaM__bp_menu_clothing"><button type="button" class="bp-mm-item__row" data-open-view="AUjR2VlEyVFlTbXhaM__bp_menu_clothing">
13902      <span class="bp-mm-item__label">Clothing</span>
13903      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13904  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13905</svg>
13906</span>
13907    </button>
13908
13909    <section class="bp-mm-view" data-view="AUjR2VlEyVFlTbXhaM__bp_menu_clothing" hidden>
13910      <header class="bp-mm-view__header">
13911        <button type="button" class="bp-mm-view__back" data-back>
13912          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13913  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13914</svg>
13915</span>
13916          <span>Clothing</span>
13917        </button>
13918        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
13919  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13920  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
13921</svg>
13922</button>
13923      </header><div class="bp-mm-view__sections"><section class="bp-mm-section">
13924              <p class="bp-mm-section__heading"><a href="/collections/clothing">Clothing</a></p><ul class="bp-mm-section__links"><li><a href="/collections/clothing">All Clothing</a></li><li><a href="/collections/clothing-athleisure">Athleisure</a></li><li><a href="/collections/clothing-bottoms">Bottoms</a></li><li><a href="/collections/clothing-jeans">Denim & Jeans</a></li><li><a href="/collections/clothing-dresses">Dresses</a></li><li><a href="/collections/clothing-intimates">Intimates</a></li><li><a href="/collections/clothing-jackets-blazers">Jackets & Blazers</a></li><li><a href="/collections/clothing-loungewear">Loungewear</a></li><li><a href="/collections/clothing-pants-leggings">Pants & Leggings</a></li><li><a href="/collections/clothing-shirts-blouses">Shirts & Blouses</a></li><li><a href="/collections/clothing-skirts-shorts">Skirts & Shorts</a></li><li><a href="/collections/clothing-sweaters">Sweaters</a></li><li><a href="/collections/clothing-swimsuits-swimwear">Swimwear</a></li><li><a href="/collections/clothing-tops-blouses-tees">Tops</a></li></ul></section><section class="bp-mm-section">
13925              <p class="bp-mm-section__heading"><a href="/pages/all-occasions">Occasions</a></p><ul class="bp-mm-section__links"><li><a href="/collections/occasions-everyday-style">Casual Chic</a></li><li><a href="/collections/occasions-night-out">Own the Evening</a></li><li><a href="/collections/occasions-special-occasion">RSVP Ready</a></li><li><a href="/collections/occasions-vacation">Escape in Style</a></li><li><a href="/collections/occasions-work">Power Moves</a></li><li><a href="/collections/occasions-wedding">Celebrate Beautifully</a></li></ul></section><section class="bp-mm-section">
13926              <p class="bp-mm-section__heading"><a href="/collections/clothing">Shops</a></p><ul class="bp-mm-section__links"><li><a href="/collections/clothing-pants-leggings">The Bottoms Guide</a></li><li><a href="/collections/clothing-jeans">The Denim Guide</a></li><li><a href="/pages/essentials-collection">The Essentials Edit</a></li><li><a href="/collections/essentials">The Tops Collection</a></li><li><a href="/collections/the-suiting-shop">The Suiting Shop</a></li><li><a href="/pages/the-dress-code">Style Guide: The Dress Code</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li><li><a href="/pages/the-sweater-edit">Style Guide: The Sweater Edit</a></li></ul></section><section class="bp-mm-section">
13927              <p class="bp-mm-section__heading"><a href="/collections/all-brands-we-love">Brands We Love</a></p><ul class="bp-mm-section__links"><li><a href="/collections/brands-we-love-becca">Becca By Rebecca Virtue</a></li><li><a href="/collections/brands-we-love-carmen-marc-valvo">Carmen Marc Valvo</a></li><li><a href="/collections/brands-we-love-change-of-scenery">Change of Scenery</a></li><li><a href="/collections/brands-we-love-mimosa-lane">Mimosa Lane</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini X Boston Proper</a></li><li><a href="/collections/brands-we-love-saint-jo">Saint Jō</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li><li><a href="/collections/brands-we-love-walter-baker">Walter Baker</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo">
13928  <a href="/collections/breast-cancer-awareness" class="bp-mega__promo-link">
13929    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_69.jpg?v=1790780283&amp;width=400" alt="Power In Pink" srcset="//www.bostonproper.com/cdn/shop/files/Image_69.jpg?v=1790780283&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_69.jpg?v=1790780283&amp;width=400 400w" width="400" height="500" loading="lazy">
13930</div>
13931    <h4 class="bp-mega__promo-title">Power In Pink</h4><div class="bp-mega__promo-copy"><p>Wearing pink never felt so powerful. Shop our curated Power in Pink Collection and join us in supporting the Lynn Cancer Institute.</p></div><span class="bp-mega__promo-cta">Shop With Purpose</span>
13932  </a>
13933</div>
13934
13935<div class="bp-mega__promo">
13936  <a href="/collections/knit-tops" class="bp-mega__promo-link">
13937    <div class="bp-mega__promo-image">
13937<img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Clothing_Image-8.jpg?v=1790707168&amp;width=400" alt="Knit Tops" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Clothing_Image-8.jpg?v=1790707168&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Clothing_Image-8.jpg?v=1790707168&amp;width=400 400w" width="400" height="500" loading="lazy">
13938</div>
13939    <h4 class="bp-mega__promo-title">Knit Tops</h4><div class="bp-mega__promo-copy"><p>From everyday to unforgettable. Flattering knits made for denim, jackets, and everything after.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
13940  </a>
13941</div>
13942
13943</div></section></li>
13944
13945
13946
13947<li
13948  role="presentation"
13949  class="menu-list__list-item bp-menu-item-li"
13950  data-bp-menu-item
13951  
13952><a
13953      href="/pages/all-occasions"
13954      data-skip-node-update="true"
13955      class="menu-list__link"
13956      aria-controls="bp-submenu-AWlVkd2t4OFJocXpVU__bp_menu_occasions"
13957      aria-haspopup="true"
13958      aria-expanded="false"
13959      ref="menuitem"
13960    >
13961      <span class="menu-list__link-title">Occasions</span>
13962    </a>
13963    <div class="bp-mega-submenu" id="bp-submenu-AWlVkd2t4OFJocXpVU__bp_menu_occasions">
13964      <div class="bp-mega-submenu__inner">
13965        <div class="bp-mega bp-mega--image-tiles"><div class="bp-mega__tiles"><a class="bp-mega__tile" href="/collections/occasions-everyday-style">
13966                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-10.jpg?v=1790701815&amp;width=400" alt="Casual Chic" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-10.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-10.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
13967</div>
13968                  <p class="bp-mega__tile-title">Casual Chic</p>
13969                  <span class="bp-mega__tile-cta">Shop Now</span>
13970                </a><a class="bp-mega__tile" href="/collections/occasions-vacation">
13971                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-14.jpg?v=1790701815&amp;width=400" alt="Escape in Style" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-14.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-14.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
13972</div>
13973                  <p class="bp-mega__tile-title">Escape in Style</p>
13974                  <span class="bp-mega__tile-cta">Shop Now</span>
13975                </a><a class="bp-mega__tile" href="/collections/occasions-special-occasion">
13976                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-16.jpg?v=1790701815&amp;width=400" alt="RSVP Ready" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-16.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-16.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
13977</div>
13978                  <p class="bp-mega__tile-title">RSVP Ready</p>
13979                  <span class="bp-mega__tile-cta">Shop Now</span>
13980                </a><a class="bp-mega__tile" href="/collections/occasions-work">
13981                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-12.jpg?v=1790701815&amp;width=400" alt="Power Moves" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-12.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-12.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
13982</div>
13983                  <p class="bp-mega__tile-title">Power Moves</p>
13984                  <span class="bp-mega__tile-cta">Shop Now</span>
13985                </a><a class="bp-mega__tile" href="/collections/occasions-night-out">
13986                  <div class="bp-mega__tile-image">
13986<img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-18_9dd5998e-01cb-46c4-a182-cd9be31c2c67.jpg?v=1790701815&amp;width=400" alt="Own the Evening" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-18_9dd5998e-01cb-46c4-a182-cd9be31c2c67.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-18_9dd5998e-01cb-46c4-a182-cd9be31c2c67.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
13987</div>
13988                  <p class="bp-mega__tile-title">Own the Evening</p>
13989                  <span class="bp-mega__tile-cta">Shop Now</span>
13990                </a><a class="bp-mega__tile" href="/collections/occasions-wedding">
13991                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-20_6043da00-6dae-4bd6-9c2c-e935f58f8b4c.jpg?v=1790701815&amp;width=400" alt="Celebrate Beautifully" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-20_6043da00-6dae-4bd6-9c2c-e935f58f8b4c.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-20_6043da00-6dae-4bd6-9c2c-e935f58f8b4c.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
13992</div>
13993                  <p class="bp-mega__tile-title">Celebrate Beautifully</p>
13994                  <span class="bp-mega__tile-cta">Shop Now</span>
13995                </a></div></div>
13996      </div>
13997    </div></li><li class="bp-mm-item" data-bp-mm-id="AWlVkd2t4OFJocXpVU__bp_menu_occasions"><button type="button" class="bp-mm-item__row" data-open-view="AWlVkd2t4OFJocXpVU__bp_menu_occasions">
13998      <span class="bp-mm-item__label">Occasions</span>
13999      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14000  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14001</svg>
14002</span>
14003    </button>
14004
14005    <section class="bp-mm-view" data-view="AWlVkd2t4OFJocXpVU__bp_menu_occasions" hidden>
14006      <header class="bp-mm-view__header">
14007        <button type="button" class="bp-mm-view__back" data-back>
14008          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14009  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14010</svg>
14011</span>
14012          <span>Occasions</span>
14013        </button>
14014        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14015  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14016  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14017</svg>
14018</button>
14019      </header><div class="bp-mm-view__tiles"><a class="bp-mm-tile" href="/collections/occasions-everyday-style">
14020              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-10.jpg?v=1790701815&amp;width=400" alt="Casual Chic" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-10.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-10.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14021</span>
14022              <span class="bp-mm-tile__title">Casual Chic</span>
14023              <span class="bp-mm-tile__cta">Shop Now</span>
14024            </a><a class="bp-mm-tile" href="/collections/occasions-vacation">
14025              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-14.jpg?v=1790701815&amp;width=400" alt="Escape in Style" srcset="//www.bostonproper.com/cdn/shop/files/Fl
14025y_Downs_Occasions_Image-14.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-14.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14026</span>
14027              <span class="bp-mm-tile__title">Escape in Style</span>
14028              <span class="bp-mm-tile__cta">Shop Now</span>
14029            </a><a class="bp-mm-tile" href="/collections/occasions-special-occasion">
14030              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-16.jpg?v=1790701815&amp;width=400" alt="RSVP Ready" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-16.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-16.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14031</span>
14032              <span class="bp-mm-tile__title">RSVP Ready</span>
14033              <span class="bp-mm-tile__cta">Shop Now</span>
14034            </a><a class="bp-mm-tile" href="/collections/occasions-work">
14035              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-12.jpg?v=1790701815&amp;width=400" alt="Power Moves" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-12.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-12.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14036</span>
14037              <span class="bp-mm-tile__title">Power Moves</span>
14038              <span class="bp-mm-tile__cta">Shop Now</span>
14039            </a><a class="bp-mm-tile" href="/collections/occasions-night-out">
14040              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-18_9dd5998e-01cb-46c4-a182-cd9be31c2c67.jpg?v=1790701815&amp;width=400" alt="Own the Evening" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-18_9dd5998e-01cb-46c4-a182-cd9be31c2c67.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-18_9dd5998e-01cb-46c4-a182-cd9be31c2c67.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14041</span>
14042              <span class="bp-mm-tile__title">Own the Evening</span>
14043              <span class="bp-mm-tile__cta">Shop Now</span>
14044            </a><a class="bp-mm-tile" href="/collections/occasions-wedding">
14045              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-20_6043da00-6dae-4bd6-9c2c-e935f58f8b4c.jpg?v=1790701815&amp;width=400" alt="Celebrate Beautifully" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-20_6043da00-6dae-4bd6-9c2c-e935f58f8b4c.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Occasions_Image-20_6043da00-6dae-4bd6-9c2c-e935f58f8b4c.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14046</span>
14047              <span class="bp-mm-tile__title">Celebrate Beautifully</span>
14048              <span class="bp-mm-tile__cta">Shop Now</span>
14049            </a></div></section></li>
14050
14051
14052
14053<li
14054  role="presentation"
14055  class="menu-list__list-item bp-menu-item-li"
14056  data-bp-menu-item
14057  
14058><a
14059      href="/pages/essentials-collection"
14060      data-skip-node-update="true"
14061      class="menu-list__link"
14062      aria-controls="bp-submenu-ARTdKY3Jpczg4VVVHb__bp_menu_collections"
14063      aria-haspopup="true"
14064      aria-expanded="false"
14065      ref="menuitem"
14066    >
14067      <span class="menu-list__link-title">Collections</span>
14068    </a>
14069    <div class="bp-mega-submenu" id="bp-submenu-ARTdKY3Jpczg4VVVHb__bp_menu_collections">
14070      <div class="bp-mega-submenu__inner">
14071        <div class="bp-mega bp-mega--image-tiles"><div class="bp-mega__tiles"><a class="bp-mega__tile" href="/collections/charmeuse">
14072                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-11.jpg?v=1790701815&amp;width=400" alt="Charmeuse" srcset="//www.bostonproper.com/cdn/shop/files/Fl
14072y_Downs_Collections_Image-11.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-11.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14073</div>
14074                  <p class="bp-mega__tile-title">Charmeuse</p>
14075                  <span class="bp-mega__tile-cta">Shop Now</span>
14076                </a><a class="bp-mega__tile" href="/collections/chic-zip">
14077                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_76_c1e341e6-f12c-49d5-bc88-54e2673f3c30.jpg?v=1790802160&amp;width=400" alt="Chic Zip" srcset="//www.bostonproper.com/cdn/shop/files/Image_76_c1e341e6-f12c-49d5-bc88-54e2673f3c30.jpg?v=1790802160&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_76_c1e341e6-f12c-49d5-bc88-54e2673f3c30.jpg?v=1790802160&amp;width=400 400w" width="400" height="500" loading="lazy">
14078</div>
14079                  <p class="bp-mega__tile-title">Chic Zip</p>
14080                  <span class="bp-mega__tile-cta">Shop Now</span>
14081                </a><a class="bp-mega__tile" href="/collections/clothing-jeans">
14082                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-17.jpg?v=1790701815&amp;width=400" alt="Denim" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-17.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-17.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14083</div>
14084                  <p class="bp-mega__tile-title">Denim</p>
14085                  <span class="bp-mega__tile-cta">Shop Now</span>
14086                </a><a class="bp-mega__tile" href="/collections/the-suiting-shop">
14087                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-13.jpg?v=1790701815&amp;width=400" alt="Modern Suiting" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-13.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-13.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14088</div>
14089                  <p class="bp-mega__tile-title">Modern Suiting</p>
14090                  <span class="bp-mega__tile-cta">Shop Now</span>
14091                </a><a class="bp-mega__tile" href="/collections/travel">
14092                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-19.jpg?v=1790701815&amp;width=400" alt="Beyond Travel" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-19.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-19.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14093</div>
14094                  <p class="bp-mega__tile-title">Beyond Travel</p>
14095                  <span class="bp-mega__tile-cta">Shop Now</span>
14096                </a><a class="bp-mega__tile" href="/collections/athleisure-luxe-lounge">
14097                  <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-21.jpg?v=1790701815&amp;width=400" alt="Luxe Lounge" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-21.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-21.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14098</div>
14099                  <p class="bp-mega__tile-title">Luxe Lounge</p>
14100                  <span class="bp-mega__tile-cta">Shop Now</span>
14101                </a></div></div>
14102      </div>
14103    </div></li><li class="bp-mm-item" data-bp-mm-id="ARTdKY3Jpczg4VVVHb__bp_menu_collections"><button type="button" class="bp-mm-item__row" data-open-view="ARTdKY3Jpczg4VVVHb__bp_menu_collections">
14104      <span class="bp-mm-item__label">Collections</span>
14105      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14106  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14107</svg>
14108</span>
14109    </button>
14110
14111    <section class="bp-mm-view" data-view="ARTdKY3Jpczg4VVVHb__bp_menu_collections" hidden>
14112      <header class="bp-mm-view__header">
14113        <button type="button" class="bp-mm-view__back" data-back>
14114          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14115  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14116</svg>
14117</span>
14118          <span>Collections</span>
14119        </button>
14120        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14121  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14122  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14123</svg>
14124</button>
14125      </header><div class="bp-mm-view__tiles"><a class="bp-mm-tile" href="/collections/charmeuse">
14126              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-11.jpg?v=1790701815&amp;width=400" alt="Charmeuse" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-11.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-11.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14127</span>
14128              <span class="bp-mm-tile__title">Charmeuse</span>
14129              <span class="bp-mm-tile__cta">Shop Now</span>
14130            </a><a class="bp-mm-tile" href="/collections/chic-zip">
14131              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_76_c1e341e6-f12c-49d5-bc88-54e2673f3c30.jpg?v=1790802160&amp;width=400" alt="Chic Zip" srcset="//www.bostonproper.com/cdn/shop/files/Image_76_c1e341e6-f12c-49d5-bc88-54e2673f3c30.jpg?v=1790802160&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_76_c1e341e6-f12c-49d5-bc88-54e2673f3c30.jpg?v=1790802160&amp;width=400 400w" width="400" height="500" loading="lazy">
14132</span>
14133              <span class="bp-mm-tile__title">Chic Zip</span>
14134              <span class="bp-mm-tile__cta">Shop Now</span>
14135            </a><a class="bp-mm-tile" href="/collections/clothing-jeans">
14136              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-17.jpg?v=1790701815&amp;width=400" alt="Denim" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-17.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-17.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14137</span>
14138              <span class="bp-mm-tile__title">Denim</span>
14139              <span class="bp-mm-tile__cta">Shop Now</span>
14140            </a><a class="bp-mm-tile" href="/collections/the-suiting-shop">
14141              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-13.jpg?v=1790701815&amp;width=400" alt="Modern Suiting" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-13.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-13.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14142</span>
14143              <span class="bp-mm-tile__title">Modern Suiting</span>
14144              <span class="bp-mm-tile__cta">Shop Now</span>
14145            </a><a class="bp-mm-tile" href="/collections/travel">
14146              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-19.jpg?v=1790701815&amp;width=400" alt="Beyond Travel" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-19.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-19.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14147</span>
14148              <span class="bp-mm-tile__title">Beyond Travel</span>
14149              <span class="bp-mm-tile__cta">Shop Now</span>
14150            </a><a class="bp-mm-tile" href="/collections/athleisure-luxe-lounge">
14151              <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-21.jpg?v=1790701815&amp;width=400" alt="Luxe Lounge" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-21.jpg?v=1790701815&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Downs_Collections_Image-21.jpg?v=1790701815&amp;width=400 400w" width="400" height="500" loading="lazy">
14152</span>
14153              <span class="bp-mm-tile__title">Luxe Lounge</span>
14154              <span class="bp-mm-tile__cta">Shop Now</span>
14155            </a></div></section></li>
14156
14157
14158
14159<li
14160  role="presentation"
14161  class="menu-list__list-item bp-menu-item-li"
14162  data-bp-menu-item
14163  
14164><a
14165      href="/collections/shoes-accessories"
14166      data-skip-node-update="true"
14167      class="menu-list__link"
14168      aria-controls="bp-submenu-AdVdsY2tEV2JFWlVvV__bp_menu_shoes"
14169      aria-haspopup="true"
14170      aria-expanded="false"
14171      ref="menuitem"
14172    >
14173      <span class="menu-list__link-title">Shoes & Accessories</span>
14174    </a>
14175    <div class="bp-mega-submenu" id="bp-submenu-AdVdsY2tEV2JFWlVvV__bp_menu_shoes">
14176      <div class="bp-mega-submenu__inner">
14177        <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column">
14178                  <p class="bp-mega__heading"><a href="/collections/shoes">Shoes</a></p><ul class="bp-mega__links"><li><a href="/collections/shoes">All Shoes</a></li><li><a href="/collections/shoes-boots">Boots & Booties</a></li><li><a href="/collections/shoes-heels">Heels</a></li><li><a href="/collections/shoes-sandals">Sandals</a></li><li><a href="/collections/shoes-sneakers">Sneakers</a></li><li><a href="/collections/shoes-wedges">Wedges</a></li></ul></div><div class="bp-mega__column">
14179                  <p class="bp-mega__heading"><a href="/collections/accessories">Accessories</a></p><ul class="bp-mega__links"><li><a href="/collections/accessories">All Accessories</a></li><li><a href="/collections/accessories-bags">Bags</a></li><li><a href="/collections/accessories-belts">Belts</a></li><li><a href="/collections/accessories-hats">Hats</a></li><li><a href="/collections/accessories-jewelry">Jewelry</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Sunglasses</a></li></ul></div><div class="bp-mega__column">
14180                  <p class="bp-mega__heading"><a href="/collections/all-brands-we-love">Brands We Love</a></p><ul class="bp-mega__links"><li><a href="/collections/brands-we-love-amsterdam-heritage">Amsterdam Heritage</a></li><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-ettika">Ettika</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-hanky-panky">Hanky Panky</a></li><li><a href="/collections/brands-we-love-hat-attack-new-york">Hat Attack</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-miami-chains-co">Miami Chains & Co.</a></li><li><a href="/collections/brands-we-love-st-moran">St. Moran</a></li><li><a href="/collections/brands-we-love-the-sak">The Sak</a></li><li><a href="/collections/brands-we-love-t-jazelle">T. Jazelle</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></div></div><div class="bp-mega__promos"><div class="bp-mega__promo">
14181  <a href="/collections/shoes-boots" class="bp-mega__promo-link">
14182    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_63.jpg?v=1790780283&amp;width=400" alt="Boots" srcset="//www.bostonproper.com/cdn/shop/files/Image_63.jpg?v=1790780283&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_63.jpg?v=1790780283&amp;width=400 400w" width="400" height="500" loading="lazy">
14183</div>
14184    <h4 class="bp-mega__promo-title">Boots</h4><div class="bp-mega__promo-copy"><p>These boots are going places. Wild prints. Rich color stories. Versatile lengths. A new look for every mood.<br/><br/></p></div><span class="bp-mega__promo-cta">Shop Now</span>
14185  </a>
14186</div>
14187
14188<div class="bp-mega__promo">
14189  <a href="/collections/accessories-jewelry" class="bp-mega__promo-link">
14190    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_74.jpg?v=1790800759&amp;width=400" alt="Jewelry" srcset="//www.bostonproper.com/cdn/shop/files/Image_74.jpg?v=1790800759&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_74.jpg?v=1790800759&amp;width=400 400w" width="400" height="500" loading="lazy">
14191</div>
14192    <h4 class="bp-mega__promo-title">Jewelry</h4><div class="bp-mega__promo-copy"><p>Drenched in the&nbsp;details&nbsp;that define Boston Proper. Layered jewels&nbsp;and accent pieces&nbsp;that set the tone.&nbsp;&nbsp;</p></div><span class="bp-mega__promo-cta">Shop Now</span>
14193  </a>
14194</div>
14195
14196</div></div>
14197      </div>
14198    </div></li><li class="bp-mm-item" data-bp-mm-id="AdVdsY2tEV2JFWlVvV__bp_menu_shoes"><button type="button" class="bp-mm-item__row" data-open-view="AdVdsY2tEV2JFWlVvV__bp_menu_shoes">
14199      <span class="bp-mm-item__label">Shoes & Accessories</span>
14200      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14201  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14202</svg>
14203</span>
14204    </button>
14205
14206    <section class="bp-mm-view" data-view="AdVdsY2tEV2JFWlVvV__bp_menu_shoes" hidden>
14207      <header class="bp-mm-view__header">
14208        <button type="button" class="bp-mm-view__back" data-back>
14209          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14210  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14211</svg>
14212</span>
14213          <span>Shoes & Accessories</span>
14214        </button>
14215        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14216  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14217  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14218</svg>
14219</button>
14220      </header><div class="bp-mm-view__sections"><section class="bp-mm-section">
14221              <p class="bp-mm-section__heading"><a href="/collections/shoes">Shoes</a></p><ul class="bp-mm-section__links"><li><a href="/collections/shoes">All Shoes</a></li><li><a href="/collections/shoes-boots">Boots & Booties</a></li><li><a href="/collections/shoes-heels">Heels</a></li><li><a href="/collections/shoes-sandals">Sandals</a></li><li><a href="/collections/shoes-sneakers">Sneakers</a></li><li><a href="/collections/shoes-wedges">Wedges</a></li></ul></section><section class="bp-mm-section">
14222              <p class="bp-mm-section__heading"><a href="/collections/accessories">Accessories</a></p><ul class="bp-mm-section__links"><li><a href="/collections/accessories">All Accessories</a></li><li><a href="/collections/accessories-bags">Bags</a></li><li><a href="/collections/accessories-belts">Belts</a></li><li><a href="/collections/accessories-hats">Hats</a></li><li><a href="/collections/accessories-jewelry">Jewelry</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Sunglasses</a></li></ul></section><section class="bp-mm-section">
14223              <p class="bp-mm-section__heading"><a href="/collections/all-brands-we-love">Brands We Love</a></p><ul class="bp-mm-section__links"><li><a href="/collections/brands-we-love-amsterdam-heritage">Amsterdam Heritage</a></li><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-ettika">Ettika</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-hanky-panky">Hanky Panky</a></li><li><a href="/collections/brands-we-love-hat-attack-new-york">Hat Attack</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-miami-chains-co">Miami Chains & Co.</a></li><li><a href="/collections/brands-we-love-st-moran">St. Moran</a></li><li><a href="/collections/brands-we-love-the-sak">The Sak</a></li><li><a href="/collections/brands-we-love-t-jazelle">T. Jazelle</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo">
14224  <a href="/collections/shoes-boots" class="bp-mega__promo-link">
14225    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_63.jpg?v=1790780283&amp;width=400" alt="Boots" srcset="//www.bostonproper.com/cdn/shop/files/Image_63.jpg?v=1790780283&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_63.jpg?v=1790780283&amp;width=400 400w" width="400" height="500" loading="lazy">
14226</div>
14227    <h4 class="bp-mega__promo-title">Boots</h4><div class="bp-mega__promo-copy"><p>These boots are going places. Wild prints. Rich color stories. Versatile lengths. A new look for every mood.<br/><br/></p></div><span class="bp-mega__promo-cta">Shop Now</span>
14228  </a>
14229</div>
14230
14231<div class="bp-mega__promo">
14232  <a href="/collections/accessories-jewelry" class="bp-mega__promo-link">
14233    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_74.jpg?v=1790800759&amp;width=400" alt="Jewelry" srcset="//www.bostonproper.com/cdn/shop/files/Image_74.jpg?v=1790800759&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_74.jpg?v=1790800759&amp;width=400 400w" width="400" height="500" loading="lazy">
14234</div>
14235    <h4 class="bp-mega__promo-title">Jewelry</h4><div class="bp-mega__promo-copy"><p>Drenched in the&nbsp;details&nbsp;that define Boston Proper. Layered jewels&nbsp;and accent pieces&nbsp;that set the tone.&nbsp;&nbsp;</p></div><span class="bp-mega__promo-cta">Shop Now</span>
14236  </a>
14237</div>
14238
14239</div></section></li>
14240
14241
14242
14243<li
14244  role="presentation"
14245  class="menu-list__list-item bp-menu-item-li"
14246  data-bp-menu-item
14247  
14248><a
14249      href="/collections/sale-clearance"
14250      data-skip-node-update="true"
14251      class="menu-list__link"
14252      aria-controls="bp-submenu-AVFlZUDZaR3FYUVAyd__bp_menu_sale"
14253      aria-haspopup="true"
14254      aria-expanded="false"
14255      ref="menuitem"
14256    >
14257      <span class="menu-list__link-title">Sale & Clearance</span>
14258    </a>
14259    <div class="bp-mega-submenu" id="bp-submenu-AVFlZUDZaR3FYUVAyd__bp_menu_sale">
14260      <div class="bp-mega-submenu__inner">
14261        <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column">
14262                  <p class="bp-mega__heading"><a href="/collections/sale-clearance">Sale & Clearance</a></p><ul class="bp-mega__links"><li><a href="/collections/sale-clearance">Shop All</a></li><li><a href="/collections/new-markdowns">New Markdowns</a></li><li><a href="/collections/sale">Sale</a></li><li><a href="/collections/clearance">Clearance</a></li></ul></div><div class="bp-mega__column">
14263                  <p class="bp-mega__heading"><a href="/collections/sale-clearance">Shop By Category</a></p><ul class="bp-mega__links"><li><a href="/collections/sale-clearance-accessories">Accessories</a></li><li><a href="/collections/sale-clearance-athleisure">Athleisure</a></li><li><a href="/collections/sale-clearance-dresses">Dresses</a></li><li><a href="/collections/sale-clearance-jackets">Jackets & Blazers</a></li><li><a href="/collections/sale-clearance-jeans">Jeans</a></li><li><a href="/collections/sale-clearance-outerwear">Outerwear</a></li><li><a href="/collections/sale-clearance-pants-leggings">Pants & Leggings</a></li><li><a href="/collections/sale-clearance-shoes">Shoes</a></li><li><a href="/collections/sale-clearance-shorts">Shorts</a></li><li><a href="/collections/sale-clearance-skirts">Skirts</a></li><li><a href="/collections/sale-clearance-sweaters">Sweaters</a></li><li><a href="/collections/sale-clearance-swimwear">Swimwear</a></li><li><a href="/collections/sale-clearance-tops">Tops</a></li></ul></div><div class="bp-mega__column">
14264                  <p class="bp-mega__heading"><a href="/collections/sale-clearance">Promotions</a></p><ul class="bp-mega__links"><li><a href="/collections/new-arrivals">20% off $175+ plus free shipping</a></li><li><a href="/collections/winter-classic-rib-styles">Save $45 on 3 or $25 on 2</a></li><li><a href="/products/boston-proper-printed-scarf-with-love-bp">Free gift with  purchase of $400+</a></li></ul></div></div><div class="bp-mega__promos"><div class="bp-mega__promo">
14265  <a href="/collections/new-markdowns" class="bp-mega__promo-link">
14266    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_b520536c-2111-43e4-b1e8-166793f8fe43.jpg?v=1790704244&amp;width=400" alt="New Markdowns" srcset="//www.bostonproper.com/cdn/shop/files/Image_b520536c-2111-43e4-b1e8-166793f8fe43.jpg?v=1790704244&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_b520536c-2111-43e4-b1e8-166793f8fe43.jpg?v=1790704244&amp;width=400 400w" width="400" height="500" loading="lazy">
14267</div>
14268    <h4 class="bp-mega__promo-title">New Markdowns</h4><div class="bp-mega__promo-copy"><p>Rare finds.&nbsp;Newly reduced.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
14269  </a>
14270</div>
14271
14272<div class="bp-mega__promo">
14273  <a href="/collections/clearance" class="bp-mega__promo-link">
14274    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image-1.jpg?v=1790780282&amp;width=400" alt="Clearance" srcset="//www.bostonproper.com/cdn/shop/files/Image-1.jpg?v=1790780282&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image-1.jpg?v=1790780282&amp;width=400 400w" width="400" height="500" loading="lazy">
14275</div>
14276    <h4 class="bp-mega__promo-title">Clearance</h4><div class="bp-mega__promo-copy"><p>Your size won’t stay here long.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
14277  </a>
14278</div>
14279
14280</div></div>
14281      </div>
14282    </div></li><li class="bp-mm-item" data-bp-mm-id="AVFlZUDZaR3FYUVAyd__bp_menu_sale"><button type="button" class="bp-mm-item__row" data-open-view="AVFlZUDZaR3FYUVAyd__bp_menu_sale">
14283      <span class="bp-mm-item__label">Sale & Clearance</span>
14284      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14285  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14286</svg>
14287</span>
14288    </button>
14289
14290    <section class="bp-mm-view" data-view="AVFlZUDZaR3FYUVAyd__bp_menu_sale" hidden>
14291      <header class="bp-mm-view__header">
14292        <button type="button" class="bp-mm-view__back" data-back>
14293          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14294  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14295</svg>
14296</span>
14297          <span>Sale & Clearance</span>
14298        </button>
14299        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14300  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14301  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14302</svg>
14303</button>
14304      </header><div class="bp-mm-view__sections"><section class="bp-mm-section">
14305              <p class="bp-mm-section__heading"><a href="/collections/sale-clearance">Sale & Clearance</a></p><ul class="bp-mm-section__links"><li><a href="/collections/sale-clearance">Shop All</a></li><li><a href="/collections/new-markdowns">New Markdowns</a></li><li><a href="/collections/sale">Sale</a></li><li><a href="/collections/clearance">Clearance</a></li></ul></section><section class="bp-mm-section">
14306              <p class="bp-mm-section__heading"><a href="/collections/sale-clearance">Shop By Category</a></p><ul class="bp-mm-section__links"><li><a href="/collections/sale-clearance-accessories">Accessories</a></li><li><a href="/collections/sale-clearance-athleisure">Athleisure</a></li><li><a href="/collections/sale-clearance-dresses">Dresses</a></li><li><a href="/collections/sale-clearance-jackets">Jackets & Blazers</a></li><li><a href="/collections/sale-clearance-jeans">Jeans</a></li><li><a href="/collections/sale-clearance-outerwear">Outerwear</a></li><li><a href="/collections/sale-clearance-pants-leggings">Pants & Leggings</a></li><li><a href="/collections/sale-clearance-shoes">Shoes</a></li><li><a href="/collections/sale-clearance-shorts">Shorts</a></li><li><a href="/collections/sale-clearance-skirts">Skirts</a></li><li><a href="/collections/sale-clearance-sweaters">Sweaters</a></li><li><a href="/collections/sale-clearance-swimwear">Swimwear</a></li><li><a href="/collections/sale-clearance-tops">Tops</a></li></ul></section><section class="bp-mm-section">
14307              <p class="bp-mm-section__heading"><a href="/collections/sale-clearance">Promotions</a></p><ul class="bp-mm-section__links"><li><a href="/collections/new-arrivals">20% off $175+ plus free shipping</a></li><li><a href="/collections/winter-classic-rib-styles">Save $45 on 3 or $25 on 2</a></li><li><a href="/products/boston-proper-printed-scarf-with-love-bp">Free gift with  purchase of $400+</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo">
14308  <a href="/collections/new-markdowns" class="bp-mega__promo-link">
14309    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_b520536c-2111-43e4-b1e8-166793f8fe43.jpg?v=1790704244&amp;width=400" alt="New Markdowns" srcset="//www.bostonproper.com/cdn/shop/files/Image_b520536c-2111-43e4-b1e8-166793f8fe43.jpg?v=1790704244&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_b520536c-2111-43e4-b1e8-166793f8fe43.jpg?v=1790704244&amp;width=400 400w" width="400" height="500" loading="lazy">
14310</div>
14311    <h4 class="bp-mega__promo-title">New Markdowns</h4><div class="bp-mega__promo-copy"><p>Rare finds.&nbsp;Newly reduced.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
14312  </a>
14313</div>
14314
14315<div class="bp-mega__promo">
14316  <a href="/collections/clearance" class="bp-mega__promo-link">
14317    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image-1.jpg?v=1790780282&amp;width=400" alt="Clearance" srcset="//www.bostonproper.com/cdn/shop/files/Image-1.jpg?v=1790780282&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image-1.jpg?v=1790780282&amp;width=400 400w" width="400" height="500" loading="lazy">
14318</div>
14319    <h4 class="bp-mega__promo-title">Clearance</h4><div class="bp-mega__promo-copy"><p>Your size won’t stay here long.</p></div><span class="bp-mega__promo-cta">Shop Now</span>
14320  </a>
14321</div>
14322
14323</div></section></li>
14324
14325
14326
14327<li
14328  role="presentation"
14329  class="menu-list__list-item bp-menu-item-li"
14330  data-bp-menu-item
14331  
14332><a
14333      href="/blogs/styleedit"
14334      data-skip-node-update="true"
14335      class="menu-list__link"
14336      aria-controls="bp-submenu-ATVRxYnVkRFJjc0I3R__bp_menu_styleedit"
14337      aria-haspopup="true"
14338      aria-expanded="false"
14339      ref="menuitem"
14340    >
14341      <span class="menu-list__link-title">styleEDIT</span>
14342    </a>
14343    <div class="bp-mega-submenu" id="bp-submenu-ATVRxYnVkRFJjc0I3R__bp_menu_styleedit">
14344      <div class="bp-mega-submenu__inner">
14345        <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column">
14346                  <p class="bp-mega__heading"><a href="/blogs/styleedit">styleEDIT: What's New</a></p><ul class="bp-mega__links"><li><a href="/pages/new-to-boston-proper">New to Boston Proper? Start Here</a></li><li><a href="/blogs/styleedit/defy-all-expectations-why-style-doesn-t-expire-it-evolves">Why Style Doesn't Expire. It Evolves.</a></li><li><a href="https://www.bostonproper.com/blogs/styleedit/denim-dresses-are-back-here-s-how-to-wear-them-now">How to Wear Denim Dresses</a></li><li><a href="/blogs/styleedit">Read All</a></li></ul></div><div class="bp-mega__column">
14347                  <p class="bp-mega__heading"><a href="/collections/new-arrivals">Trending Now</a></p><ul class="bp-mega__links"><li><a href="/collections/featured-shop-animal-prints">Animal Prints</a></li><li><a href="/collections/featured-shops-matching-sets">Matching Sets</a></li><li><a href="/collections/color-crush-wine">Trending Color: Wine</a></li><li><a href="/collections/featured-shop-intricate-details">Intricate Details</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li></ul></div><div class="bp-mega__column">
14348                  <p class="bp-mega__heading"><a href="/blogs/styleedit">Discover</a></p><ul class="bp-mega__links"><li><a href="/pages/behind-the-seams">Behind the Seams</a></li><li><a href="/pages/sheryls-loves">Sheryl's Loves</a></li><li><a href="/pages/digital-catalog">Digital Catalog</a></li></ul></div></div><div class="bp-mega__promos"><div class="bp-mega__promo">
14349  <a href="/pages/sheryls-loves" class="bp-mega__promo-link">
14350    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_65.jpg?v=1790780283&amp;width=400" alt="Sheryl’s Loves" srcset="//www.bostonproper.com/cdn/shop/files/Image_65.jpg?v=1790780283&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_65.jpg?v=1790780283&amp;width=400 400w" width="400" height="500" loading="lazy">
14351</div>
14352    <h4 class="bp-mega__promo-title">Sheryl’s Loves</h4><div class="bp-mega__promo-copy"><p>“These pieces feel so me. Feminine, confident, and exactly how I want to show up right now.”&nbsp;
—Sheryl, Editor-in-Chic&nbsp;</p></div><span class="bp-mega__promo-cta">Shop Now</span>
14353  </a>
14354</div>
14355
14356<div class="bp-mega__promo">
14357  <a href="/pages/digital-catalog" class="bp-mega__promo-link">
14358    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_75.jpg?v=1790800820&amp;width=400" alt="Digital Catalog" srcset="//www.bostonproper.com/cdn/shop/files/Image_75.jpg?v=1790800820&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_75.jpg?v=1790800820&amp;width=400 400w" width="400" height="500" loading="lazy">
14359</div>
14360    <h4 class="bp-mega__promo-title">Digital Catalog</h4><div class="bp-mega__promo-copy"><p>Turn the page. Your best style era starts here.&nbsp;</p></div><span class="bp-mega__promo-cta">Shop Now</span>
14361  </a>
14362</div>
14363
14364</div></div>
14365      </div>
14366    </div></li><li class="bp-mm-item" data-bp-mm-id="ATVRxYnVkRFJjc0I3R__bp_menu_styleedit"><button type="button" class="bp-mm-item__row" data-open-view="ATVRxYnVkRFJjc0I3R__bp_menu_styleedit">
14367      <span class="bp-mm-item__label">styleEDIT</span>
14368      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14369  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14370</svg>
14371</span>
14372    </button>
14373
14374    <section class="bp-mm-view" data-view="ATVRxYnVkRFJjc0I3R__bp_menu_styleedit" hidden>
14375      <header class="bp-mm-view__header">
14376        <button type="button" class="bp-mm-view__back" data-back>
14377          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14378  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14379</svg>
14380</span>
14381          <span>styleEDIT</span>
14382        </button>
14383        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14384  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14385  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14386</svg>
14387</button>
14388      </header><div class="bp-mm-view__sections"><section class="bp-mm-section">
14389              <p class="bp-mm-section__heading"><a href="/blogs/styleedit">styleEDIT: What's New</a></p><ul class="bp-mm-section__links"><li><a href="/pages/new-to-boston-proper">New to Boston Proper? Start Here</a></li><li><a href="/blogs/styleedit/defy-all-expectations-why-style-doesn-t-expire-it-evolves">Why Style Doesn't Expire. It Evolves.</a></li><li><a href="https://www.bostonproper.com/blogs/styleedit/denim-dresses-are-back-here-s-how-to-wear-them-now">How to Wear Denim Dresses</a></li><li><a href="/blogs/styleedit">Read All</a></li></ul></section><section class="bp-mm-section">
14390              <p class="bp-mm-section__heading"><a href="/collections/new-arrivals">Trending Now</a></p><ul class="bp-mm-section__links"><li><a href="/collections/featured-shop-animal-prints">Animal Prints</a></li><li><a href="/collections/featured-shops-matching-sets">Matching Sets</a></li><li><a href="/collections/color-crush-wine">Trending Color: Wine</a></li><li><a href="/collections/featured-shop-intricate-details">Intricate Details</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li></ul></section><section class="bp-mm-section">
14391              <p class="bp-mm-section__heading"><a href="/blogs/styleedit">Discover</a></p><ul class="bp-mm-section__links"><li><a href="/pages/behind-the-seams">Behind the Seams</a></li><li><a href="/pages/sheryls-loves">Sheryl's Loves</a></li><li><a href="/pages/digital-catalog">Digital Catalog</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo">
14392  <a href="/pages/sheryls-loves" class="bp-mega__promo-link">
14393    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_65.jpg?v=1790780283&amp;width=400" alt="Sheryl’s Loves" srcset="//www.bostonproper.com/cdn/shop/files/Image_65.jpg?v=1790780283&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_65.jpg?v=1790780283&amp;width=400 400w" width="400" height="500" loading="lazy">
14394</div>
14395    <h4 class="bp-mega__promo-title">Sheryl’s Loves</h4><div class="bp-mega__promo-copy"><p>“These pieces feel so me. Feminine, confident, and exactly how I want to show up right now.”&nbsp;
—Sheryl, Editor-in-Chic&nbsp;</p></div><span class="bp-mega__promo-cta">Shop Now</span>
14396  </a>
14397</div>
14398
14399<div class="bp-mega__promo">
14400  <a href="/pages/digital-catalog" class="bp-mega__promo-link">
14401    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_75.jpg?v=1790800820&amp;width=400" alt="Digital Catalog" srcset="//www.bostonproper.com/cdn/shop/files/Image_75.jpg?v=1790800820&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_75.jpg?v=1790800820&amp;width=400 400w" width="400" height="500" loading="lazy">
14402</div>
14403    <h4 class="bp-mega__promo-title">Digital Catalog</h4><div class="bp-mega__promo-copy"><p>Turn the page. Your best style era starts here.&nbsp;</p></div><span class="bp-mega__promo-cta">Shop Now</span>
14404  </a>
14405</div>
14406
14407</div></section></li>
14408
14409
14410
14411<li
14412  role="presentation"
14413  class="menu-list__list-item bp-menu-item-li"
14414  data-bp-menu-item
14415  
14416><a
14417      href="/collections/brands-we-love"
14418      data-skip-node-update="true"
14419      class="menu-list__link"
14420      aria-controls="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands"
14421      aria-haspopup="true"
14422      aria-expanded="false"
14423      ref="menuitem"
14424    >
14425      <span class="menu-list__link-title">Brands We Love</span>
14426    </a>
14427    <div class="bp-mega-submenu" id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands">
14428      <div class="bp-mega-submenu__inner">
14429        <div class="bp-mega bp-mega--tabs-promos"><div class="bp-mega__tabs" data-bp-mega-tabs data-bp-tab-columns="2">
14430              <ul class="bp-mega__tabs-list" role="tablist"><li role="presentation">
14431                    <button
14432                      type="button"
14433                      role="tab"
14434                      id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-tab-0"
14435                      class="bp-mega__tab is-active"
14436                      aria-controls="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-panel-0"
14437                      aria-selected="true"
14438                      data-bp-mega-tab
14439                    >
14440                      <span class="bp-mega__tab-label">BRANDS WE LOVE</span>
14441                      <span class="bp-mega__tab-chevron" aria-hidden="true">
14442                        <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
14443                          <path d="M23.8674 11.8674C23.9116 11.8244 23.9558 11.7814 24 11.7385C24.0872 11.8256 24.1744 11.9128 24.2615 12C24.2186 12.0442 24.1756 12.0884 24.1326 12.1326C23.8696 12.4029 23.6066 12.6733 23.3436 12.9436C20.9768 15.3768 18.6099 17.8099 16.2431 20.2431V19.7569C18.6762 22.1238 21.1094 24.4906 23.5425 26.8575C23.8129 27.1205 24.0832 27.3835 24.3536 27.6464C24.473 27.7627 24.5925 27.8789 24.712 27.9951C24.473 28.2341 24.2341 28.473 23.9951 28.712C23.8789 28.5925 23.7627 28.473 23.6464 28.3536C23.3835 28.0832 23.1205 27.8129 22.8575 27.5425C20.4906 25.1094 18.1238 22.6762 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1901 17.3901 20.6232 15.0232 23.0564 12.6564C23.3267 12.3934 23.5971 12.1304 23.8674 11.8674Z" fill="currentColor"/>
14444                          <path d="M23.6464 11.6464C23.7627 11.527 23.8789 11.4075 23.9951 11.288C24.2341 11.527 24.473 11.7659 24.712 12.0049C24.5925 12.1211 24.473 12.2373 24.3536 12.3536C24.0832 12.6165 23.8129 12.8795 23.5425 13.1425C21.1094 15.5094 18.6762 17.8762 16.2431 20.2431V19.7569C18.6099 22.1901 20.9768 24.6232 23.3436 27.0564C23.6066 27.3267 23.8696 27.5971 24.1326 27.8674C24.1756 27.9116 24.2186 27.9558 24.2615 28C24.1744 28.0872 24.0872 28.1744 24 28.2615C23.9558 28.2186 23.9116 28.1756 23.8674 28.1326C23.5971 27.8696 23.3267 27.6066 23.0564 27.3436C20.6232 24.9768 18.1901 22.6099 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1238 17.3238 20.4906 14.8906 22.8575 12.4575C23.1205 12.1871 23.3835 11.9168 23.6464 11.6464Z" fill="currentColor"/>
14445                        </svg>
14446                      </span>
14447                    </button>
14448                  </li><li role="presentation">
14449                    <button
14450                      type="button"
14451                      role="tab"
14452                      id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-tab-1"
14453                      class="bp-mega__tab"
14454                      aria-controls="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-panel-1"
14455                      aria-selected="false"
14456                      data-bp-mega-tab
14457                    >
14458                      <span class="bp-mega__tab-label">JEWELRY & ACCESSORIES</span>
14459                      <span class="bp-mega__tab-chevron" aria-hidden="true">
14460                        <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
14461                          <path d="M23.8674 11.8674C23.9116 11.8244 23.9558 11.7814 24 11.7385C24.0872 11.8256 24.1744 11.9128 24.2615 12C24.2186 12.0442 24.1756 12.0884 24.1326 12.1326C23.8696 12.4029 23.6066 12.6733 23.3436 12.9436C20.9768 15.3768 18.6099 17.8099 16.2431 20.2431V19.7569C18.6762 22.1238 21.1094 24.4906 23.5425 26.8575C23.8129 27.1205 24.0832 27.3835 24.3536 27.6464C24.473 27.7627 24.5925 27.8789 24.712 27.9951C24.473 28.2341 24.2341 28.473 23.9951 28.712C23.8789 28.5925 23.7627 28.473 23.6464 28.3536C23.3835 28.0832 23.1205 27.8129 22.8575 27.5425C20.4906 25.1094 18.1238 22.6762 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1901 17.3901 20.6232 15.0232 23.0564 12.6564C23.3267 12.3934 23.5971 12.1304 23.8674 11.8674Z" fill="currentColor"/>
14462                          <path d="M23.6464 11.6464C23.7627 11.527 23.8789 11.4075 23.9951 11.288C24.2341 11.527 24.473 11.7659 24.712 12.0049C24.5925 12.1211 24.473 12.2373 24.3536 12.3536C24.0832 12.6165 23.8129 12.8795 23.5425 13.1425C21.1094 15.5094 18.6762 17.8762 16.2431 20.2431V19.7569C18.6099 22.1901 20.9768 24.6232 23.3436 27.0564C23.6066 27.3267 23.8696 27.5971 24.1326 27.8674C24.1756 27.9116 24.2186 27.9558 24.2615 28C24.1744 28.0872 24.0872 28.1744 24 28.2615C23.9558 28.2186 23.9116 28.1756 23.8674 28.1326C23.5971 27.8696 23.3267 27.6066 23.0564 27.3436C20.6232 24.9768 18.1901 22.6099 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1238 17.3238 20.4906 14.8906 22.8575 12.4575C23.1205 12.1871 23.3835 11.9168 23.6464 11.6464Z" fill="currentColor"/>
14463                        </svg>
14464                      </span>
14465                    </button>
14466                  </li><li role="presentation">
14467                    <button
14468                      type="button"
14469                      role="tab"
14470                      id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-tab-2"
14471                      class="bp-mega__tab"
14472                      aria-controls="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-panel-2"
14473                      aria-selected="false"
14474                      data-bp-mega-tab
14475                    >
14476                      <span class="bp-mega__tab-label">ATHLEISURE</span>
14477                      <span class="bp-mega__tab-chevron" aria-hidden="true">
14478                        <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
14479                          <path d="M23.8674 11.8674C23.9116 11.8244 23.9558 11.7814 24 11.7385C24.0872 11.8256 24.1744 11.9128 24.2615 12C24.2186 12.0442 24.1756 12.0884 24.1326 12.1326C23.8696 12.4029 23.6066 12.6733 23.3436 12.9436C20.9768 15.3768 18.6099 17.8099 16.2431 20.2431V19.7569C18.6762 22.1238 21.1094 24.4906 23.5425 26.8575C23.8129 27.1205 24.0832 27.3835 24.3536 27.6464C24.473 27.7627 24.5925 27.8789 24.712 27.9951C24.473 28.2341 24.2341 28.473 23.9951 28.712C23.8789 28.5925 23.7627 28.473 23.6464 28.3536C23.3835 28.0832 23.1205 27.8129 22.8575 27.5425C20.4906 25.1094 18.1238 22.6762 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1901 17.3901 20.6232 15.0232 23.0564 12.6564C23.3267 12.3934 23.5971 12.1304 23.8674 11.8674Z" fill="currentColor"/>
14480                          <path d="M23.6464 11.6464C23.7627 11.527 23.8789 11.4075 23.9951 11.288C24.2341 11.527 24.473 11.7659 24.712 12.0049C24.5925 12.1211 24.473 12.2373 24.3536 12.3536C24.0832 12.6165 23.8129 12.8795 23.5425 13.1425C21.1094 15.5094 18.6762 17.8762 16.2431 20.2431V19.7569C18.6099 22.1901 20.9768 24.6232 23.3436 27.0564C23.6066 27.3267 23.8696 27.5971 24.1326 27.8674C24.1756 27.9116 24.2186 27.9558 24.2615 28C24.1744 28.0872 24.0872 28.1744 24 28.2615C23.9558 28.2186 23.9116 28.1756 23.8674 28.1326C23.5971 27.8696 23.3267 27.6066 23.0564 27.3436C20.6232 24.9768 18.1901 22.6099 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1238 17.3238 20.4906 14.8906 22.8575 12.4575C23.1205 12.1871 23.3835 11.9168 23.6464 11.6464Z" fill="currentColor"/>
14481                        </svg>
14482                      </span>
14483                    </button>
14484                  </li><li role="presentation">
14485                    <button
14486                      type="button"
14487                      role="tab"
14488                      id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-tab-3"
14489                      class="bp-mega__tab"
14490                      aria-controls="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-panel-3"
14491                      aria-selected="false"
14492                      data-bp-mega-tab
14493                    >
14494                      <span class="bp-mega__tab-label">HEALTH & BEAUTY</span>
14495                      <span class="bp-mega__tab-chevron" aria-hidden="true">
14496                        <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
14497                          <path d="M23.8674 11.8674C23.9116 11.8244 23.9558 11.7814 24 11.7385C24.0872 11.8256 24.1744 11.9128 24.2615 12C24.2186 12.0442 24.1756 12.0884 24.1326 12.1326C23.8696 12.4029 23.6066 12.6733 23.3436 12.9436C20.9768 15.3768 18.6099 17.8099 16.2431 20.2431V19.7569C18.6762 22.1238 21.1094 24.4906 23.5425 26.8575C23.8129 27.1205 24.0832 27.3835 24.3536 27.6464C24.473 27.7627 24.5925 27.8789 24.712 27.9951C24.473 28.2341 24.2341 28.473 23.9951 28.712C23.8789 28.5925 23.7627 28.473 23.6464 28.3536C23.3835 28.0832 23.1205 27.8129 22.8575 27.5425C20.4906 25.1094 18.1238 22.6762 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1901 17.3901 20.6232 15.0232 23.0564 12.6564C23.3267 12.3934 23.5971 12.1304 23.8674 11.8674Z" fill="currentColor"/>
14498                          <path d="M23.6464 11.6464C23.7627 11.527 23.8789 11.4075 23.9951 11.288C24.2341 11.527 24.473 11.7659 24.712 12.0049C24.5925 12.1211 24.473 12.2373 24.3536 12.3536C24.0832 12.6165 23.8129 12.8795 23.5425 13.1425C21.1094 15.5094 18.6762 17.8762 16.2431 20.2431V19.7569C18.6099 22.1901 20.9768 24.6232 23.3436 27.0564C23.6066 27.3267 23.8696 27.5971 24.1326 27.8674C24.1756 27.9116 24.2186 27.9558 24.2615 28C24.1744 28.0872 24.0872 28.1744 24 28.2615C23.9558 28.2186 23.9116 28.1756 23.8674 28.1326C23.5971 27.8696 23.3267 27.6066 23.0564 27.3436C20.6232 24.9768 18.1901 22.6099 15.7569 20.2431L15.514 19.9933L15.7569 19.7569C18.1238 17.3238 20.4906 14.8906 22.8575 12.4575C23.1205 12.1871 23.3835 11.9168 23.6464 11.6464Z" fill="currentColor"/>
14499                        </svg>
14500                      </span>
14501                    </button>
14502                  </li></ul>
14503
14504              <div class="bp-mega__tabs-panels"><div
14505                    id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-panel-0"
14506                    role="tabpanel"
14507                    aria-labelledby="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-tab-0"
14508                    class="bp-mega__tab-panel is-active"
14509                    data-bp-mega-panel
14510                    
14511                  >
14512                    <p class="bp-mega__heading"><a href="/pages/brands-we-love">BRANDS WE LOVE</a></p><ul class="bp-mega__links"><li><a href="/pages/brands-we-love">View All Brands</a></li><li><a href="/collections/all-brands-we-love">Shop All</a></li><li><a href="/collections/brands-we-love-amsterdam-heritage">Amsterdam Heritage</a></li><li><a href="/collections/brands-we-love-a-rose">A.Rose</a></li><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-anatomie">Anatomie</a></li><li><a href="/collections/brands-we-love-becca">Becca By Rebecca Virtue</a></li><li><a href="/collections/brands-we-love-carmen-marc-valvo">Carmen Marc Valvo</a></li><li><a href="/collections/brands-we-love-change-of-scenery">
14512Change of Scenery</a></li><li><a href="/collections/brands-we-love-ettika">Ettika</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-hanky-panky">Hanky Panky</a></li><li><a href="/collections/brands-we-love-hat-attack-new-york">Hat Attack</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-mdaire">MDAiRE</a></li><li><a href="/collections/brands-we-love-miami-chains-co">Miami Chains & Co.</a></li><li><a href="/collections/brands-we-love-mimosa-lane">Mimosa Lane</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini x Boston Proper</a></li><li><a href="/collections/brands-we-love-prolon-life">Prolon Life</a></li><li><a href="/collections/brands-we-love-pq-swim">PQ Swim X Boston Proper</a></li><li><a href="/collections/brands-we-love-saint-jo">Saint Jō</a></li><li><a href="/collections/brands-we-love-st-moran">St. Moran</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li><li><a href="/collections/brands-we-love-the-sak">The Sak</a></li><li><a href="/collections/brands-we-love-t-jazelle">T. Jazelle</a></li><li><a href="/collections/brands-we-love-trina-turk">Trina Turk</a></li><li><a href="/collections/brands-we-love-walter-baker">Walter Baker</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></div><div
14513                    id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-panel-1"
14514                    role="tabpanel"
14515                    aria-labelledby="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-tab-1"
14516                    class="bp-mega__tab-panel"
14517                    data-bp-mega-panel
14518                    hidden
14519                  >
14520                    <p class="bp-mega__heading"><a href="/collections/brands-we-love-jewelry">JEWELRY & ACCESSORIES</a></p><ul class="bp-mega__links"><li><a href="/collections/brands-we-love-jewelry">Shop All</a></li><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-amsterdam-heritage">Amsterdam Heritage</a></li><li><a href="/collections/brands-we-love-ettika">Ettika</a></li><li><a href="/collections/brands-we-love-st-moran">St. Moran</a></li><li><a href="/collections/brands-we-love-t-jazelle">T. Jazelle</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-hat-attack-new-york">Hat Attack</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-miami-chains-co">Miami Chains & Co.</a></li><li><a href="/collections/brands-we-love-the-sak">The Sak</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></div><div
14521                    id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-panel-2"
14522                    role="tabpanel"
14523                    aria-labelledby="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-tab-2"
14524                    class="bp-mega__tab-panel"
14525                    data-bp-mega-panel
14526                    hidden
14527                  >
14528                    <p class="bp-mega__heading"><a href="/collections/all-brands-we-love">ATHLEISURE</a></p><ul class="bp-mega__links"><li><a href="/collections/brands-we-love-anatomie">Anatomie</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini X Boston Proper</a></li></ul></div><div
14529                    id="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-panel-3"
14530                    role="tabpanel"
14531                    aria-labelledby="bp-submenu-AUm5TVW95VENzMmkzb__bp_menu_brands-tab-3"
14532                    class="bp-mega__tab-panel"
14533                    data-bp-mega-panel
14534                    hidden
14535                  >
14536                    <p class="bp-mega__heading"><a href="/collections/brands-we-love-health-and-beauty">HEALTH & BEAUTY</a></p><ul class="bp-mega__links"><li><a href="/collections/brands-we-love-health-and-beauty">Shop All</a></li><li><a href="/collections/brands-we-love-mdaire">MDAiRE</a></li><li><a href="/collections/brands-we-love-mimosa-lane">Mimosa Lane</a></li><li><a href="/collections/brands-we-love-prolon-life">Prolon Life</a></li><li><a href="/collections/brands-we-love-saint-jo">SAINT Jō</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li></ul></div></div><div class="bp-mega__promos bp-mega__promos--tabs"><div class="bp-mega__promo">
14537  <a href="/collections/brands-we-love-ettika" class="bp-mega__promo-link">
14538    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&amp;width=400" alt="Ettika" srcset="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&amp;width=400 400w" width="400" height="625" loading="lazy">
14539</div>
14540    <h4 class="bp-mega__promo-title">Ettika</h4><span class="bp-mega__promo-cta">Shop Now</span>
14541  </a>
14542</div>
14543
14544<div class="bp-mega__promo">
14545  <a href="/collections/brands-we-love-saint-jo" class="bp-mega__promo-link">
14546    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&amp;width=400" alt="SAINT Jō" srcset="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&amp;width=400 400w" width="400" height="501" loading="lazy" style="object-position:50.0% 75.781%;">
14547</div>
14548    <h4 class="bp-mega__promo-title">SAINT Jō</h4><span class="bp-mega__promo-cta">Shop Now</span>
14549  </a>
14550</div>
14551
14552</div></div></div>
14553      </div>
14554    </div></li><li class="bp-mm-item" data-bp-mm-id="AUm5TVW95VENzMmkzb__bp_menu_brands"><button type="button" class="bp-mm-item__row" data-open-view="AUm5TVW95VENzMmkzb__bp_menu_brands">
14555      <span class="bp-mm-item__label">Brands We Love</span>
14556      <span class="bp-mm-item__chevron" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14557  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14558</svg>
14559</span>
14560    </button>
14561
14562    <section class="bp-mm-view" data-view="AUm5TVW95VENzMmkzb__bp_menu_brands" hidden>
14563      <header class="bp-mm-view__header">
14564        <button type="button" class="bp-mm-view__back" data-back>
14565          <span class="bp-mm-view__back-icon" aria-hidden="true"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14566  <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14567</svg>
14568</span>
14569          <span>Brands We Love</span>
14570        </button>
14571        <button type="button" class="bp-mm-view__close" data-close aria-label="Close menu"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
14572  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14573  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
14574</svg>
14575</button>
14576      </header><div class="bp-mm-view__sections"><section class="bp-mm-section">
14577              <p class="bp-mm-section__heading"><a href="/pages/brands-we-love">BRANDS WE LOVE</a></p><ul class="bp-mm-section__links"><li><a href="/pages/brands-we-love">View All Brands</a></li><li><a href="/collections/all-brands-we-love">Shop All</a></li><li><a href="/collections/brands-we-love-amsterdam-heritage">Amsterdam Heritage</a></li><li><a href="/collections/brands-we-love-a-rose">A.Rose</a></li><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-anatomie">Anatomie</a></li><li><a href="/collections/brands-we-love-becca">Becca By Rebecca Virtue</a></li><li><a href="/collections/brands-we-love-carmen-marc-valvo">Carmen Marc Valvo</a></li><li><a href="/collections/brands-we-love-change-of-scenery">Change of Scenery</a></li><li><a href="/collections/brands-we-love-ettika">Ettika</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-hanky-panky">Hanky Panky</a></li><li><a href="/collections/brands-we-love-hat-attack-new-york">Hat Attack</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-mdaire">MDAiRE</a></li><li><a href="/collections/brands-we-love-miami-chains-co">Miami Chains & Co.</a></li><li><a href="/collections/brands-we-love-mimosa-lane">Mimosa Lane</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini x Boston Proper</a></li><li><a href="/collections/brands-we-love-prolon-life">Prolon Life</a></li><li><a href="/collections/brands-we-love-pq-swim">PQ Swim X Boston Proper</a></li><li><a href="/collections/brands-we-love-saint-jo">Saint Jō</a></li><li><a href="/collections/brands-we-love-st-moran">St. Moran</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li><li><a href="/collections/brands-we-love-the-sak">The Sak</a></li><li><a href="/collections/brands-we-love-t-jazelle">T. Jazelle</a></li><li><a href="/collections/brands-we-love-trina-turk">Trina Turk</a></li><li><a href="/collections/brands-we-love-walter-baker">Walter Baker</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></section><section class="bp-mm-section">
14578              <p class="bp-mm-section__heading"><a href="/collections/brands-we-love-jewelry">JEWELRY & ACCESSORIES</a></p><ul class="bp-mm-section__links"><li><a href="/collections/brands-we-love-jewelry">Shop All</a></li><li><a href="/collections/brands-we-love-ana-luisa">Ana Luisa</a></li><li><a href="/collections/brands-we-love-amsterdam-heritage">Amsterdam Heritage</a></li><li><a href="/collections/brands-we-love-ettika">Ettika</a></li><li><a href="/collections/brands-we-love-st-moran">St. Moran</a></li><li><a href="/collections/brands-we-love-t-jazelle">T. Jazelle</a></li><li><a href="/collections/brands-we-love-fifth-and-ninth">Fifth & Ninth</a></li><li><a href="/collections/brands-we-love-hat-attack-new-york">Hat Attack</a></li><li><a href="/collections/brands-we-love-jardin-jewelry">Jardin Jewelry</a></li><li><a href="/collections/brands-we-love-miami-chains-co">Miami Chains & Co.</a></li><li><a href="/collections/brands-we-love-the-sak">The Sak</a></li><li><a href="/collections/brands-we-love-w-y-e-t-h">WYETH</a></li></ul></section><section class="bp-mm-section">
14579              <p class="bp-mm-section__heading"><a href="/collections/all-brands-we-love">ATHLEISURE</a></p><ul class="bp-mm-section__links"><li><a href="/collections/brands-we-love-anatomie">Anatomie</a></li><li><a href="/collections/brands-we-love-pickletini">Pickletini X Boston Proper</a></li></ul></section><section class="bp-mm-section">
14580              <p class="bp-mm-section__heading"><a href="/collections/brands-we-love-health-and-beauty">HEALTH & BEAUTY</a></p><ul class="bp-mm-section__links"><li><a href="/collections/brands-we-love-health-and-beauty">Shop All</a></li><li><a href="/collections/brands-we-love-mdaire">MDAiRE</a></li><li><a href="/collections/brands-we-love-mimosa-lane">Mimosa Lane</a></li><li><a href="/collections/brands-we-love-prolon-life">Prolon Life</a></li><li><a href="/collections/brands-we-love-saint-jo">SAINT Jō</a></li><li><a href="/collections/brands-we-love-sum-of-all">Sum Of All</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo">
14581  <a href="/collections/brands-we-love-ettika" class="bp-mega__promo-link">
14582    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&amp;width=400" alt="Ettika" srcset="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&amp;width=400 400w" width="400" height="625" loading="lazy">
14583</div>
14584    <h4 class="bp-mega__promo-title">Ettika</h4><span class="bp-mega__promo-cta">Shop Now</span>
14585  </a>
14586</div>
14587
14588<div class="bp-mega__promo">
14589  <a href="/collections/brands-we-love-saint-jo" class="bp-mega__promo-link">
14590    <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&amp;width=400" alt="SAINT Jō" srcset="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&amp;width=200 200w, //www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&amp;width=400 400w" width="400" height="501" loading="lazy" style="object-position:50.0% 75.781%;">
14591</div>
14592    <h4 class="bp-mega__promo-title">SAINT Jō</h4><span class="bp-mega__promo-cta">Shop Now</span>
14593  </a>
14594</div>
14595
14596</div></section></li>
14597
14598
14599
14600
14601
14602      <li
14603        class="menu-list__list-item"
14604        role="presentation"
14605        slot="more"
14606        on:focus="/activate"
14607        on:blur="/deactivate"
14608        on:pointerenter="/activate"
14609        on:pointerleave="/deactivate"
14610      ><button class="menu-list__link button-unstyled">
14611          <span class="menu-list__link-title">More</span>
14612        </button>
14613      </li>
14614    
14615</overflow-list>
14616
14617        </nav>
14618      </div>
14619
14620      
14620<script
14621        src="//www.bostonproper.com/cdn/shop/t/1521/assets/header-menu.js?v=13599797148522725401790713714"
14622        type="module"
14623        fetchpriority="low"
14624      ></script>
14624
14625    </header-menu>
14626
14627
14628<style data-shopify>
14629  .header__underlay {
14630    --color-submenu: rgb(254 255 250 / 1.0);
14631  }
14632</style>
14633
14634
14635
14636
14637            
14638        
14639      
14640    </div><div
14641      class="header__column header__column--right"
14642      data-testid="header-top-right"
14643    >
14644      
14645        
14646          
14647              
14648  
14649  
14650
14651            
14652        
14653      
14654        
14655          
14656              
14657  <search-button
14658    class="search-action search-action--hidden-on-drawer"
14659  >
14660    <button
14661      on:click="#search-modal/showDialog"
14662      class="button-unstyled header-actions__action"
14663      aria-label="Search"
14664      aria-haspopup="dialog"
14665    >
14666      <span class="hidden">
14667        Search
14668      </span>
14669
14670      <span class="svg-wrapper ">
14671        <svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
14672<path d="M30.6967 19.7055C30.7183 23.8405 27.932 27.3926 24.0949 28.7508C17.6703 31.1232 10.0267 26.8687 10 19.7055C10.0272 12.5414 17.6703 8.28779 24.0953 10.6602C27.932 12.0184 30.7187 15.5704 30.6967 19.7055ZM28.5408 19.7055C28.5477 16.9739 27.3344 14.2088 25.1509 12.5164C22.4003 10.326 18.2959 10.3256 15.5454 12.5164C13.3619 14.2088 12.1486 16.9735 12.1555 19.7055C12.1486 22.437 13.3619 25.2022 15.5454 26.8946C18.2959 29.085 22.4003 29.0854 25.1509 26.8946C27.3344 25.2022 28.5477 22.4374 28.5408 19.7055Z" fill="currentColor"/>
14673<path d="M33.1718 33.9998C31.5945 32.7679 30.2255 31.2984 28.9126 29.7966C28.4814 29.2934 28.0606 28.7816 27.6699 28.2439L28.9794 27.1216C29.4511 27.5898 29.8927 28.084 30.3238 28.5872C31.3971 29.854 32.4207 31.1661 33.3132 32.5696C33.4917 32.8528 33.6659 33.1396 33.8263 33.4388L33.1714 34.0002L33.1718 33.9998Z" fill="currentColor"/>
14674</svg>
14675
14676      </span>
14677    </button>
14678  </search-button>
14679
14680
14681
14682
14683            
14684        
14685      
14686        
14687          
14688              
14689
14690<script
14691  type="module"
14692  src="//www.bostonproper.com/cdn/shop/t/1521/assets/cart-icon.js?v=157241182139685326961790713714"
14693  fetchpriority="low"
14694></script>
14694
14695
14696
14697
14698
14699<header-actions
14700  
14701  data-bp-mobile-account="hamburger">
14702  
14703<bp-saved-drawer class="bp-saved-drawer" data-hydration-key="bp-saved-drawer">
14704  <button
14705    type="button"
14706    class="bp-saved-drawer__trigger header-actions__action"
14707    data-bp-saved-open
14708    aria-haspopup="dialog"
14709    aria-label="Saved for later"
14710  ><svg width="24" height="24" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
14711      <path d="M22.1364 34C22.0452 33.9982 21.9449 33.964 21.8658 33.9141L21.8316 33.8952L21.7642 33.8575C21.4558 33.6826 21.1514 33.4983 20.8515 33.3099C15.6957 30.0059 10.1181 24.467 10.0003 17.9623C9.97376 14.3139 11.7681 10.6318 15.693 10.0815C16.2307 10.0038 16.7679 9.98353 17.311 10.0127C19.188 10.1018 20.6434 11.2765 21.4931 12.8915C21.8946 13.6378 22.1791 14.4241 22.3608 15.2504L21.9202 14.8926H22.3527L21.9121 15.2504C22.0937 14.4245 22.3783 13.6378 22.7802 12.8919C23.393 11.7378 24.3673 10.7119 25.6338 10.2771C26.372 10.011 27.1588 9.97409 27.9316 10.0163C28.1434 10.0262 28.37 10.0537 28.5804 10.0829C32.3843 10.6147 34.184 14.0775 34.273 17.6341C34.3472 24.275 28.6604 29.9519 23.4218 33.3094C23.1646 33.4704 22.9057 33.6291 22.6427 33.7815L22.5096 33.857L22.4422 33.8948C22.3527 33.951 22.2416 33.9955 22.1373 33.9995L22.1364 34ZM22.1364 33.1008C22.0735 33.0891 21.9665 33.1211 21.9359 33.1426L21.9431 33.1377C21.9728 33.1175 22.0982 33.0248 22.1333 32.9997C27.2231 29.1984 33.9673 22.4766 32.1775 15.5337C31.6438 13.4328 30.4057 11.8228 28.2045 11.3727C27.4753 11.2325 26.6975 11.1511 25.975 11.3507C24.5561 11.732 23.6255 13.0434 23.1179 14.3621C22.9371 14.8166 22.8113 15.3147 22.7164 15.7926H22.3527C22.1558 15.7926 21.7525 15.7926 21.5569 15.7926C21.4621 15.3152 21.3362 14.8166 21.155 14.3621C20.3821 12.3938 18.9893 10.9663 16.7391 11.2711C15.8701 11.3597 14.9934 11.6223 14.2727 12.1182C12.8008 13.1113 12.1241 14.893 11.8872 16.596C10.9885 23.1456 17.307 29.3895 22.14 32.9997L22.2574 33.0855L22.3158 33.1278L22.3446 33.1485L22.3518 33.1534C22.3482 33.1521 22.3738 33.166 22.3316 33.1426C22.274 33.1125 22.2007 33.0972 22.1373 33.1017L22.1364 33.1008Z" fill="currentColor"/>
14712    </svg>
14713    <span class="bp-saved-drawer__trigger-count" data-bp-saved-trigger-count hidden></span>
14714  </button>
14715
14716  <dialog class="bp-saved-drawer__dialog" data-bp-saved-dialog aria-label="Saved for Later">
14717    <header class="bp-saved-drawer__header">
14718      <h2 class="bp-saved-drawer__heading">
14719        <span class="bp-saved-drawer__bubble" data-bp-saved-bubble>0</span>
14720        Saved for Later
14721      </h2>
14722      <button type="button" class="bp-saved-drawer__close" data-bp-saved-close aria-label="Close">
14723        <svg width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true">
14724          <path d="M5 5l10 10M15 5L5 15" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/>
14725        </svg>
14726      </button>
14727    </header>
14728
14729    <div class="bp-saved-drawer__body">
14730      <div class="bp-saved-drawer__loading" data-bp-saved-loading hidden>
14731        <span class="bp-saved-drawer__spinner" aria-hidden="true"></span>
14732        <p>Loading your saved items…</p>
14733      </div>
14734
14735      <div class="bp-saved-drawer__empty" data-bp-saved-empty>
14736        <p>No saved items yet.</p>
14737        <p class="bp-saved-drawer__empty-help">Tap the bookmark on any bag item to save it for later.</p>
14738      </div>
14739
14740      <ul class="bp-saved-drawer__list" data-bp-saved-list hidden></ul><template data-bp-saved-template>
14741        <li class="bp-saved-drawer__card" data-bp-saved-card>
14742          <a class="bp-saved-drawer__image" data-bp-card-link>
14743            <img alt="" data-bp-card-image>
14744          </a>
14745          <div class="bp-saved-drawer__details">
14746            <div class="bp-saved-drawer__title-row">
14747              <h3 class="bp-saved-drawer__name"><a data-bp-card-link></a></h3>
14748              <span class="bp-saved-drawer__price" data-bp-card-price></span>
14749            </div>
14750            <p class="bp-saved-drawer__variant" data-bp-card-variant></p>
14751            <ul class="bp-saved-drawer__props" data-bp-card-props></ul>
14752            <div class="bp-saved-drawer__actions">
14753              <button type="button" class="bp-saved-drawer__btn bp-saved-drawer__btn--primary" data-bp-card-move>Move to Bag</button>
14754              <button type="button" class="bp-saved-drawer__btn bp-saved-drawer__btn--secondary" data-bp-card-remove>Remove</button>
14755            </div>
14756          </div>
14757        </li>
14758      </template>
14759    </div>
14760  </dialog>
14761</bp-saved-drawer>
14762
14763<style data-shopify>
14764  bp-saved-drawer { display: contents; }
14765
14766  .bp-saved-drawer__trigger {
14767    position: relative;
14768    background: transparent;
14769    border: 0;
14770    padding: 0;
14771    cursor: pointer;
14772    color: var(--color-foreground);
14773    display: inline-flex;
14774    align-items: center;
14775    justify-content: center;
14776    width: 44px;
14777    height: 44px;
14778  }
14779  .bp-saved-drawer__trigger svg { width: 24px; height: 24px; display: block; }
14780  .bp-saved-drawer__trigger-count {
14781    position: absolute;
14782    top: 4px;
14783    right: 4px;
14784    min-width: 18px;
14785    height: 18px;
14786    padding: 0 5px;
14787    /* 18×18 circular notification badge — see matching note in
14788       snippets/bp-cart-drawer.liquid. Kept as a circle, not squared. */
14789    border-radius: 50%;
14790    background: #EBAE55;
14791    /* Dark ink on the gold badge — white on #EBAE55 is only 1.96:1 (fails
14792       WCAG). Matches the cart trigger-count badge. */
14793    color: var(--bp-color-text);
14794    font-family: var(--bp-font-body);
14795    font-size: 11px;
14796    font-weight: 500;
14797    display: inline-flex;
14798    align-items: center;
14799    justify-content: center;
14800  }
14801  .bp-saved-drawer__trigger-count[hidden] { display: none; }
14802  /* Loading badge — shown while we wait for Swym to reconcile, so the count
14803     never briefly shows a stale/wrong number. A quiet pulse on the empty
14804     badge; the real number replaces it once synced. */
14805  .bp-saved-drawer__trigger-count.is-loading {
14806    background: rgba(23, 22, 9, 0.18);
14807    min-width: 12px;
14808    height: 12px;
14809    padding: 0;
14810    top: 6px;
14811    right: 6px;
14812    animation: bp-saved-badge-pulse 0.9s ease-in-out infinite;
14813  }
14814  @keyframes bp-saved-badge-pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 0.9; } }
14815  @media (prefers-reduced-motion: reduce) {
14816    .bp-saved-drawer__trigger-count.is-loading { animation: none; opacity: 0.5; }
14817  }
14818
14819  .bp-saved-drawer__dialog {
14820    position: fixed;
14821    inset: 0 0 0 auto;
14822    margin: 0;
14823    padding: 0;
14824    border: 0;
14825    width: calc(100vw / 3);
14826    min-width: 480px;
14827    max-width: 100vw;
14828    height: 100dvh;
14829    max-height: 100dvh;
14830    background: var(--bp-color-bg-page);
14831    color: var(--bp-color-text);
14832    box-shadow: -8px 0 30px rgb(0 0 0 / 0.12);
14833    overflow: hidden;
14834    font-family: var(--bp-font-body);
14835    z-index: 9999;
14836  }
14837  .bp-saved-drawer__dialog[open] {
14838    display: flex;
14839    flex-direction: column;
14840    animation: bpDrawerSlideIn 0.25s cubic-bezier(0.4, 0, 0.2, 1) forwards;
14841  }
14842  .bp-saved-drawer__dialog.is-closing {
14843    animation: bpDrawerSlideOut 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
14844  }
14845  .bp-saved-drawer__dialog::backdrop { background: rgb(0 0 0 / 0.3); }
14846  @media (max-width: 749px) {
14847    .bp-saved-drawer__dialog { width: 100vw; min-width: 0; }
14848  }
14849
14850  .bp-saved-drawer__header {
14851    flex: 0 0 auto;
14852    display: flex;
14853    align-items: center;
14854    justify-content: space-between;
14855    padding: 20px 24px;
14856    border-bottom: 1px solid rgba(23, 22, 9, 0.08);
14857    background: var(--bp-color-bg-page);
14858  }
14859  .bp-saved-drawer__heading {
14860    margin: 0;
14861    display: inline-flex;
14862    align-items: center;
14863    gap: 12px;
14864    color: var(--bp-color-text);
14865    font-family: var(--bp-font-display);
14866    font-size: 28px;
14867    font-weight: 300;
14868    line-height: 120%;
14869    letter-spacing: -0.56px;
14870  }
14871  .bp-saved-drawer__bubble {
14872    display: inline-flex;
14873    align-items: center;
14874    justify-content: center;
14875    width: 32px;
14876    height: 32px;
14877    border-radius: 50%;
14878    background: #EBAE55;
14879    /* Dark ink on the gold badge — #fff on #EBAE55 is only 1.96:1 (WCAG fail).
14880       #171609 clears AA at 9.3:1. Same fix already applied to the cart count
14881       badge (QA 7/27, contrast audit — last of the gold-badge group). */
14882    color: var(--bp-color-text, #171609);
14883    font-family: var(--bp-font-body);
14884    font-size: 14px;
14885    font-weight: 500;
14886  }
14887  .bp-saved-drawer__close {
14888    background: transparent;
14889    border: 0;
14890    padding: 0;
14891    width: 32px;
14892    height: 32px;
14893    cursor: pointer;
14894    color: var(--bp-color-text);
14895    display: inline-flex;
14896    align-items: center;
14897    justify-content: center;
14898  }
14899  .bp-saved-drawer__close:hover { opacity: 0.6; }
14900
14901  .bp-saved-drawer__body {
14902    flex: 1 1 auto;
14903    overflow-y: auto;
14904    padding: 0 24px 24px;
14905  }
14906  .bp-saved-drawer__empty {
14907    padding: 48px 0;
14908    text-align: center;
14909    color: var(--bp-color-body-copy);
14910  }
14911  .bp-saved-drawer__loading {
14912    padding: 48px 0;
14913    text-align: center;
14914    color: var(--bp-color-body-copy);
14915    display: flex;
14916    flex-direction: column;
14917    align-items: center;
14918    gap: 12px;
14919  }
14920  .bp-saved-drawer__loading[hidden] { display: none; }
14921  .bp-saved-drawer__spinner {
14922    width: 28px;
14923    height: 28px;
14924    border: 2px solid rgba(23, 22, 9, 0.18);
14925    border-top-color: var(--bp-color-text, #171609);
14926    border-radius: 50%;
14927    animation: bp-saved-spin 0.7s linear infinite;
14928  }
14929  @keyframes bp-saved-spin { to { transform: rotate(360deg); } }
14930  @media (prefers-reduced-motion: reduce) {
14931    .bp-saved-drawer__spinner { animation-duration: 1.6s; }
14932  }
14933  .bp-saved-drawer__empty-help {
14934    margin-top: 4px;
14935    color: var(--bp-color-body-copy);
14936    font-size: 13px;
14937  }
14938
14939  .bp-saved-drawer__list {
14940    list-style: none;
14941    margin: 0;
14942    padding: 0;
14943    display: flex;
14944    flex-direction: column;
14945  }
14946
14947  .bp-saved-drawer__card {
14948    display: grid;
14949    grid-template-columns: 110px 1fr;
14950    gap: 16px;
14951    padding: 20px 0;
14952    border-bottom: 1px solid rgba(23, 22, 9, 0.08);
14953  }
14954  .bp-saved-drawer__card:last-child { border-bottom: 0; }
14955
14956  .bp-saved-drawer__image {
14957    display: block;
14958    width: 110px;
14959    aspect-ratio: 4 / 5;
14960    background: var(--bp-color-bg-cream);
14961    overflow: hidden;
14962  }
14963  .bp-saved-drawer__image img {
14964    width: 100%;
14965    height: 100%;
14966    object-fit: cover;
14967    display: block;
14968  }
14969  .bp-saved-drawer__details {
14970    display: flex;
14971    flex-direction: column;
14972    gap: 6px;
14973    min-width: 0;
14974  }
14975  .bp-saved-drawer__title-row {
14976    display: flex;
14977    justify-content: space-between;
14978    gap: 12px;
14979    align-items: baseline;
14980  }
14981  .bp-saved-drawer__name {
14982    margin: 0;
14983    font-family: var(--bp-font-body);
14984    font-size: 14px;
14985    font-weight: 700;
14986    line-height: 145%;
14987    letter-spacing: -0.14px;
14988    color: var(--bp-color-text);
14989  }
14990  .bp-saved-drawer__name a { color: inherit; text-decoration: none; }
14991  .bp-saved-drawer__price {
14992    flex: 0 0 auto;
14993    font-size: 14px;
14994    font-weight: 700;
14995    color: var(--bp-color-text);
14996  }
14997  .bp-saved-drawer__variant {
14998    margin: 0;
14999    color: var(--bp-color-body-copy);
15000    font-size: 13px;
15001  }
15002  .bp-saved-drawer__props {
15003    list-style: none;
15004    margin: 4px 0 0;
15005    padding: 0;
15006    display: flex;
15007    flex-wrap: wrap;
15008    gap: 6px;
15009  }
15010  .bp-saved-drawer__props li {
15011    background: var(--bp-color-bg-cream);
15012    padding: 2px 8px;
15013    font-size: 11px;
15014    font-weight: 700;
15015    letter-spacing: 0.04em;
15016    text-transform: uppercase;
15017    color: var(--bp-color-text);
15018  }
15019  .bp-saved-drawer__actions {
15020    margin-top: 10px;
15021    display: flex;
15022    gap: 8px;
15023    flex-wrap: wrap;
15024  }
15025  .bp-saved-drawer__btn {
15026    height: 40px;
15027    padding: 0 16px;
15028    border: 1px solid var(--bp-color-text);
15029    cursor: pointer;
15030    font-family: var(--bp-font-body);
15031    font-size: 13px;
15032    font-weight: 500;
15033    letter-spacing: -0.13px;
15034    transition: opacity 0.2s ease, background 0.2s ease;
15035  }
15036  .bp-saved-drawer__btn--primary {
15037    background: var(--bp-color-text);
15038    color: var(--bp-color-cta-text);
15039  }
15040  .bp-saved-drawer__btn--primary:hover { opacity: 0.85; }
15041  .bp-saved-drawer__btn--primary:disabled { opacity: 0.4; cursor: wait; }
15042  /* Sold-out Move button: stays disabled + relabelled, no hover lift. */
15043  .bp-saved-drawer__btn--soldout,
15044  .bp-saved-drawer__btn--primary.bp-saved-drawer__btn--soldout:disabled {
15045    opacity: 0.4;
15046    cursor: not-allowed;
15047  }
15048  .bp-saved-drawer__btn--secondary {
15049    background: var(--bp-color-bg-page);
15050    color: var(--bp-color-text);
15051  }
15052  .bp-saved-drawer__btn--secondary:hover { background: var(--bp-color-bg-cream); }
15053  /* Sold-out marker — mirrors the cart line's unavailable treatment
15054     (snippets/bp-cart-line-item.liquid), BP promo red. */
15055  .bp-saved-drawer__unavailable {
15056    margin: 4px 0 0;
15057    font-family: var(--bp-font-body);
15058    font-size: 12px;
15059    font-weight: 700;
15060    letter-spacing: 0.04em;
15061    text-transform: uppercase;
15062    color: var(--bp-color-promo, #B5341B);
15063  }
15064  .bp-saved-drawer__card.is-unavailable .bp-saved-drawer__image,
15065  .bp-saved-drawer__card.is-unavailable .bp-saved-drawer__name {
15066    opacity: 0.55;
15067  }
15068</style>
15069
15070<script type="module">
15071  if (!customElements.get('bp-saved-drawer')) {
15072    class BpSavedDrawer extends HTMLElement {
15073      connectedCallback() {
15074        this.dialog = this.querySelector('[data-bp-saved-dialog]');
15075        this.list = this.querySelector('[data-bp-saved-list]');
15076        this.empty = this.querySelector('[data-bp-saved-empty]');
15077        this.loading = this.querySelector('[data-bp-saved-loading]');
15078        this.template = this.querySelector('[data-bp-saved-template]');
15079        this.bubble = this.querySelector('[data-bp-saved-bubble]');
15080        this.triggerCount = this.querySelector('[data-bp-saved-trigger-count]');
15081
15082        // Local trigger inside this component.
15083        const localOpener = this.querySelector('[data-bp-saved-open]');
15084        if (localOpener) localOpener.addEventListener('click', (e) => { e.preventDefault(); this.open(); });
15085
15086        // Delegated open for any element anywhere with data-bp-saved-open.
15087        // Using `once: false` lets cart-drawer footer/empty links open us too.
15088        if (!window.__bpSavedOpenWired) {
15089          window.__bpSavedOpenWired = true;
15090          document.addEventListener('click', (e) => {
15091            const trigger = e.target.closest('[data-bp-saved-open]');
15092            if (!trigger || this.contains(trigger)) return;
15093            e.preventDefault();
15094            const el = document.querySelector('bp-saved-drawer');
15095            if (el && typeof el.open === 'function') el.open();
15096          });
15097        }
15098
15099        this.dialog.addEventListener('click', (e) => {
15100          if (e.target.closest('[data-bp-saved-close]')) {
15101            e.preventDefault();
15102            this.close();
15103            return;
15104          }
15105          if (e.target === this.dialog) this.close();
15106        });
15107
15108        this.dialog.addEventListener('cancel', (e) => {
15109          e.preventDefault();
15110          this.close();
15111        });
15112
15113        // Card actions (Move to Bag / Remove).
15114        this.list.addEventListener('click', async (e) => {
15115          const card = e.target.closest('[data-bp-saved-card]');
15116          if (!card) return;
15117          const key = card.dataset.savedKey;
15118
15119          if (e.target.closest('[data-bp-card-remove]')) {
15120            this.removeSaved(key);
15121            this.render();
15122            return;
15123          }
15124          if (e.target.closest('[data-bp-card-move]')) {
15125            const moveBtn = e.target.closest('[data-bp-card-move]');
15126            moveBtn.disabled = true;
15127            moveBtn.textContent = 'Adding…';
15128            try {
15129              await this.moveToBag(key);
15130            } catch (err) {
15131              // The item is still saved — handleMoveToBag only drops the
15132              // save after /cart/add.js succeeds. Leave the card in the
15133              // list and say why, instead of dropping the shopper back to
15134              // an unchanged button with no explanation. (This branch was
15135              // unreachable until handleMoveToBag stopped swallowing add
15136              // failures: it removed the save first, warned to the console,
15137              // and returned as if it had worked — so the item disappeared
15138              // from Saved for Later without ever reaching the cart.)
15139              console.error('[bp-saved-drawer] move-to-bag failed', err);
15140              if (err && err.status === 422) {
15141                // Genuinely unsellable (sold out). Stamp it persistently
15142                // instead of flickering the label back to "Move to Bag"
15143                // after 2.6s (Dragana QA 7/22) — the item stays saved and
15144                // reads Sold out / Unavailable until stock returns.
15145                this.markUnavailable(card);
15146                if (err.description) moveBtn.title = err.description;
15147              } else {
15148                // Transient failure (network, etc.) — let them retry.
15149                moveBtn.disabled = false;
15150                moveBtn.textContent = 'Try again';
15151                moveBtn.title = (err && err.description) || 'Could not add to bag';
15152                setTimeout(() => {
15153                  moveBtn.textContent = 'Move to Bag';
15154                  moveBtn.removeAttribute('title');
15155                }, 2600);
15156              }
15157              return;
15158            }
15159            this.removeSaved(key);
15160            this.render();
15161            // Close saved drawer so the cart drawer becomes the active dialog,
15162            // then refresh + open the cart drawer.
15163            this.close();
15164            document.dispatchEvent(new CustomEvent('cart:updated'));
15165            const cartDrawer = document.querySelector('bp-cart-drawer');
15166            if (cartDrawer && typeof cartDrawer.open === 'function') {
15167              setTimeout(() => cartDrawer.open(), 220);
15168            }
15169          }
15170        });
15171
15172        // Cross-tab + same-tab sync. We listen on the legacy
15173        // `bp.saved_for_later` key AND the Swym-mirror key
15174        // `save-for-later-items` (bp-swym-helpers).
15175        window.addEventListener('storage', (e) => {
15176          if (e.key === 'bp.saved_for_later' || e.key === 'save-for-later-items') this.render();
15177        });
15178        document.addEventListener('bp:saved:updated', () => this.render());
15179        document.addEventListener('wishlist:updated', () => this.render());
15180        document.addEventListener('wishlist:item-saved', () => this.render());
15181        // Swym finished its reconcile — leave the loading state and render.
15182        document.addEventListener('bp:saved:synced', () => this.render());
15183
15184        // Migrate any pre-existing local-only entries (legacy
15185        // `bp.saved_for_later`) into the Swym-compatible mirror so
15186        // the customer doesn't lose what they already saved.
15187        this.migrateLegacy();
15188
15189        this.render();
15190      }
15191
15192      // ----- Storage adapter — prefer Swym-backed mirror -----
15193      // Returns the list of saved items either from the Swym mirror
15194      // (bp-swym-helpers) when available, falling back to the legacy
15195      // single-array `bp.saved_for_later` key for back-compat.
15196      readItems() {
15197        if (window.bpSavedForLater && typeof window.bpSavedForLater.getLocalWishlist === 'function') {
15198          const w = window.bpSavedForLater.getLocalWishlist();
15199          return Array.isArray(w && w.items) ? w.items : [];
15200        }
15201        try { return JSON.parse(localStorage.getItem('bp.saved_for_later') || '[]'); }
15202        catch (_) { return []; }
15203      }
15204      migrateLegacy() {
15205        if (!window.bpSavedForLater) return;
15206        let legacy = [];
15207        try { legacy = JSON.parse(localStorage.getItem('bp.saved_for_later') || '[]'); }
15208        catch (_) { legacy = []; }
15209        if (!Array.isArray(legacy) || !legacy.length) return;
15210        const customerId = window.bpSavedForLater.getCustomerId();
15211        const all = window.bpSavedForLater.getSavedItemsLocalStorage() || {};
15212        const current = all[customerId] || { items: [], count: 0 };
15213        // De-dupe by variant_id.
15214        const have = new Set(current.items.map((it) => String(it.variant_id)));
15215        const adapted = legacy
15216          .filter((it) => !have.has(String(it.variantId || it.variant_id)))
15217          .map((it) => ({
15218            id: String(it.productId || it.product_id || it.variantId),
15219            handle: it.handle || '',
15220            variant_id: String(it.variantId || it.variant_id),
15221            variant_price: String(it.price || it.variant_price || ''),
15222            variant_compare_at_price: String(it.compare_at_price || it.variant_compare_at_price || ''),
15223            variant_title: String(it.variantTitle || it.variant_title || ''),
15224            title: it.title || '',
15225            image: it.image || '',
15226            quantity: String(it.quantity || 1),
15227            properties: it.properties || {},
15228            variant_sku: it.sku || it.variant_sku || ''
15229          }));
15230        if (!adapted.length) return;
15231        const merged = current.items.concat(adapted);
15232        all[customerId] = { ...current, items: merged, count: merged.length };
15233        window.bpSavedForLater.storeSavedItemsLocalStorage(all);
15234        // Wipe the legacy bucket so the migration is one-shot.
15235        try { localStorage.removeItem('bp.saved_for_later'); } catch (_) {}
15236      }
15237
15238      open() {
15239        this.render();
15240        if (this.dialog.open) return;
15241        if (typeof this.dialog.showModal === 'function') this.dialog.showModal();
15242        else this.dialog.setAttribute('open', '');
15243      }
15244      close() {
15245        if (this._closing || !this.dialog.open) return;
15246        this._closing = true;
15247        this.dialog.classList.add('is-closing');
15248        const onEnd = () => {
15249          this.dialog.classList.remove('is-closing');
15250          this._closing = false;
15251          try { this.dialog.close(); } catch (_) { this.dialog.removeAttribute('open'); }
15252        };
15253        this.dialog.addEventListener('animationend', onEnd, { once: true });
15254        setTimeout(() => { if (this._closing) onEnd(); }, 350);
15255      }
15256
15257      getSaved() { return this.readItems(); }
15258      removeSaved(key) {
15259        // `key` for Swym-mirror items is variant_id; legacy items used
15260        // a `key` field. We resolve by either.
15261        const items = this.readItems();
15262        const target = items.find((i) => String(i.variant_id) === String(key) || String(i.key) === String(key));
15263        if (!target) return;
15264        if (window.bpSavedForLater && window.bpSavedForLater.removeWishlistItem) {
15265          window.bpSavedForLater.removeWishlistItem(target.id, target.variant_id);
15266        }
15267      }
15268
15269      async moveToBag(key) {
15270        const items = this.readItems();
15271        const item = items.find((i) => String(i.variant_id) === String(key) || String(i.key) === String(key));
15272        if (!item) return;
15273        const productId = item.id;
15274        const variantId = item.variant_id || item.variantId;
15275        const qty = parseInt(item.quantity, 10) || 1;
15276        const isWishlistItemProductLevel = String(productId) === String(variantId);
15277        if (typeof window.handleMoveToBag === 'function') {
15278          await window.handleMoveToBag(productId, variantId, qty, isWishlistItemProductLevel, item, null);
15279          return;
15280        }
15281        // Last-resort fallback if Swym helpers haven't loaded yet.
15282        const body = { items: [{ id: variantId, quantity: qty, properties: item.properties || {} }] };
15283        const res = await fetch('/cart/add.js', {
15284          method: 'POST',
15285          headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
15286          body: JSON.stringify(body)
15287        });
15288        if (!res.ok) throw new Error('HTTP ' + res.status);
15289      }
15290
15291      formatMoney(cents) { return '$' + (cents / 100).toFixed(2); }
15292      // Atlas's variant_price is a currency-formatted string ("$25.00" or
15293      // "2500" cents string). Normalise to cents for arithmetic.
15294      parsePriceCents(v) {
15295        if (v == null) return 0;
15296        const s = String(v).replace(/[^0-9.-]/g, '');
15297        if (!s) return 0;
15298        if (s.indexOf('.') >= 0) return Math.round(parseFloat(s) * 100);
15299        return parseInt(s, 10) || 0;
15300      }
15301
15302      // Saved entries store no availability (only id/handle/price/title/…),
15303      // so a sold-out save looked identical to an in-stock one and the only
15304      // "unavailable" hint was the transient 422 flicker on Move to Bag.
15305      // Resolve availability from /products/<handle>.js — cached per handle
15306      // (one fetch, reused across re-renders) — so each card can carry a
15307      // stable sold-out marker up front (Dragana QA 7/22).
15308      fetchProductJson(handle) {
15309        if (!handle) return Promise.resolve(null);
15310        if (!this._prodCache) this._prodCache = new Map();
15311        if (this._prodCache.has(handle)) return this._prodCache.get(handle);
15312        const p = fetch(`/products/${handle}.js`, { credentials: 'same-origin' })
15313          .then((r) => (r.ok ? r.json() : null))
15314          .catch(() => null);
15315        this._prodCache.set(handle, p);
15316        return p;
15317      }
15318
15319      // Resolves to false only when we can confirm sold-out. Unknown (fetch
15320      // failed / no handle) resolves true so we never falsely block a save —
15321      // the 422 path still catches a genuine sold-out at add time.
15322      isSavedItemAvailable(item) {
15323        const variantId = item.variant_id || item.variantId;
15324        return this.fetchProductJson(item.handle).then((product) => {
15325          if (!product) return true;
15326          const variants = product.variants || [];
15327          if (variantId) {
15328            const v = variants.find((vv) => String(vv.id) === String(variantId));
15329            // Exact saved variant known → trust its own availability.
15330            if (v) return !!v.available;
15331          }
15332          // Product-level save, or the saved variant was retired: sellable
15333          // if ANY variant is still in stock.
15334          return variants.some((vv) => vv.available);
15335        });
15336      }
15337
15338      // Stamp a card as sold out: red marker + a disabled, relabelled Move
15339      // button. Idempotent, and safe to call from both render() (proactive)
15340      // and the 422 catch (reactive) — see the Move to Bag handler.
15341      markUnavailable(node) {
15342        if (!node || node.classList.contains('is-unavailable')) return;
15343        node.classList.add('is-unavailable');
15344        const moveBtn = node.querySelector('[data-bp-card-move]');
15345        if (moveBtn) {
15346          moveBtn.disabled = true;
15347          moveBtn.textContent = 'Unavailable';
15348          moveBtn.classList.add('bp-saved-drawer__btn--soldout');
15349        }
15350        const details = node.querySelector('.bp-saved-drawer__details');
15351        if (details && !details.querySelector('[data-bp-card-unavailable]')) {
15352          const marker = document.createElement('p');
15353          marker.className = 'bp-saved-drawer__unavailable';
15354          marker.setAttribute('data-bp-card-unavailable', '');
15355          marker.textContent = 'Sold out';
15356          const actions = details.querySelector('.bp-saved-drawer__actions');
15357          if (actions) details.insertBefore(marker, actions);
15358          else details.appendChild(marker);
15359        }
15360      }
15361
15362      // Ready to render for real: Swym has reconciled the wishlist, OR we've
15363      // fallen back to localStorage after a timeout (Swym slow / errored / not
15364      // installed). Until then we show a LOADING state everywhere instead of
15365      // rendering localStorage first and then flashing when Swym swaps it in —
15366      // the single-source approach that killed the appear/vanish/reappear flash.
15367      _ready() {
15368        if (this._localFallback) return true;
15369        return !!(window.bpSavedForLater
15370          && typeof window.bpSavedForLater.isSynced === 'function'
15371          && window.bpSavedForLater.isSynced());
15372      }
15373
15374      // Kick a sync (in case the drawer mounted before the helper's load-time
15375      // sync ran) and arm a fallback so we're never stuck on the spinner.
15376      _scheduleReady() {
15377        if (this._readyWaiting) return;
15378        this._readyWaiting = true;
15379        if (window.bpSavedForLater && typeof window.bpSavedForLater.checkWishlistSync === 'function') {
15380          try { window.bpSavedForLater.checkWishlistSync(); } catch (_) {}
15381        }
15382        setTimeout(() => {
15383          if (!this._ready()) { this._localFallback = true; this.render(); }
15384        }, 5000);
15385      }
15386
15387      render() {
15388        // Loading state — shown until Swym is synced (or we time out to local).
15389        // Covers the drawer body AND the topnav count so nothing shows a
15390        // premature/for-a-moment-wrong value.
15391        if (!this._ready()) {
15392          if (this.loading) this.loading.hidden = false;
15393          if (this.list) this.list.hidden = true;
15394          if (this.empty) this.empty.hidden = true;
15395          if (this.triggerCount) {
15396            this.triggerCount.hidden = false;
15397            this.triggerCount.classList.add('is-loading');
15398            this.triggerCount.textContent = '';
15399          }
15400          this._scheduleReady();
15401          return;
15402        }
15403        if (this.loading) this.loading.hidden = true;
15404        if (this.triggerCount) this.triggerCount.classList.remove('is-loading');
15405
15406        const items = this.getSaved();
15407
15408        // Trigger + header bubble.
15409        if (this.bubble) this.bubble.textContent = items.length;
15410        if (this.triggerCount) {
15411          this.triggerCount.textContent = items.length;
15412          this.triggerCount.toggleAttribute('hidden', items.length === 0);
15413        }
15414
15415        if (!items.length) {
15416          this._renderSig = '';
15417          this.list.innerHTML = '';
15418          this.list.hidden = true;
15419          this.empty.hidden = false;
15420          return;
15421        }
15422        this.empty.hidden = true;
15423        this.list.hidden = false;
15424
15425        // Newest-first. Sort by the Swym-proof order map (variant_id →
15426        // timestamp, stored under its own key that Swym's sync never rewrites),
15427        // falling back to the per-item savedAt, then 0. This is what keeps a
15428        // fresh save on top both in-session and after refresh — the per-item
15429        // savedAt alone kept getting dropped/reordered by Swym's async sync, so
15430        // the item slid to the bottom. Items with no timestamp keep their
15431        // relative order below the ranked ones (stable sort).
15432        const order = (window.bpSavedForLater && typeof window.bpSavedForLater.getSavedOrder === 'function')
15433          ? window.bpSavedForLater.getSavedOrder()
15434          : {};
15435        const rank = (it) => Number(order[String(it.variant_id)]) || Number(it.savedAt) || 0;
15436        const ordered = items.slice().sort((a, b) => rank(b) - rank(a));
15437
15438        // Skip the rebuild when the visible list is unchanged. render() fires
15439        // several times right after a reload-then-open (open + Swym's
15440        // checkWishlistSync swapping in the remote item objects + storage /
15441        // wishlist events); each innerHTML reset flashed a blank frame between
15442        // paints, so the items appeared, vanished, then reappeared. Key the
15443        // signature on the ordered variant ids only, String-normalized so
15444        // Swym's reformatted objects (numeric vs string ids) don't falsely
15445        // differ from the localStorage ones.
15446        //
15447        // CRUCIAL: only skip when the DOM ACTUALLY reflects that signature
15448        // (childElementCount matches). Otherwise a render that set the signature
15449        // but left the list empty (e.g. an interrupted build) would skip forever
15450        // and the drawer would never show items.
15451        const sig = ordered.map((it) => String(it.variant_id || it.variantId || '')).join('|');
15452        if (sig === this._renderSig && this.list.childElementCount === ordered.length) return;
15453        this._renderSig = sig;
15454
15455        this.list.innerHTML = '';
15456        ordered.forEach((item) => {
15457          // Each entry stored by bp-swym-helpers uses Atlas's shape
15458          // (variant_id, variant_title, variant_price, title, image,
15459          // handle, quantity). Legacy entries used variantId/title/price/
15460          // variantTitle/url — read either form.
15461          const variantId = item.variant_id || item.variantId;
15462          const productId = item.id || item.productId;
15463          const variantTitle = item.variant_title || item.variantTitle || '';
15464          const url = item.handle ? `/products/${item.handle}` : (item.url || '#');
15465          const priceCents = this.parsePriceCents(item.variant_price || item.price);
15466          const qty = parseInt(item.quantity, 10) || 1;
15467
15468          const node = this.template.content.firstElementChild.cloneNode(true);
15469          node.dataset.savedKey = variantId || item.key;
15470
15471          const img = node.querySelector('[data-bp-card-image]');
15472          if (item.image) {
15473            img.src = item.image;
15474            img.alt = item.title || '';
15475          } else {
15476            img.remove();
15477          }
15478          node.querySelectorAll('[data-bp-card-link]').forEach((a) => {
15479            if (url) a.href = url;
15480            if (a.tagName === 'A' && a.children.length === 0) a.textContent = item.title || 'Item';
15481          });
15482
15483          node.querySelector('[data-bp-card-price]').textContent =
15484            this.formatMoney(priceCents * qty);
15485
15486          const variantEl = node.querySelector('[data-bp-card-variant]');
15487          if (variantTitle && variantTitle !== 'Default Title') {
15488            variantEl.textContent = variantTitle.replace(' / ', ' - ');
15489          } else {
15490            variantEl.remove();
15491          }
15492
15493          const propsEl = node.querySelector('[data-bp-card-props]');
15494          const props = item.properties || {};
15495          const visible = Object.entries(props).filter(([k, v]) => k && k[0] !== '_' && v);
15496          if (!visible.length) {
15497            propsEl.remove();
15498          } else {
15499            visible.forEach(([k, v]) => {
15500              const li = document.createElement('li');
15501              li.textContent = (k === 'Final Sale' || k === 'Final_Sale') ? 'Final Sale' : `${k}: ${v}`;
15502              propsEl.appendChild(li);
15503            });
15504          }
15505
15506          this.list.appendChild(node);
15507
15508          // Resolve availability async and stamp sold-out state once known.
15509          // Guard on isConnected so a re-render mid-fetch doesn't touch a
15510          // detached node.
15511          this.isSavedItemAvailable(item).then((available) => {
15512            if (!available && node.isConnected) this.markUnavailable(node);
15513          });
15514        });
15515      }
15516    }
15517    customElements.define('bp-saved-drawer', BpSavedDrawer);
15518  }
15519</script>
15519
15520
15521
15522  
15523    
15524    <div
15525      class="account-button header-actions__action color-scheme-1"
15526    >
15527      <shopify-store store-domain="https://www.bostonproper.com" country="US" language="en"></shopify-store>
15528<shopify-account
15529        menu="customer-account-main-menu"
15530        
15531      >
15532        
15533          <span
15534            slot="signed-out-avatar"
15535            class="account-button__text header-actions__text-style hidden"
15536          >
15537            Account
15538          </span>
15539
15540          <span
15541            slot="signed-out-avatar"
15542            class=""
15543            aria-hidden="true"
15544          >
15545            
15546  <span
15547    slot="signed-out-avatar"
15548    class="account-button__icon"
15549    aria-hidden="true"
15550  ><svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
15551<path d="M16.2227 15.2379C16.2134 12.9677 17.7898 11.0652 19.936 10.3449C23.4796 9.10175 27.7591 11.331 27.7783 15.2379C27.7587 19.1448 23.4796 21.374 19.936 20.1309C17.7903 19.4105 16.2134 17.5081 16.2227 15.2379ZM18.0005 15.2379C17.992 16.8309 18.828 18.4907 20.3231 19.2146C21.3583 19.7286 22.6431 19.7286 23.6783 19.2146C25.1729 18.4907 26.0094 16.8309 26.0009 15.2379C26.0094 13.6448 25.1734 11.985 23.6783 11.2612C22.6431 10.7472 21.3583 10.7472 20.3231 11.2612C18.8285 11.985 17.992 13.6448 18.0005 15.2379Z" fill="currentColor"/>
15552<path d="M12 34C12.28 29.7933 13.4618 25.0731 17.7702 23.2244C19.1058 22.6506 20.5636 22.4433 22 22.4372C24.3076 22.4241 26.7129 23.0455 28.4364 24.6324C29.9582 26.0034 30.8698 27.9263 31.3693 29.8649C31.6809 31.0482 31.8529 32.2665 31.9596 33.4808C31.972 33.6536 31.9853 33.8268 32 34H29.7778C29.7956 33.733 29.8182 33.3246 29.824 33.051C29.8591 30.5425 29.4138 27.8399 27.6716 25.9069C26.6804 24.8318 25.348 24.1738 23.8938 23.9146C22.0573 23.6027 20.0453 23.6973 18.336 24.4605C17.4333 24.8698 16.6467 25.4863 16.0364 26.2503L15.9004 26.431C15.784 26.5771 15.6858 26.7421 15.5796 26.8965C15.5347 26.9698 15.4516 27.1186 15.408 27.191C15.3351 27.308 15.2636 27.4738 15.1973 27.5951C14.3849 29.2863 14.1489 31.1922 14.176 33.0514C14.1871 33.3176 14.1987 33.7352 14.2222 34.0004H12V34Z" fill="currentColor"/>
15553</svg>
15554</span>
15555
15556          </span>
15557        
15558      </shopify-account>
15559    </div>
15560  
15561
15562  
15563<bp-cart-drawer class="bp-cart-drawer"><button
15564    type="button"
15565    class="bp-cart-drawer__trigger button-unstyled header-actions__action"
15566    data-bp-cart-open
15567    aria-haspopup="dialog"
15568    aria-label="Cart"
15569  ><svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
15570<path d="M12.0056 15.7691H31.6937H31.8451L31.9148 15.771C32.278 15.7797 32.6482 15.9823 32.8268 16.3059C32.938 16.4983 32.9759 16.6612 33.0022 16.8634C33.4498 21.2612 33.8731 25.7394 34.5178 30.1086C34.6327 30.9237 34.7435 31.7392 34.8506 32.5552C34.8547 32.5903 34.8598 32.6609 34.8616 32.6964C34.8889 33.1127 34.6941 33.6024 34.2718 33.8294C33.9755 33.9993 33.6815 34.0011 33.3686 33.9997C31.157 33.9997 12.811 33.9997 10.6515 33.9997C10.4346 33.9951 10.1328 34.0168 9.89368 33.9513C9.23232 33.7847 8.91618 33.1713 9.0191 32.515C9.16909 31.3709 9.44831 29.3324 9.60846 28.1675C10.0368 25.012 10.3617 21.7057 10.6824 18.5286C10.7083 18.3412 10.8153 17.1934 10.838 17.0203L10.8537 16.8694L10.8555 16.8505C10.8555 16.8458 10.8569 16.8362 10.8592 16.8237C10.9312 16.2154 11.3729 15.7626 12.0056 15.7691ZM12.0056 17.1537C12.0444 17.1537 12.0993 17.1274 12.1482 17.0914C12.187 17.0618 12.2142 17.0235 12.2253 17.0037C12.2373 16.9838 12.2378 16.9765 12.2364 16.9811C12.2355 16.9871 12.2336 16.9958 12.2322 17.0023C12.2322 17.0023 12.2313 17.0051 12.2308 17.0129L12.229 17.0318L12.2128 17.1823C11.9142 20.0285 11.5529 23.0635 11.299 25.9079C11.1246 28.0553 11.0036 30.5711 10.8541 32.7236L10.8518 32.7495V32.7569C10.8518 32.7569 10.8523 32.7587 10.8527 32.7495C10.8527 32.7426 10.8527 32.7232 10.8481 32.6973C10.8329 32.5889 10.7743 32.4698 10.6833 32.3655C10.5763 32.2524 10.4346 32.1643 10.3054 32.1509C10.298 32.1509 10.322 32.1527 10.3584 32.1532C12.7754 32.1541 30.8602 32.1532 33.3691 32.1532H33.508C33.5246 32.1523 33.5394 32.1518 33.5468 32.1513C33.5551 32.1509 33.5
15570583 32.1504 33.5514 32.1509C33.3538 32.1707 33.1171 32.3789 33.0515 32.5709C33.0068 32.6923 33.0132 32.7292 33.0137 32.7536C33.0137 32.7504 33.0137 32.7518 33.0137 32.7449L33.0114 32.719C32.8416 30.2979 32.7349 27.8656 32.5176 25.4505C32.2619 22.6989 31.9185 19.7359 31.6204 16.9815C31.631 17.0065 31.6647 17.0609 31.7136 17.0951C31.7528 17.1255 31.7967 17.1431 31.8216 17.1491L31.8373 17.1528H31.8437C31.8437 17.1528 31.846 17.1541 31.847 17.1541C31.8493 17.1541 31.852 17.1541 31.8511 17.1541C31.8502 17.1541 31.8544 17.1541 31.8451 17.1541C31.7639 17.1532 31.4796 17.1551 31.391 17.1541H12.0056V17.1537Z" fill="currentColor"/>
15571<path d="M15.0254 20.6119C15.1782 18.5997 15.2225 16.5187 15.8266 14.5651C16.734 11.5684 18.7877 9.98351 21.9326 10.0001C27.3328 10.0107 28.4539 14.3911 28.7234 18.9108C28.7622 19.4858 28.7931 20.06 28.8397 20.6115L26.9936 20.6027C27.0412 20.1015 27.1053 19.4092 27.1339 18.9181C27.3342 15.9118 27.0098 11.9371 23.5031 11.0995C22.4804 10.8627 21.3843 10.8627 20.3615 11.0995C17.4687 11.7885 16.7293 14.6421 16.6901 17.2733C16.6652 18.3611 16.7676 19.5126 16.8715 20.6027L15.0254 20.6115V20.6119Z" fill="currentColor"/>
15572</svg>
15573<span class="bp-cart-drawer__trigger-count" data-bp-cart-trigger-count hidden>0</span>
15574  </button>
15575
15576  <dialog class="bp-cart-drawer__dialog" data-bp-cart-dialog aria-label="Bag">
15577    <header class="bp-cart-drawer__header">
15578      <h2 class="bp-cart-drawer__heading">
15579        <span class="bp-cart-drawer__bubble" data-bp-cart-bubble>0</span>
15580        Bag
15581      </h2>
15582      <button type="button" class="bp-cart-drawer__close" data-bp-cart-close aria-label="Close bag">
15583        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true">
15584          <path d="M18 6C17.7882 6.18821 17.5764 6.37643 17.3646 6.56464C13.5525 9.95251 9.74038 13.3404 5.92825 16.7282C5.71646 16.9165 5.50468 17.1047 5.29289 17.2929C5.0433 17.5147 4.79371 17.7365 4.54412 17.9583C5.0433 18.4575 5.54248 18.9567 6.04167 19.4559C6.26348 19.2063 6.48529 18.9567 6.70711 18.7071C6.89532 18.4953 7.08354 18.2835 7.27175 18.0718C10.6596 14.2596 14.0475 10.4475 17.4354 6.63536C17.6236 6.42357 17.8118 6.21179 18 6Z" fill="currentColor"/>
15585          <path d="M18.7071 6.70711C18.9567 6.48529 19.2063 6.26348 19.4559 6.04167C18.9567 5.54248 18.4575 5.0433 17.9583 4.54412C17.7365 4.79371 17.5147 5.0433 17.2929 5.29289C17.1047 5.50468 16.9165 5.71646 16.7282 5.92825C13.3404 9.74038 9.95251 13.5525 6.56464 17.3646C6.37643 17.5764 6.18821 17.7882 6 18C6.21178 17.8118 6.42357 17.6236 6.63536 17.4354C10.4475 14.0475 14.2596 10.6596 18.0718 7.27175C18.2835 7.08354 18.4953 6.89532 18.7071 6.70711Z" fill="currentColor"/>
15586          <path d="M6 6C6.18821 6.21179 6.37643 6.42357 6.56464 6.63536C9.95251 10.4475 13.3404 14.2596 16.7282 18.0718C16.9165 18.2835 17.1047 18.4953 17.2929 18.7071C17.5147 18.9567 17.7365 19.2063 17.9583 19.4559C18.4575 18.9567 18.9567 18.4575 19.4559 17.9583C19.2063 17.7365 18.9567 17.5147 18.7071 17.2929C18.4953 17.1047 18.2835 16.9165 18.0718 16.7282C14.2596 13.3404 10.4475 9.95251 6.63536 6.56464C6.42357 6.37643 6.21179 6.18821 6 6Z" fill="currentColor"/>
15587          <path d="M6.70711 5.29289C6.48529 5.0433 6.26348 4.79371 6.04167 4.54412C5.54248 5.0433 5.0433 5.54248 4.54412 6.04167C4.79371 6.26348 5.0433 6.48529 5.29289 6.70711C5.50468 6.89532 5.71646 7.08354 5.92825 7.27175C9.74038 10.6596 13.5525 14.0475 17.3646 17.4354C17.5764 17.6236 17.7882 17.8118 18 18C17.8118 17.7882 17.6236 17.5764 17.4354 17.3646C14.0475 13.5525 10.6596 9.74038 7.27175 5.92825C7.08354 5.71646 6.89532 5.50468 6.70711 5.29289Z" fill="currentColor"/>
15588        </svg>
15589      </button>
15590    </header>
15591
15592    <div class="bp-cart-drawer__body" data-bp-cart-body><div class="bp-cart-drawer__empty" data-bp-cart-empty >
15593        <p>Your bag is empty.</p>
15594        <a href="/collections/all" class="bp-cart-drawer__empty-cta">Continue shopping</a>
15595        <button type="button" class="bp-cart-drawer__empty-cta bp-cart-drawer__empty-cta--btn" data-bp-saved-open>View saved items</button><div class="bp-cart-drawer__recs" data-bp-cart-recs><header class="bp-cart-drawer__recs-head">
15596              <h3 class="bp-cart-drawer__recs-title">Recommended for you</h3>
15597              <div class="bp-cart-drawer__recs-arrows">
15598                <button type="button" class="bp-cart-drawer__recs-arrow" data-bp-recs-
15598prev aria-label="Previous"><svg width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true">
15599                    <path d="M18.1326 13.8674C18.0884 13.8244 18.0442 13.7814 18 13.7385C17.9128 13.8256 17.8256 13.9128 17.7385 14C17.7814 14.0442 17.8244 14.0884 17.8674 14.1326C18.1304 14.4029 18.3934 14.6733 18.6564 14.9436C21.0232 17.3768 23.3901 19.8099 25.7569 22.2431V21.7569C23.3238 24.1238 20.8906 26.4906 18.4575 28.8575C18.1871 29.1205 17.9168 29.3835 17.6464 29.6464C17.527 29.7627 17.4075 29.8789 17.288 29.9951C17.527 30.2341 17.7659 30.473 18.0049 30.712C18.1211 30.5925 18.2373 30.473 18.3536 30.3536C18.6165 30.0832 18.8795 29.8129 19.1425 29.5425C21.5094 27.1094 23.8762 24.6762 26.2431 22.2431L26.486 21.9933L26.2431 21.7569C23.8099 19.3901 21.3768 17.0232 18.9436 14.6564C18.6733 14.3934 18.4029 14.1304 18.1326 13.8674Z" fill="currentColor"/>
15600                    <path d="M18.3536 13.6464C18.2373 13.527 18.1211 13.4075 18.0049 13.288C17.7659 13.527 17.527 13.7659 17.288 14.0049C17.4075 14.1211 17.527 14.2373 17.6464 14.3536C17.9168 14.6165 18.1871 14.8795 18.4575 15.1425C20.8906 17.5094 23.3238 19.8762 25.7569 22.2431V21.7569C23.3901 24.1901 21.0232 26.6232 18.6564 29.0564C18.3934 29.3267 18.1304 29.5971 17.8674 29.8674C17.8244 29.9116 17.7814 29.9558 17.7385 30C17.8256 30.0872 17.9128 30.1744 18 30.2615C18.0442 30.2186 18.0884 30.1756 18.1326 30.1326C18.4029 29.8696 18.6733 29.6066 18.9436 29.3436C21.3768 26.9768 23.8099 24.6099 26.2431 22.2431L26.486 21.9933L26.2431 21.7569C23.8762 19.3238 21.5094 16.8906 19.1425 14.4575C18.8795 14.1871 18.6165 13.9168 18.3536 13.6464Z" fill="currentColor"/>
15601                  </svg>
15602                </button>
15603                <button type="button" class="bp-cart-drawer__recs-arrow" data-bp-recs-next aria-label="Next">
15604                  <svg width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true">
15605                    <path d="M18.1326 13.8674C18.0884 13.8244 18.0442 13.7814 18 13.7385C17.9128 13.8256 17.8256 13.9128 17.7385 14C17.7814 14.0442 17.8244 14.0884 17.8674 14.1326C18.1304 14.4029 18.3934 14.6733 18.6564 14.9436C21.0232 17.3768 23.3901 19.8099 25.7569 22.2431V21.7569C23.3238 24.1238 20.8906 26.4906 18.4575 28.8575C18.1871 29.1205 17.9168 29.3835 17.6464 29.6464C17.527 29.7627 17.4075 29.8789 17.288 29.9951C17.527 30.2341 17.7659 30.473 18.0049 30.712C18.1211 30.5925 18.2373 30.473 18.3536 30.3536C18.6165 30.0832 18.8795 29.8129 19.1425 29.5425C21.5094 27.1094 23.8762 24.6762 26.2431 22.2431L26.486 21.9933L26.2431 21.7569C23.8099 19.3901 21.3768 17.0232 18.9436 14.6564C18.6733 14.3934 18.4029 14.1304 18.1326 13.8674Z" fill="currentColor"/>
15606                    <path d="M18.3536 13.6464C18.2373 13.527 18.1211 13.4075 18.0049 13.288C17.7659 13.527 17.527 13.7659 17.288 14.0049C17.4075 14.1211 17.527 14.2373 17.6464 14.3536C17.9168 14.6165 18.1871 14.8795 18.4575 15.1425C20.8906 17.5094 23.3238 19.8762 25.7569 22.2431V21.7569C23.3901 24.1901 21.0232 26.6232 18.6564 29.0564C18.3934 29.3267 18.1304 29.5971 17.8674 29.8674C17.8244 29.9116 17.7814 29.9558 17.7385 30C17.8256 30.0872 17.9128 30.1744 18 30.2615C18.0442 30.2186 18.0884 30.1756 18.1326 30.1326C18.4029 29.8696 18.6733 29.6066 18.9436 29.3436C21.3768 26.9768 23.8099 24.6099 26.2431 22.2431L26.486 21.9933L26.2431 21.7569C23.8762 19.3238 21.5094 16.8906 19.1425 14.4575C18.8795 14.1871 18.6165 13.9168 18.3536 13.6464Z" fill="currentColor"/>
15607                  </svg>
15608                </button>
15609              </div>
15610            </header>
15611            <ul class="bp-cart-drawer__recs-track" role="list"><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host">
15612  <article
15613    class="bp-card"
15614    data-product-id="15399681392806"
15615    data-product-url="/products/leopard-print-skirt-brown-multi"
15616    data-bp-card-secondary-hover="true"
15617    data-bp-card-qv-dest="drawer"
15618    data-bp-card-qv-vis-d="hover"
15619    data-bp-card-qv-vis-m="shown"
15620    data-bp-card-qb-style="disabled"
15621    data-bp-track-product='{    "id":          15399681392806,    "title":       "Leopard Print Skirt Brown Multi",    "vendor":      "Bagatelle",    "handle":      "leopard-print-skirt-brown-multi",    "url":         "\/products\/leopard-print-skirt-brown-multi",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO3390_SET.jpg?v=1791009176\u0026width=720",    "category":    "Skirts",    "product_type":null,    "selected_variant": {      "id":               56779671077030,      "sku":              "2DO3390800",      "price":            110.0,      "compare_at_price": 110.0,      "option1":          "Brown Multi",      "option2":          "L",      "product_id":       15399681392806,      "available":          true,      "inventory_quantity": 51    }  }'
15622  >
15623    <div class="bp-card__media">
15624      <a class="bp-card__media-link" href="/products/leopard-print-skirt-brown-multi" aria-label="Leopard Print Skirt Brown Multi" ref="productCardLink"><img
15625            class="bp-card__image bp-card__image--primary"
15626            src="//www.bostonproper.com/cdn/shop/files/2DO3390_SET.jpg?v=1791009176&
15626width=720"
15627            srcset="//www.bostonproper.com/cdn/shop/files/2DO3390_SET.jpg?v=1791009176&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DO3390_SET.jpg?v=1791009176&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DO3390_SET.jpg?v=1791009176&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DO3390_SET.jpg?v=1791009176&width=1080 1080w"
15628            sizes="(min-width: 1024px) 25vw, 50vw"
15629            width="1639"
15630            height="2048"
15631            alt="Leopard Print Skirt Brown Multi"
15632            loading="lazy"
15633            data-bp-card-image-primary
15634          ><img
15635            class="bp-card__image bp-card__image--secondary"
15636            src="//www.bostonproper.com/cdn/shop/files/2_c2593330-685e-4f0d-affc-d3a27bbd70d9.jpg?v=1791009175&width=720"
15637            srcset="//www.bostonproper.com/cdn/shop/files/2_c2593330-685e-4f0d-affc-d3a27bbd70d9.jpg?v=1791009175&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_c2593330-685e-4f0d-affc-d3a27bbd70d9.jpg?v=1791009175&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_c2593330-685e-4f0d-affc-d3a27bbd70d9.jpg?v=1791009175&width=720 720w"
15638            sizes="(min-width: 1024px) 25vw, 50vw"
15639            width="1639"
15640            height="2048"
15641            alt=""
15642            loading="lazy"
15643            aria-hidden="true"
15644            data-bp-card-image-secondary
15645          ></a><div class="bp-card__badges" data-bp-card-badges></div></div>
15646
15647    <div class="bp-card__body"><h3 class="bp-card__title">
15648        <a href="/products/leopard-print-skirt-brown-multi">Leopard Print Skirt</a>
15649      </h3>
15650
15651      <div class="bp-card__price-row"><span class="bp-card__price">$110</span>
15652        <s class="bp-card__compare" hidden></s></div></div>
15653  </article>
15654</product-card>
15655</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host">
15656  <article
15657    class="bp-card"
15658    data-product-id="15399681360038"
15659    data-product-url="/products/metallic-zebra-printed-dress-tan-multi"
15660    data-bp-card-secondary-hover="true"
15661    data-bp-card-qv-dest="drawer"
15662    data-bp-card-qv-vis-d="hover"
15663    data-bp-card-qv-vis-m="shown"
15664    data-bp-card-qb-style="disabled"
15665    data-bp-track-product='{    "id":          15399681360038,    "title":       "Metallic Zebra Printed Dress Tan Multi",    "vendor":      "Bagatelle",    "handle":      "metallic-zebra-printed-dress-tan-multi",    "url":         "\/products\/metallic-zebra-printed-dress-tan-multi",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO0590_SET.jpg?v=1791009160\u0026width=720",    "category":    "Dresses",    "product_type":null,    "selected_variant": {      "id":               56779670782118,      "sku":              "2DO0590006",      "price":            180.0,      "compare_at_price": 180.0,      "option1":          "Tan Multi",      "option2":          "6",      "product_id":       15399681360038,      "available":          true,      "inventory_quantity": 50    }  }'
15666  >
15667    <div class="bp-card__media">
15668      <a class="bp-card__media-link" href="/products/metallic-zebra-printed-dress-tan-multi" aria-label="Metallic Zebra Printed Dress Tan Multi" ref="productCardLink"><img
15669            class="bp-card__image bp-card__image--primary"
15670            src="//www.bostonproper.com/cdn/shop/files/2DO0590_SET.jpg?v=1791009160&width=720"
15671            srcset="//www.bostonproper.com/cdn/shop/files/2DO0590_SET.jpg?v=1791009160&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DO0590_SET.jpg?v=1791009160&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DO0590_SET.jpg?v=1791009160&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DO0590_SET.jpg?v=1791009160&width=1080 1080w"
15672            sizes="(min-width: 1024px) 25vw, 50vw"
15673            width="1639"
15674            height="2048"
15675            alt="Metallic Zebra Printed Dress Tan Multi"
15676            loading="lazy"
15677            data-bp-card-image-primary
15678          ><img
15679            class="bp-card__image bp-card__image--secondary"
15680            src="//www.bostonproper.com/cdn/shop/files/2_0161cf9a-a917-4e26-98d6-d48db12f058a.jpg?v=1791009160&width=720"
15681            srcset="//www.bostonproper.com/cdn/shop/files/2_0161cf9a-a917-4e26-98d6-d48db12f058a.jpg?v=1791009160&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_0161cf9a-a917-4e26-98d6-d48db12f058a.jpg?v=1791009160&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_0161cf9a-a917-4e26-98d6-d48db12f058a.jpg?v=1791009160&width=720 720w"
15682            sizes="(min-width: 1024px) 25vw, 50vw"
15683            width="1639"
15684            height="2048"
15685            alt=""
15686            loading="lazy"
15687            aria-hidden="true"
15688            data-bp-card-image-secondary
15689          ></a><div class="bp-card__badges" data-bp-card-badges></div></div>
15690
15691    <div class="bp-card__body"><h3 class="bp-card__title">
15692        <a href="/products/metallic-zebra-printed-dress-tan-multi">Metallic Zebra Printed Dress</a>
15693      </h3>
15694
15695      <div class="bp-card__price-row"><span class="bp-card__price">$180</span>
15696        <s class="bp-card__compare" hidden></s></div></div>
15697  </article>
15698</product-card>
15699</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host">
15700  <article
15701    class="bp-card"
15702    data-product-id="15399680114854"
15703    data-product-url="/products/sam-edelman-fur-lace-up-bootie-tan"
15704    data-bp-card-secondary-hover="true"
15705    data-bp-card-qv-dest="drawer"
15706    data-bp-card-qv-vis-d="hover"
15707    data-bp-card-qv-vis-m="shown"
15708    data-bp-card-qb-style="disabled"
15709    data-bp-track-product='{    "id":          15399680114854,    "title":       "Sam Edelman Fur Lace Up Bootie Tan",    "vendor":      "Sam Edelman",    "handle":      "sam-edelman-fur-lace-up-bootie-tan",    "url":         "\/products\/sam-edelman-fur-lace-up-bootie-tan",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO5680_SET.jpg?v=1791009185\u0026width=720",    "category":    "Shoes",    "product_type":null,    "selected_variant": {      "id":               56779666161830,      "sku":              "2DO5680060",      "price":            180.0,      "compare_at_price": 180.0,      "option1":          "Tan",      "option2":          "6.0",      "product_id":       15399680114854,      "available":          true,      "inventory_quantity": 13    }  }'
15710  >
15711    <div class="bp-card__media">
15712      <a class="bp-card__media-link" href="/products/sam-edelman-fur-lace-up-bootie-tan" aria-label="Sam Edelman Fur Lace Up Bootie Tan" ref="productCardLink"><img
15713            class="bp-card__image bp-card__image--primary"
15714            src="//www.bostonproper.com/cdn/shop/files/2DO5680_SET.jpg?v=1791009185&width=720"
15715            srcset="//www.bostonproper.com/cdn/shop/files/2DO5680_SET.jpg?v=1791009185&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DO5680_SET.jpg?v=1791009185&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DO5680_SET.jpg?v=1791009185&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DO5680_SET.jpg?v=1791009185&width=1080 1080w"
15716            sizes="(min-width: 1024px) 25vw, 50vw"
15717            width="1639"
15718            height="2048"
15719            alt="Sam Edelman Fur Lace Up Bootie Tan"
15720            loading="lazy"
15721            data-bp-card-image-primary
15722          ><img
15723            class="bp-card__image bp-card__image--secondary"
15724            src="//www.bostonproper.com/cdn/shop/files/2_811cc34e-278e-4bea-a759-24085c37ff4f.jpg?v=1791009185&width=720"
15725            srcset="//www.bostonproper.com/cdn/shop/files/2_811cc34e-278e-4bea-a759-24085c37ff4f.jpg?v=1791009185&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_811cc34e-278e-4bea-a759-24085c37ff4f.jpg?v=1791009185&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_811cc34e-278e-4bea-a759-24085c37ff4f.jpg?v=1791009185&width=720 720w"
15726            sizes="(min-width: 1024px) 25vw, 50vw"
15727            width="1639"
15728            height="2048"
15729            alt=""
15730            loading="lazy"
15731            aria-hidden="true"
15732            data-bp-card-image-secondary
15733          ></a><div class="bp-card__badges" data-bp-card-badges></div></div>
15734
15735    <div class="bp-card__body"><h3 class="bp-card__title">
15736        <a href="/products/sam-edelman-fur-lace-up-bootie-tan">Sam Edelman Fur Lace Up Bootie</a>
15737      </h3>
15738
15739      <div class="bp-card__price-row"><span class="bp-card__price">$180</span>
15740        <s class="bp-card__compare" hidden></s></div></div>
15741  </article>
15742</product-card>
15743</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host">
15744  <article
15745    class="bp-card"
15746    data-product-id="15399680082086"
15747    data-product-url="/products/ultimate-velvet-double-breasted-shaped-blazer-black"
15748    data-bp-card-secondary-hover="true"
15749    data-bp-card-qv-dest="drawer"
15750    data-bp-card-qv-vis-d="hover"
15751    data-bp-card-qv-vis-m="shown"
15752    data-bp-card-qb-style="disabled"
15753    data-bp-track-product='{    "id":          15399680082086,    "title":       "Ultimate Velvet Double Breasted Shaped Blazer Black",    "vendor":      "Boston Proper",    "handle":      "ultimate-velvet-double-breasted-shaped-blazer-black",    "url":         "\/products\/ultimate-velvet-double-breasted-shaped-blazer-black",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP1920_SET.jpg?v=1791009211\u0026width=720",    "category":    "Jackets",    "product_type":null,    "selected_variant": {      "id":               56779665801382,      "sku":              "2DP1920002",      "price":            150.0,      "compare_at_price": 150.0,      "option1":          "Black",      "option2":          "2",      "product_id":       15399680082086,      "available":          true,      "inventory_quantity": 21    }  }'
15754  >
15755    <div class="bp-card__media">
15756      <a class="bp-card__media-link" href="/products/ultimate-velvet-double-breasted-shaped-blazer-black" aria-label="Ultimate Velvet Double Breasted Shaped Blazer Black" ref="productCardLink"><img
15757            class="bp-card__image bp-card__image--primary"
15758            src="//www.bostonproper.com/cdn/shop/files/2DP1920_SET.jpg?v=1791009211&width=720"
15759            srcset="//www.bostonproper.com/cdn/shop/files/2DP1920_SET.jpg?v=1791009211&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DP1920_SET.jpg?v=1791009211&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DP1920_SET.jpg?v=1791009211&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DP1920_SET.jpg?v=1791009211&width=1080 1080w"
15760            sizes="(min-width: 1024px) 25vw, 50vw"
15761            width="1639"
15762            height="2048"
15763            alt="Ultimate Velvet Double Breasted Shaped Blazer Black"
15764            loading="lazy"
15765            data-bp-card-image-primary
15766          ><img
15767            class="bp-card__image bp-card__image--secondary"
15768            src="//www.bostonproper.com/cdn/shop/files/2_1560b9bf-904f-46e5-b2c8-2e27b8946935.jpg?v=1791009211&width=720"
15769            srcset="//www.bostonproper.com/cdn/shop/files/2_1560b9bf-904f-46e5-b2c8-2e27b8946935.jpg?v=1791009211&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_1560b9bf-904f-46e5-b2c8-2e27b8946935.jpg?v=1791009211&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_1560b9bf-904f-46e5-b2c8-2e27b8946935.jpg?v=1791009211&width=720 720w"
15770            sizes="(min-width: 1024px) 25vw, 50vw"
15771            width="1639"
15772            height="2048"
15773            alt=""
15774            loading="lazy"
15775            aria-hidden="true"
15776            data-bp-card-image-secondary
15777          ></a><div class="bp-card__badges" data-bp-card-badges></div></div>
15778
15779    <div class="bp-card__body"><h3 class="bp-card__title">
15780        <a href="/products/ultimate-velvet-double-breasted-shaped-blazer-black">Ultimate Velvet Double Breasted Shaped Blazer</a>
15781      </h3>
15782
15783      <div class="bp-card__price-row"><span class="bp-card__price">$150</span>
15784        <s class="bp-card__compare" hidden></s></div></div>
15785  </article>
15786</product-card>
15787</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host">
15788  <article
15789    class="bp-card"
15790    data-product-id="15371225596070"
15791    data-product-url="/products/breast-cancer-awareness-graphic-sweatshirt-azalea"
15792    data-bp-card-secondary-hover="true"
15793    data-bp-card-qv-dest="drawer"
15794    data-bp-card-qv-vis-d="hover"
15795    data-bp-card-qv-vis-m="shown"
15796    data-bp-card-qb-style="disabled"
15797    data-bp-track-product='{    "id":          15371225596070,    "title":       "Breast Cancer Awareness Graphic Sweatshirt Azalea",    "vendor":      "Boston Proper",    "handle":      "breast-cancer-awareness-graphic-sweatshirt-azalea",    "url":         "\/products\/breast-cancer-awareness-graphic-sweatshirt-azalea",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DR2070_SET.jpg?v=1791009256\u0026width=720",    "category":    "Athleisure",    "product_type":null,    "selected_variant": {      "id":               56671921471654,      "sku":              "2DR2070700",      "price":            60.0,      "compare_at_price": 60.0,      "option1":          "Azalea",      "option2":          "M",      "product_id":       15371225596070,      "available":          true,      "inventory_quantity": 121    }  }'
15798  >
15799    <div class="bp-card__media">
15800      <a class="bp-card__media-link" href="/products/breast-cancer-awareness-graphic-sweatshirt-azalea" aria-label="Breast Cancer Awareness Graphic Sweatshirt Azalea" ref="productCardLink"><img
15801            class="bp-card__image bp-card__image--primary"
15802            src="//www.bostonproper.com/cdn/shop/files/2DR2070_SET.jpg?v=1791009256&width=720"
15803            srcset="//www.bostonproper.com/cdn/shop/files/2DR2070_SET.jpg?v=1791009256&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DR2070_SET.jpg?v=1791009256&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DR2070_SET.jpg?v=1791009256&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DR2070_SET.jpg?v=1791009256&width=1080 1080w"
15804            sizes="(min-width: 1024px) 25vw, 50vw"
15805            width="1639"
15806            height="2048"
15807            alt="Breast Cancer Awareness Graphic Sweatshirt Azalea"
15808            loading="lazy"
15809            data-bp-card-image-primary
15810          ><img
15811            class="bp-card__image bp-card__image--secondary"
15812            src="//www.bostonproper.com/cdn/shop/files/2_c24d6d54-749e-49e8-a1fc-99f0a0a3a351.jpg?v=1791009256&width=720"
15813            srcset="//www.bostonproper.com/cdn/shop/files/2_c24d6d54-749e-49e8-a1fc-99f0a0a3a351.jpg?v=1791009256&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_c24d6d54-749e-49e8-a1fc-99f0a0a3a351.jpg?v=1791009256&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_c24d6d54-749e-49e8-a1fc-99f0a0a3a351.jpg?v=1791009256&width=720 720w"
15814            sizes="(min-width: 1024px) 25vw, 50vw"
15815            width="1639"
15816            height="2048"
15817            alt=""
15818            loading="lazy"
15819            aria-hidden="true"
15820            data-bp-card-image-secondary
15821          ></a><div class="bp-card__badges" data-bp-card-badges></div></div>
15822
15823    <div class="bp-card__body"><h3 class="bp-card__title">
15824        <a href="/products/breast-cancer-awareness-graphic-sweatshirt-azalea">Breast Cancer Awareness Graphic Sweatshirt</a>
15825      </h3>
15826
15827      <div class="bp-card__price-row"><span class="bp-card__price">$60</span>
15828        <s class="bp-card__compare" hidden></s></div></div>
15829  </article>
15830</product-card>
15831</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host">
15832  <article
15833    class="bp-card"
15834    data-product-id="15366923452582"
15835    data-product-url="/products/mock-neck-intarsia-flare-sleeve-tunic-west-side-paisley"
15836    data-bp-card-secondary-hover="true"
15837    data-bp-card-qv-dest="drawer"
15838    data-bp-card-qv-vis-d="hover"
15839    data-bp-card-qv-vis-m="shown"
15840    data-bp-card-qb-style="disabled"
15841    data-bp-track-product='{    "id":          15366923452582,    "title":       "Mock Neck Intarsia Flare Sleeve Tunic West Side Paisley",    "vendor":      "Boston Proper",    "handle":      "mock-neck-intarsia-flare-sleeve-tunic-west-side-paisley",    "url":         "\/products\/mock-neck-intarsia-flare-sleeve-tunic-west-side-paisley",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DM9540_SET.jpg?v=1791009180\u0026width=720",    "category":    "Sweater Tops",    "product_type":null,    "selected_variant": {      "id":               56658234933414,      "sku":              "2DM9540400",      "price":            100.0,      "compare_at_price": 100.0,      "option1":          "West Side Paisley",  
15841    "option2":          "XXS",      "product_id":       15366923452582,      "available":          true,      "inventory_quantity": 4    }  }'
15842  >
15843    <div class="bp-card__media">
15844      <a class="bp-card__media-link" href="/products/mock-neck-intarsia-flare-sleeve-tunic-west-side-paisley" aria-label="Mock Neck Intarsia Flare Sleeve Tunic West Side Paisley" ref="productCardLink"><img
15845            class="bp-card__image bp-card__image--primary"
15846            src="//www.bostonproper.com/cdn/shop/files/2DM9540_SET.jpg?v=1791009180&width=720"
15847            srcset="//www.bostonproper.com/cdn/shop/files/2DM9540_SET.jpg?v=1791009180&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DM9540_SET.jpg?v=1791009180&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DM9540_SET.jpg?v=1791009180&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DM9540_SET.jpg?v=1791009180&width=1080 1080w"
15848            sizes="(min-width: 1024px) 25vw, 50vw"
15849            width="1639"
15850            height="2048"
15851            alt="Mock Neck Intarsia Flare Sleeve Tunic West Side Paisley"
15852            loading="lazy"
15853            data-bp-card-image-primary
15854          ><img
15855            class="bp-card__image bp-card__image--secondary"
15856            src="//www.bostonproper.com/cdn/shop/files/2_ba1b3491-d2cb-4ccb-8e77-772ed7e57457.jpg?v=1791009179&width=720"
15857            srcset="//www.bostonproper.com/cdn/shop/files/2_ba1b3491-d2cb-4ccb-8e77-772ed7e57457.jpg?v=1791009179&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_ba1b3491-d2cb-4ccb-8e77-772ed7e57457.jpg?v=1791009179&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_ba1b3491-d2cb-4ccb-8e77-772ed7e57457.jpg?v=1791009179&width=720 720w"
15858            sizes="(min-width: 1024px) 25vw, 50vw"
15859            width="1639"
15860            height="2048"
15861            alt=""
15862            loading="lazy"
15863            aria-hidden="true"
15864            data-bp-card-image-secondary
15865          ></a><div class="bp-card__badges" data-bp-card-badges></div></div>
15866
15867    <div class="bp-card__body"><h3 class="bp-card__title">
15868        <a href="/products/mock-neck-intarsia-flare-sleeve-tunic-west-side-paisley">Mock Neck Intarsia Flare Sleeve Tunic</a>
15869      </h3>
15870
15871      <div class="bp-card__price-row"><span class="bp-card__price">$100</span>
15872        <s class="bp-card__compare" hidden></s></div></div>
15873  </article>
15874</product-card>
15875</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host">
15876  <article
15877    class="bp-card"
15878    data-product-id="15364508745894"
15879    data-product-url="/products/bcbgeneration-hardware-strap-to-the-knee-boot-cognac"
15880    data-bp-card-secondary-hover="true"
15881    data-bp-card-qv-dest="drawer"
15882    data-bp-card-qv-vis-d="hover"
15883    data-bp-card-qv-vis-m="shown"
15884    data-bp-card-qb-style="disabled"
15885    data-bp-track-product='{    "id":          15364508745894,    "title":       "BCBGeneration Hardware Strap To The Knee Boot Cognac",    "vendor":      "BCBG",    "handle":      "bcbgeneration-hardware-strap-to-the-knee-boot-cognac",    "url":         "\/products\/bcbgeneration-hardware-strap-to-the-knee-boot-cognac",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO6680_SET_538a0547-6fc7-4be8-8b60-4ea8b9720f2e.jpg?v=1791009184\u0026width=720",    "category":    "Shoes",    "product_type":null,    "selected_variant": {      "id":               56648379236518,      "sku":              "2DO6680060",      "price":            89.0,      "compare_at_price": 89.0,      "option1":          "Cognac",      "option2":          "6.0",      "product_id":       15364508745894,      "available":          true,      "inventory_quantity": 54    }  }'
15886  >
15887    <div class="bp-card__media">
15888      <a class="bp-card__media-link" href="/products/bcbgeneration-hardware-strap-to-the-knee-boot-cognac" aria-label="BCBGeneration Hardware Strap To The Knee Boot Cognac" ref="productCardLink"><img
15889            class="bp-card__image bp-card__image--primary"
15890            src="//www.bostonproper.com/cdn/shop/files/2DO6680_SET_538a0547-6fc7-4be8-8b60-4ea8b9720f2e.jpg?v=1791009184&width=720"
15891            srcset="//www.bostonproper.com/cdn/shop/files/2DO6680_SET_538a0547-6fc7-4be8-8b60-4ea8b9720f2e.jpg?v=1791009184&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DO6680_SET_538a0547-6fc7-4be8-8b60-4ea8b9720f2e.jpg?v=1791009184&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DO6680_SET_538a0547-6fc7-4be8-8b60-4ea8b9720f2e.jpg?v=1791009184&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DO6680_SET_538a0547-6fc7-4be8-8b60-4ea8b9720f2e.jpg?v=1791009184&width=1080 1080w"
15892            sizes="(min-width: 1024px) 25vw, 50vw"
15893            width="1639"
15894            height="2048"
15895            alt="BCBGeneration Hardware Strap To The Knee Boot Cognac"
15896            loading="lazy"
15897            data-bp-card-image-primary
15898          ><img
15899            class="bp-card__image bp-card__image--secondary"
15900            src="//www.bostonproper.com/cdn/shop/files/2_a1b81ef7-627c-4e8f-ac6d-4c188935d7ce.jpg?v=1791009184&width=720"
15901            srcset="//www.bostonproper.com/cdn/shop/files/2_a1b81ef7-627c-4e8f-ac6d-4c188935d7ce.jpg?v=1791009184&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_a1b81ef7-627c-4e8f-ac6d-4c188935d7ce.jpg?v=1791009184&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_a1b81ef7-627c-4e8f-ac6d-4c188935d7ce.jpg?v=1791009184&width=720 720w"
15902            sizes="(min-width: 1024px) 25vw, 50vw"
15903            width="1639"
15904            height="2048"
15905            alt=""
15906            loading="lazy"
15907            aria-hidden="true"
15908            data-bp-card-image-secondary
15909          ></a><div class="bp-card__badges" data-bp-card-badges></div></div>
15910
15911    <div class="bp-card__body"><h3 class="bp-card__title">
15912        <a href="/products/bcbgeneration-hardware-strap-to-the-knee-boot-cognac">BCBGeneration Hardware Strap To The Knee Boot</a>
15913      </h3>
15914
15915      <div class="bp-card__price-row"><span class="bp-card__price">$89</span>
15916        <s class="bp-card__compare" hidden></s></div></div>
15917  </article>
15918</product-card>
15919</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host">
15920  <article
15921    class="bp-card"
15922    data-product-id="15363223355558"
15923    data-product-url="/products/high-waisted-sport-legging-cherry-lacquer"
15924    data-bp-card-secondary-hover="true"
15925    data-bp-card-qv-dest="drawer"
15926    data-bp-card-qv-vis-d="hover"
15927    data-bp-card-qv-vis-m="shown"
15928    data-bp-card-qb-style="disabled"
15929    data-bp-track-product='{    "id":          15363223355558,    "title":       "High Waisted Sport Legging Cherry Lacquer",    "vendor":      "Boston Proper",    "handle":      "high-waisted-sport-legging-cherry-lacquer",    "url":         "\/products\/high-waisted-sport-legging-cherry-lacquer",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DB3271_SET.jpg?v=1791009254\u0026width=720",    "category":    "Athleisure",    "product_type":null,    "selected_variant": {      "id":               56643511681190,      "sku":              "2DB3271500",      "price":            50.0,      "compare_at_price": 50.0,      "option1":          "Cherry Lacquer",      "option2":          "XS",      "product_id":       15363223355558,      "available":          true,      "inventory_quantity": 32    }  }'
15930  >
15931    <div class="bp-card__media">
15932      <a class="bp-card__media-link" href="/products/high-waisted-sport-legging-cherry-lacquer" aria-label="High Waisted Sport Legging Cherry Lacquer" ref="productCardLink"><img
15933            class="bp-card__image bp-card__image--primary"
15934            src="//www.bostonproper.com/cdn/shop/files/2DB3271_SET.jpg?v=1791009254&width=720"
15935            srcset="//www.bostonproper.com/cdn/shop/files/2DB3271_SET.jpg?v=1791009254&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DB3271_SET.jpg?v=1791009254&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DB3271_SET.jpg?v=1791009254&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DB3271_SET.jpg?v=1791009254&width=1080 1080w"
15936            sizes="(min-width: 1024px) 25vw, 50vw"
15937            width="1639"
15938            height="2048"
15939            alt="High Waisted Sport Legging Cherry Lacquer"
15940            loading="lazy"
15941            data-bp-card-image-primary
15942          ><img
15943            class="bp-card__image bp-card__image--secondary"
15944            src="//www.bostonproper.com/cdn/shop/files/2_c0eb9c53-309b-4e5a-bdeb-b4f3a1da61e1.jpg?v=1791009254&width=720"
15945            srcset="//www.bostonproper.com/cdn/shop/files/2_c0eb9c53-309b-4e5a-bdeb-b4f3a1da61e1.jpg?v=1791009254&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_c0eb9c53-309b-4e5a-bdeb-b4f3a1da61e1.jpg?v=1791009254&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_c0eb9c53-309b-4e5a-bdeb-b4f3a1da61e1.jpg?v=1791009254&width=720 720w"
15946            sizes="(min-width: 1024px) 25vw, 50vw"
15947            width="1639"
15948            height="2048"
15949            alt=""
15950            loading="lazy"
15951            aria-hidden="true"
15952            data-bp-card-image-secondary
15953          ></a><div class="bp-card__badges" data-bp-card-badges></div></div>
15954
15955    <div class="bp-card__body"><h3 class="bp-card__title">
15956        <a href="/products/high-waisted-sport-legging-cherry-lacquer">High Waisted Sport Legging</a>
15957      </h3>
15958
15959      <div class="bp-card__price-row"><span class="bp-card__price">$50</span>
15960        <s class="bp-card__compare" hidden></s></div></div>
15961  </article>
15962</product-card>
15963</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host">
15964  <article
15965    class="bp-card"
15966    data-product-id="15342913847462"
15967    data-product-url="/products/herringbone-double-breasted-blazer-with-rhinestone-embellishment-gold-gray-multi"
15968    data-bp-card-secondary-hover="true"
15969    data-bp-card-qv-dest="drawer"
15970    data-bp-card-qv-vis-d="hover"
15971    data-bp-card-qv-vis-m="shown"
15972    data-bp-card-qb-style="disabled"
15973    data-bp-track-product='{    "id":          15342913847462,    "title":       "Herringbone Double Breasted Blazer With Rhinestone Embellishment Gold\/Gray Multi",    "vendor":      "Boston Proper",    "handle":      "herringbone-double-breasted-blazer-with-rhinestone-embellishment-gold-gray-multi",    "url":         "\/products\/herringbone-double-breasted-blazer-with-rhinestone-embellishment-gold-gray-multi",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP1690_SET.jpg?v=1791009251\u0026width=720",    "category":    "Jackets",    "product_type":null,    "selected_variant": {      "id":               56564923891878,      "sku":              "2DP1690006",      "price":            250.0,      "compare_at_price": 250.0,      "option1":          "Gold\/Gray Multi",      "option2":          "6",      "product_id":       15342913847462,      "available":          true,      "inventory_quantity": 71    }  }'
15974  >
15975    <div class="bp-card__media">
15976      <a class="bp-card__media-link" href="/products/herringbone-double-breasted-blazer-with-rhinestone-embellishment-gold-gray-multi" aria-label="Herringbone Double Breasted Blazer With Rhinestone Embellishment Gold/Gray Multi" ref="productCardLink"><img
15977            class="bp-card__image bp-card__image--primary"
15978            src="//www.bostonproper.com/cdn/shop/files/2DP1690_SET.jpg?v=1791009251&width=720"
15979            srcset="//www.bostonproper.com/cdn/shop/files/2DP1690_SET.jpg?v=1791009251&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DP1690_SET.jpg?v=1791009251&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DP1690_SET.jpg?v=1791009251&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DP1690_SET.jpg?v=1791009251&width=1080 1080w"
15980            sizes="(min-width: 1024px) 25vw, 50vw"
15981            width="1639"
15982            height="2048"
15983            alt="Herringbone Double Breasted Blazer With Rhinestone Embellishment Gold/Gray Multi"
15984            loading="lazy"
15985            data-bp-card-image-primary
15986          ><img
15987            class="bp-card__image bp-card__image--secondary"
15988            src="//www.bostonproper.com/cdn/shop/files/2_3c4a7bff-e851-481b-a
15988a8c-37759ba4fe6e.jpg?v=1791009251&width=720"
15989            srcset="//www.bostonproper.com/cdn/shop/files/2_3c4a7bff-e851-481b-aa8c-37759ba4fe6e.jpg?v=1791009251&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_3c4a7bff-e851-481b-aa8c-37759ba4fe6e.jpg?v=1791009251&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_3c4a7bff-e851-481b-aa8c-37759ba4fe6e.jpg?v=1791009251&width=720 720w"
15990            sizes="(min-width: 1024px) 25vw, 50vw"
15991            width="1639"
15992            height="2048"
15993            alt=""
15994            loading="lazy"
15995            aria-hidden="true"
15996            data-bp-card-image-secondary
15997          ></a><div class="bp-card__badges" data-bp-card-badges></div></div>
15998
15999    <div class="bp-card__body"><h3 class="bp-card__title">
16000        <a href="/products/herringbone-double-breasted-blazer-with-rhinestone-embellishment-gold-gray-multi">Herringbone Double Breasted Blazer With Rhinestone Embellishment</a>
16001      </h3>
16002
16003      <div class="bp-card__price-row"><span class="bp-card__price">$250</span>
16004        <s class="bp-card__compare" hidden></s></div></div>
16005  </article>
16006</product-card>
16007</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host">
16008  <article
16009    class="bp-card"
16010    data-product-id="15336227864742"
16011    data-product-url="/products/knit-suede-drape-front-jacket-stone"
16012    data-bp-card-secondary-hover="true"
16013    data-bp-card-qv-dest="drawer"
16014    data-bp-card-qv-vis-d="hover"
16015    data-bp-card-qv-vis-m="shown"
16016    data-bp-card-qb-style="disabled"
16017    data-bp-track-product='{    "id":          15336227864742,    "title":       "Knit Suede Drape Front Jacket Stone",    "vendor":      "Boston Proper",    "handle":      "knit-suede-drape-front-jacket-stone",    "url":         "\/products\/knit-suede-drape-front-jacket-stone",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DR1780_SET.jpg?v=1791009250\u0026width=720",    "category":    "Jackets",    "product_type":null,    "selected_variant": {      "id":               56545549123750,      "sku":              "2DR1780400",      "price":            125.0,      "compare_at_price": 125.0,      "option1":          "Stone",      "option2":          "XXS",      "product_id":       15336227864742,      "available":          true,      "inventory_quantity": 6    }  }'
16018  >
16019    <div class="bp-card__media">
16020      <a class="bp-card__media-link" href="/products/knit-suede-drape-front-jacket-stone" aria-label="Knit Suede Drape Front Jacket Stone" ref="productCardLink"><img
16021            class="bp-card__image bp-card__image--primary"
16022            src="//www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1791009250&width=720"
16023            srcset="//www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1791009250&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1791009250&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1791009250&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1791009250&width=1080 1080w"
16024            sizes="(min-width: 1024px) 25vw, 50vw"
16025            width="1639"
16026            height="2048"
16027            alt="Knit Suede Drape Front Jacket Stone"
16028            loading="lazy"
16029            data-bp-card-image-primary
16030          ><img
16031            class="bp-card__image bp-card__image--secondary"
16032            src="//www.bostonproper.com/cdn/shop/files/2_658da758-2997-4038-9a66-4589dff50ec8.jpg?v=1791009249&width=720"
16033            srcset="//www.bostonproper.com/cdn/shop/files/2_658da758-2997-4038-9a66-4589dff50ec8.jpg?v=1791009249&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_658da758-2997-4038-9a66-4589dff50ec8.jpg?v=1791009249&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_658da758-2997-4038-9a66-4589dff50ec8.jpg?v=1791009249&width=720 720w"
16034            sizes="(min-width: 1024px) 25vw, 50vw"
16035            width="1639"
16036            height="2048"
16037            alt=""
16038            loading="lazy"
16039            aria-hidden="true"
16040            data-bp-card-image-secondary
16041          ></a><div class="bp-card__badges" data-bp-card-badges></div></div>
16042
16043    <div class="bp-card__body"><h3 class="bp-card__title">
16044        <a href="/products/knit-suede-drape-front-jacket-stone">Knit Suede Drape Front Jacket</a>
16045      </h3>
16046
16047      <div class="bp-card__price-row"><span class="bp-card__price">$125</span>
16048        <s class="bp-card__compare" hidden></s></div></div>
16049  </article>
16050</product-card>
16051</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host">
16052  <article
16053    class="bp-card"
16054    data-product-id="15336227831974"
16055    data-product-url="/products/knit-suede-drape-front-jacket-blue"
16056    data-bp-card-secondary-hover="true"
16057    data-bp-card-qv-dest="drawer"
16058    data-bp-card-qv-vis-d="hover"
16059    data-bp-card-qv-vis-m="shown"
16060    data-bp-card-qb-style="disabled"
16061    data-bp-track-product='{    "id":          15336227831974,    "title":       "Knit Suede Drape Front Jacket Blue",    "vendor":      "Boston Proper",    "handle":      "knit-suede-drape-front-jacket-blue",    "url":         "\/products\/knit-suede-drape-front-jacket-blue",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DR1730_SET_9fea2518-0e42-496d-aca4-19f54a5af591.jpg?v=1791009249\u0026width=720",    "category":    "Jackets",    "product_type":null,    "selected_variant": {      "id":               56545548927142,      "sku":              "2DR1730400",      "price":            125.0,      "compare_at_price": 125.0,      "option1":          "Blue",      "option2":          "XXS",      "product_id":       15336227831974,      "available":          true,      "inventory_quantity": 12    }  }'
16062  >
16063    <div class="bp-card__media">
16064      <a class="bp-card__media-link" href="/products/knit-suede-drape-front-jacket-blue" aria-label="Knit Suede Drape Front Jacket Blue" ref="productCardLink"><img
16065            class="bp-card__image bp-card__image--primary"
16066            src="//www.bostonproper.com/cdn/shop/files/2DR1730_SET_9fea2518-0e42-496d-aca4-19f54a5af591.jpg?v=1791009249&width=720"
16067            srcset="//www.bostonproper.com/cdn/shop/files/2DR1730_SET_9fea2518-0e42-496d-aca4-19f54a5af591.jpg?v=1791009249&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DR1730_SET_9fea2518-0e42-496d-aca4-19f54a5af591.jpg?v=1791009249&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DR1730_SET_9fea2518-0e42-496d-aca4-19f54a5af591.jpg?v=1791009249&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DR1730_SET_9fea2518-0e42-496d-aca4-19f54a5af591.jpg?v=1791009249&width=1080 1080w"
16068            sizes="(min-width: 1024px) 25vw, 50vw"
16069            width="1639"
16070            height="2048"
16071            alt="Knit Suede Drape Front Jacket Blue"
16072            loading="lazy"
16073            data-bp-card-image-primary
16074          ><img
16075            class="bp-card__image bp-card__image--secondary"
16076            src="//www.bostonproper.com/cdn/shop/files/2_289296ee-9816-41a8-9944-3c93127b0c63.jpg?v=1791009248&width=720"
16077            srcset="//www.bostonproper.com/cdn/shop/files/2_289296ee-9816-41a8-9944-3c93127b0c63.jpg?v=1791009248&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_289296ee-9816-41a8-9944-3c93127b0c63.jpg?v=1791009248&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_289296ee-9816-41a8-9944-3c93127b0c63.jpg?v=1791009248&width=720 720w"
16078            sizes="(min-width: 1024px) 25vw, 50vw"
16079            width="1639"
16080            height="2048"
16081            alt=""
16082            loading="lazy"
16083            aria-hidden="true"
16084            data-bp-card-image-secondary
16085          ></a><div class="bp-card__badges" data-bp-card-badges></div></div>
16086
16087    <div class="bp-card__body"><h3 class="bp-card__title">
16088        <a href="/products/knit-suede-drape-front-jacket-blue">Knit Suede Drape Front Jacket</a>
16089      </h3>
16090
16091      <div class="bp-card__price-row"><span class="bp-card__price">$125</span>
16092        <s class="bp-card__compare" hidden></s></div></div>
16093  </article>
16094</product-card>
16095</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host">
16096  <article
16097    class="bp-card"
16098    data-product-id="15334258868390"
16099    data-product-url="/products/half-zip-sparkle-snowflake-sweater-french-kiss"
16100    data-bp-card-secondary-hover="true"
16101    data-bp-card-qv-dest="drawer"
16102    data-bp-card-qv-vis-d="hover"
16103    data-bp-card-qv-vis-m="shown"
16104    data-bp-card-qb-style="disabled"
16105    data-bp-track-product='{    "id":          15334258868390,    "title":       "Half Zip Sparkle Snowflake Sweater French Kiss",    "vendor":      "Boston Proper",    "handle":      "half-zip-sparkle-snowflake-sweater-french-kiss",    "url":         "\/products\/half-zip-sparkle-snowflake-sweater-french-kiss",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DQ0611_SET.jpg?v=1791009258\u0026width=720",    "category":    "Sweater Tops",    "product_type":null,    "selected_variant": {      "id":               56539690696870,      "sku":              "2DQ0611500",      "price":            100.0,      "compare_at_price": 100.0,      "option1":          "French Kiss",      "option2":          "XS",      "product_id":       15334258868390,      "available":          true,      "inventory_quantity": 90    }  }'
16106  >
16107    <div class="bp-card__media">
16108      <a class="bp-card__media-link" href="/products/half-zip-sparkle-snowflake-sweater-french-kiss" aria-label="Half Zip Sparkle Snowflake Sweater French Kiss" ref="productCardLink"><img
16109            class="bp-card__image bp-card__image--primary"
16110            src="//www.bostonproper.com/cdn/shop/files/2DQ0611_SET.jpg?v=1791009258&width=720"
16111            srcset="//www.bostonproper.com/cdn/shop/files/2DQ0611_SET.jpg?v=1791009258&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DQ0611_SET.jpg?v=1791009258&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DQ0611_SET.jpg?v=1791009258&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DQ0611_SET.jpg?v=1791009258&width=1080 1080w"
16112            sizes="(min-width: 1024px) 25vw, 50vw"
16113            width="1639"
16114            height="2048"
16115            alt="Half Zip Sparkle Snowflake Sweater French Kiss"
16116            loading="lazy"
16117            data-bp-card-image-primary
16118          ><img
16119            class="bp-card__image bp-card__image--secondary"
16120            src="//www.bostonproper.com/cdn/shop/files/2_6a50f250-465a-41b2-9e01-3af49d502b58.jpg?v=1791009258&width=720"
16121            srcset="//www.bostonproper.com/cdn/shop/files/2_6a50f250-465a-41b2-9e01-3af49d502b58.jpg?v=1791009258&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_6a50f250-465a-41b2-9e01-3af49d502b58.jpg?v=1791009258&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_6a50f250-465a-41b2-9e01-3af49d502b58.jpg?v=1791009258&width=720 720w"
16122            sizes="(min-width: 1024px) 25vw, 50vw"
16123            width="1639"
16124            height="2048"
16125            alt=""
16126            loading="lazy"
16127            aria-hidden="true"
16128            data-bp-card-image-secondary
16129          ></a><div class="bp-card__badges" data-bp-card-badges></div></div>
16130
16131    <div class="bp-card__body"><h3 class="bp-card__title">
16132        <a href="/products/half-zip-sparkle-snowflake-sweater-french-kiss">Half Zip Sparkle Snowflake Sweater</a>
16133      </h3>
16134
16135      <div class="bp-card__price-row"><span class="bp-card__price">$100</span>
16136        <s class="bp-card__compare" hidden></s></div></div>
16137  </article>
16138</product-card>
16139</li></ul>
16140          </div></div>
16141      <ul class="bp-cart-drawer__items" data-bp-cart-items hidden></ul><section class="bp-cart-drawer__ctl" data-bp-ctl hidden>
16142        <header class="bp-cart-drawer__ctl-head">
16143          <h3 class="bp-cart-drawer__ctl-title">Complete the Look</h3>
16144          <div class="bp-cart-drawer__ctl-arrows">
16145            <button type="button" class="bp-cart-drawer__ctl-arrow" data-bp-ctl-prev aria-label="Previous"><svg width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true">
16146                <path d="M18.1326 13.8674C18.0884 13.8244 18.0442 13.7814 18 13.7385C17.9128 13.8256 17.8256 13.9128 17.7385 14C17.7814 14.0442 17.8244 14.0884 17.8674 14.1326C18.1304 14.4029 18.3934 14.6733 18.6564 14.9436C21.0232 17.3768 23.3901 19.8099 25.7569 22.2431V21.7569C23.3238 24.1238 20.8906 26.4906 18.4575 28.8575C18.1871 29.1205 17.9168 29.3835 17.6464 29.6464C17.527 29.7627 17.4075 29.8789 17.288 29.9951C17.527 30.2341 17.7659 30.473 18.0049 30.712C18.1211 30.5925 18.2373 30.473 18.3536 30.3536C18.6165 30.0832 18.8795 29.8129 19.1425 29.5425C21.5094 27.1094 23.8762 24.6762 26.2431 22.2431L26.486 21.9933L26.2431 21.7569C23.8099 19.3901 21.3768 17.0232 18.9436 14.6564C18.6733 14.3934 18.4029 14.1304 18.1326 13.8674Z" fill="currentColor"/>
16147                <path d="M18.3536 13.6464C18.2373 13.527 18.1211 13.4075 18.0049 13.288C17.7659 13.527 17.527 13.7659 17.288 14.0049C17.4075 14.1211 17.527 14.2373 17.6464 14.3536C17.9168 14.6165 18.1871 14.8795 18.4575 15.1425C20.8906 17.5094 23.3238 19.8762 25.7569 22.2431V21.7569C23.3901 24.1901 21.0232 26.6232 18.6564 29.0564C18.3934 29.3267 18.1304 29.5971 17.8674 29.8674C17.8244 29.9116 17.7814 29.9558 17.7385 30C17.8256 30.0872 17.9128 30.1744 18 30.2615C18.0442 30.2186 18.0884 30.1756 18.1326 30.1326C18.4029 29.8696 18.6733 29.6066 18.9436 29.3436C21.3768 26.9768 23.8099 24.6099 26.2431 22.2431L26.486 21.9933L26.2431 21.7569C23.8762 19.3238 21.5094 16.8906 19.1425 14.4575C18.8795 14.1871 18.6165 13.9168 18.3536 13.6464Z" fill="currentColor"/>
16148              </svg>
16149            </button>
16150            <button type="button" class="bp-cart-drawer__ctl-arrow" data-bp-ctl-next aria-label="Next">
16151              <svg width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true">
16152                <path d="M18.1326 13.8674C18.0884 13.8244 18.0442 13.7814 18 13.7385C17.9128 13.8256 17.8256 13.9128 17.7385 14C17.7814 14.0442 17.8244 14.0884 17.8674 14.1326C18.1304 14.4029 18.3934 14.6733 18.6564 14.9436C21.0232 17.3768 23.3901 19.8099 25.7569 22.2431V21.7569C23.3238 24.1238 20.8906 26.4906 18.4575 28.8575C18.1871 29.1205 17.9168 29.3835 17.6464 29.6464C17.527 29.7627 17.4075 29.8789 17.288 29.9951C17.527 30.2341 17.7659 30.473 18.0049 30.712C18.1211 30.5925 18.2373 30.473 18.3536 30.3536C18.6165 30.0832 18.8795 29.8129 19.1425 29.5425C21.5094 27.1094 23.8762 24.6762 26.2431 22.2431L26.486 21.9933L26.2431 21.7569C23.8099 19.3901 21.3768 17.0232 18.9436 14.6564C18.6733 14.3934 18.4029 14.1304 18.1326 13.8674Z" fill="currentColor"/>
16153                <path d="M18.3536 13.6464C18.2373 13.527 18.1211 13.4075 18.0049 13.288C17.7659 13.527 17.527 13.7659 17.288 14.0049C17.4075 14.1211 17.527 14.2373 17.6464 14.3536C17.9168 14.6165 18.1871 14.8795 18.4575 15.1425C20.8906 17.5094 23.3238 19.8762 25.7569 22.2431V21.7569C23.3901 24.1901 21.0232 26.6232 18.6564 29.0564C18.3934 29.3267 18.1304 29.5971 17.8674 29.8674C17.8244 29.9116 17.7814 29.9558 17.7385 30C17.8256 30.0872 17.9128 30.1744 18 30.2615C18.0442 30.2186 18.0884 30.1756 18.1326 30.1326C18.4029 29.8696 18.6733 29.6066 18.9436 29.3436C21.3768 26.9768 23.8099 24.6099 26.2431 22.2431L26.486 21.9933L26.2431 21.7569C23.8762 19.3238 21.5094 16.8906 19.1425 14.4575C18.8795 14.1871 18.6165 13.9168 18.3536 13.6464Z" fill="currentColor"/>
16154              </svg>
16155            </button>
16156          </div>
16157        </header><div class="bp-cart-drawer__ctl-track" data-bp-ctl-track></div><div class="bp-cart-drawer__ctl-indicator" data-bp-ctl-indicator aria-hidden="true"></div>
16158      </section>
16159    </div><footer class="bp-cart-drawer__foot" hidden><section
16160  class="bp-cart-discount bp-cart-discount--drawer"
16161  data-bp-cart-discount
16162  data-bp-existing-codes=""
16163><div class="bp-cart-discount__collapse" data-bp-promo-collapse>
16164      <button
16165        type="button"
16166        class="bp-cart-discount__summary"
16167        data-bp-promo-toggle
16168        aria-expanded="false"
16169        aria-controls="bp-promo-body-drawer"
16170      >
16171        <span class="bp-cart-discount__summary-text">Promo code</span>
16172        <svg class="bp-cart-discount__summary-chev" width="12" height="8" viewBox="0 0 12 8" fill="none" aria-hidden="true">
16173          <path d="M1 1.5L6 6.5L11 1.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>
16174        </svg>
16175      </button>
16176      <div class="bp-cart-discount__collapse-body" id="bp-promo-body-drawer" data-bp-promo-body>
16177        <div class="bp-cart-discount__collapse-inner"><form class="bp-cart-discount__form" data-bp-cart-discount-form novalidate>
16178    <div class="bp-cart-discount__row">
16179      <input
16180        type="text"
16181        id="bp-cart-discount-input-drawer"
16182        name="discount"
16183        class="bp-cart-discount__input"
16184        placeholder="Enter promo code"
16185        autocomplete="off"
16186        autocapitalize="characters"
16187        spellcheck="false"
16188        data-bp-cart-discount-input
16189        aria-label="Promo code"
16190        aria-describedby="bp-cart-discount-error-drawer"
16191      >
16192      <button type="submit" class="bp-cart-discount__submit" data-bp-cart-discount-submit>Apply</button>
16193    </div>
16194    <p class="bp-cart-discount__error" id="bp-cart-discount-error-drawer" data-bp-cart-discount-error role="alert" hidden>This code isn't valid. Please try another.</p>
16195  </form></div>
16196      </div>
16197    </div></section>
16198
16199<style data-shopify>
16200  .bp-cart-discount {
16201    width: 100%;
16202    margin: 12px 0 0;
16203    font-family: var(--bp-font-body);
16204  }
16205  /* Drawer footer (snippets/bp-cart-drawer.liquid) is a flex column with
16206     its own `gap` between rows — this block's own top margin stacked on
16207     top of that gap, doubling the space above it. Page surface keeps the
16208     margin (not laid out in a gapped flex stack). */
16209  .bp-cart-discount--drawer { margin-top: 0; }
16210  .bp-cart-discount__form { margin: 0; padding: 0; }
16211
16212  /* Collapsible promo bar (drawer). Collapsed = just the summary row,
16213     so the sticky footer reclaims the input + button height. The body
16214     grows/shrinks with a grid-template-rows 0fr<->1fr transition. */
16215  .bp-cart-discount__collapse { width: 100%; }
16216  .bp-cart-discount__summary {
16217    display: flex;
16218    width: 100%;
16219    align-items: center;
16220    justify-content: space-between;
16221    gap: 8px;
16222    margin: 0;
16223    padding: 2px 0;
16224    background: transparent;
16225    border: 0;
16226    text-align: left;
16227    cursor: pointer;
16228    font-family: var(--bp-font-body);
16229    font-size: 12px;
16230    font-weight: 700;
16231    letter-spacing: 0.5px;
16232    text-transform: uppercase;
16233    color: var(--bp-color-text);
16234  }
16235  .bp-cart-discount__summary:focus-visible {
16236    outline: 2px solid var(--bp-color-text);
16237    outline-offset: 2px;
16238  }
16239  .bp-cart-discount__summary-chev {
16240    flex: 0 0 auto;
16241    transition: transform 0.28s ease;
16242  }
16243  .bp-cart-discount__collapse.is-open .bp-cart-discount__summary-chev { transform: rotate(180deg); }
16244
16245  .bp-cart-discount__collapse-body {
16246    display: grid;
16247    grid-template-rows: 0fr;
16248    transition: grid-template-rows 0.28s ease;
16249  }
16250  .bp-cart-discount__collapse.is-open .bp-cart-discount__collapse-body { grid-template-rows: 1fr; }
16251  /* The inner wrapper is the animated row — must clip + allow 0 height. */
16252  .bp-cart-discount__collapse-inner {
16253    overflow: hidden;
16254    min-height: 0;
16255    padding-top: 10px;
16256  }
16257  @media (prefers-reduced-motion: reduce) {
16258    .bp-cart-discount__collapse-body,
16259    .bp-cart-discount__summary-chev { transition: none; }
16260  }
16261
16262  .bp-cart-discount__label {
16263    display: block;
16264    margin: 0 0 6px;
16265    font-size: 12px;
16266    font-weight: 700;
16267    letter-spacing: 0.5px;
16268    text-transform: uppercase;
16269    color: var(--bp-color-text);
16270  }
16271  .bp-cart-discount__row {
16272    display: flex;
16273    gap: 8px;
16274    align-items: stretch;
16275  }
16276  .bp-cart-discount__input {
16277    flex: 1 1 auto;
16278    min-width: 0;
16279    height: 44px;
16280    padding: 0 12px;
16281    background: transparent;
16282    border: 1px solid rgba(23, 22, 9, 0.32);
16283    color: var(--bp-color-text);
16284    font-family: var(--bp-font-body);
16285    font-size: 14px;
16286    line-height: 1;
16287    letter-spacing: 0.04em;
16288    text-transform: uppercase;
16289    box-sizing: border-box;
16290  }
16291  .bp-cart-discount__input::placeholder { color: var(--bp-color-body-copy, #74736B); text-transform: none; letter-spacing: -0.14px; }
16292  .bp-cart-discount__input:focus {
16293    outline: none;
16294    border-color: var(--bp-color-text);
16295  }
16296  .bp-cart-discount__input:focus-visible {
16297    outline: 2px solid var(--bp-color-text);
16298    outline-offset: 2px;
16299  }
16300  .bp-cart-discount__submit {
16301    flex: 0 0 auto;
16302    height: 44px;
16303    padding: 0 20px;
16304    background: var(--bp-color-text);
16305    color: var(--bp-color-cta-text);
16306    border: 0;
16307    font-family: var(--bp-font-body);
16308    font-size: 14px;
16309    font-weight: 500;
16310    letter-spacing: -0.14px;
16311    cursor: pointer;
16312    transition: opacity 0.2s ease;
16313  }
16314  .bp-cart-discount__submit:hover { opacity: 0.85; }
16315  .bp-cart-discount__submit:disabled { opacity: 0.5;
16315 cursor: not-allowed; }
16316  .bp-cart-discount__error {
16317    margin: 8px 0 0;
16318    color: var(--bp-color-promo, #B5341B);
16319    font-size: 12px;
16320    line-height: 145%;
16321    letter-spacing: -0.12px;
16322  }
16323
16324  /* Applied-code pills */
16325  .bp-cart-discount__pills {
16326    list-style: none;
16327    margin: 10px 0 0;
16328    padding: 0;
16329    display: flex;
16330    flex-wrap: wrap;
16331    gap: 6px;
16332  }
16333  .bp-cart-discount__pill {
16334    display: inline-flex;
16335    align-items: center;
16336    gap: 6px;
16337    padding: 4px 4px 4px 10px;
16338    background: var(--bp-color-bg-cream, #F7F6EA);
16339    color: var(--bp-color-text);
16340    font-size: 12px;
16341    font-weight: 500;
16342    letter-spacing: 0.04em;
16343    text-transform: uppercase;
16344    border-radius: 0;
16345  }
16346  .bp-cart-discount__pill-code { line-height: 1; }
16347  .bp-cart-discount__pill-remove {
16348    display: inline-flex;
16349    align-items: center;
16350    justify-content: center;
16351    width: 20px;
16352    height: 20px;
16353    padding: 0;
16354    background: transparent;
16355    border: 0;
16356    color: var(--bp-color-text);
16357    cursor: pointer;
16358    border-radius: 50%;
16359    transition: background 0.15s ease;
16360  }
16361  .bp-cart-discount__pill-remove:hover { background: rgba(23, 22, 9, 0.08); }
16362</style>
16363
16364<script>
16365  (function () {
16366    if (window.__bpCartDiscountWired) return;
16367    window.__bpCartDiscountWired = true;
16368
16369    const ROOT = (window.Shopify && window.Shopify.routes && window.Shopify.routes.root) || '/';
16370
16371    function getCodesFromHost(host) {
16372      const raw = host.getAttribute('data-bp-existing-codes') || '';
16373      return raw ? raw.split(',').filter(Boolean) : [];
16374    }
16375
16376    async function postDiscount(codes) {
16377      const res = await fetch(ROOT + 'cart/update.js', {
16378        method: 'POST',
16379        headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
16380        body: JSON.stringify({ discount: codes.join(',') }),
16381        credentials: 'same-origin',
16382        cache: 'no-store',
16383      });
16384      if (!res.ok) throw new Error('cart/update.js HTTP ' + res.status);
16385      return res.json();
16386    }
16387
16388    function setError(host, show, msg) {
16389      const el = host.querySelector('[data-bp-cart-discount-error]');
16390      const input = host.querySelector('[data-bp-cart-discount-input]');
16391      if (input) input.setAttribute('aria-invalid', show ? 'true' : 'false');
16392      if (!el) return;
16393      if (show) {
16394        if (msg) el.textContent = msg;
16395        el.hidden = false;
16396      } else {
16397        el.hidden = true;
16398      }
16399    }
16400
16401    function isApplicableInCart(cart, code) {
16402      return (cart.discount_codes || []).some((d) => d.code === code && d.applicable === true);
16403    }
16404
16405    function esc(s) {
16406      return String(s == null ? '' : s)
16407        .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
16408        .replace(/"/g, '&quot;');
16409    }
16410
16411    // Rebuild the applied-code pills in place so they behave like checkout:
16412    // a chip with a remove appears the moment a code applies and clears the
16413    // moment it is removed, with no page reload. Mirrors the server-rendered
16414    // pill markup; the delegated remove handler below covers injected buttons.
16415    function renderPills(host, applied) {
16416      const form = host.querySelector('[data-bp-cart-discount-form]');
16417      if (!form) return;
16418      let ul = host.querySelector('[data-bp-cart-discount-pills]');
16419      if (!applied.length) { if (ul) ul.remove(); return; }
16420      if (!ul) {
16421        ul = document.createElement('ul');
16422        ul.className = 'bp-cart-discount__pills';
16423        ul.setAttribute('data-bp-cart-discount-pills', '');
16424        ul.setAttribute('role', 'list');
16425        form.parentNode.insertBefore(ul, form.nextSibling);
16426      }
16427      ul.innerHTML = applied.map((code) => {
16428        const c = esc(code);
16429        return '<li class="bp-cart-discount__pill" data-bp-cart-discount-pill data-discount-code="' + c + '">' +
16430          '<span class="bp-cart-discount__pill-code">' + c + '</span>' +
16431          '<button type="button" class="bp-cart-discount__pill-remove" aria-label="Remove ' + c + '" data-bp-cart-discount-remove="' + c + '">' +
16432          '<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M3 3l6 6M9 3l-6 6" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/></svg>' +
16433          '</button></li>';
16434      }).join('');
16435    }
16436
16437    function broadcastCartUpdate(cart) {
16438      document.dispatchEvent(new CustomEvent('cart:updated', { detail: { cart } }));
16439      // Update every BP-discount host's data-bp-existing-codes (so the next
16440      // submit carries the new state) AND re-render its applied-code pills in
16441      // place, so the removable chip shows/clears live like the checkout one.
16442      const applied = (cart.discount_codes || [])
16443        .filter((d) => d.applicable)
16444        .map((d) => d.code);
16445      document.querySelectorAll('[data-bp-cart-discount]').forEach((host) => {
16446        host.setAttribute('data-bp-existing-codes', applied.join(','));
16447        renderPills(host, applied);
16448      });
16449    }
16450
16451    // Collapsible promo bar (drawer) — toggle the accordion open/closed.
16452    document.addEventListener('click', (e) => {
16453      const toggle = e.target && e.target.closest && e.target.closest('[data-bp-promo-toggle]');
16454      if (!toggle) return;
16455      const collapse = toggle.closest('[data-bp-promo-collapse]');
16456      if (!collapse) return;
16457      const open = collapse.classList.toggle('is-open');
16458      toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
16459    });
16460
16461    document.addEventListener('submit', async (e) => {
16462      const form = e.target && e.target.closest && e.target.closest('[data-bp-cart-discount-form]');
16463      if (!form) return;
16464      e.preventDefault();
16465      const host = form.closest('[data-bp-cart-discount]');
16466      const input = form.querySelector('[data-bp-cart-discount-input]');
16467      const submit = form.querySelector('[data-bp-cart-discount-submit]');
16468      if (!host || !input) return;
16469      const code = (input.value || '').trim();
16470      if (!code) return;
16471
16472      const existing = getCodesFromHost(host);
16473      if (existing.includes(code)) {
16474        input.value = '';
16475        return;
16476      }
16477      setError(host, false);
16478      if (submit) submit.disabled = true;
16479      try {
16480        const cart = await postDiscount(existing.concat([code]));
16481        if (!isApplicableInCart(cart, code)) {
16482          setError(host, true);
16483          input.value = '';
16484          return;
16485        }
16486        broadcastCartUpdate(cart);
16487        input.value = '';
16488        // Success confirmation. The subtotal change alone is easy to miss and
16489        // the applied-code pills only re-render on reload, so the shopper had
16490        // no signal the code applied (QA 7/22, Dragana). Surface a toast now.
16491        if (window.bpToast) window.bpToast('Promo code "' + code + '" applied.');
16492      } catch (err) {
16493        console.warn('[bp-cart-discount] apply failed', err);
16494        setError(host, true, 'Something went wrong. Please try again.');
16495      } finally {
16496        if (submit) submit.disabled = false;
16497      }
16498    });
16499
16500    document.addEventListener('click', async (e) => {
16501      const btn = e.target && e.target.closest && e.target.closest('[data-bp-cart-discount-remove]');
16502      if (!btn) return;
16503      e.preventDefault();
16504      const host = btn.closest('[data-bp-cart-discount]');
16505      if (!host) return;
16506      const codeToRemove = btn.getAttribute('data-bp-cart-discount-remove');
16507      const existing = getCodesFromHost(host).filter((c) => c !== codeToRemove);
16508      try {
16509        const cart = await postDiscount(existing);
16510        broadcastCartUpdate(cart);
16511      } catch (err) {
16512        console.warn('[bp-cart-discount] remove failed', err);
16513      }
16514    });
16515
16516    // Hydrate the applied-code pills from the live cart on load. A code applied
16517    // in a PRIOR session (persisted on the cart) reliably shows up in /cart.js
16518    // discount_codes, but the server-side Liquid cart object can render empty
16519    // for it, so the server-rendered pill was missing and an already-applied
16520    // code showed no chip until re-applied. Reading the live cart here makes
16521    // the removable chip appear on load regardless.
16522    (function hydrateAppliedCodes() {
16523      const run = () => {
16524        if (!document.querySelector('[data-bp-cart-discount]')) return;
16525        fetch(ROOT + 'cart.js', { credentials: 'same-origin', cache: 'no-store' })
16526          .then((r) => (r.ok ? r.json() : null))
16527          .then((cart) => {
16528            if (!cart) return;
16529            const applied = (cart.discount_codes || [])
16530              .filter((d) => d.applicable)
16531              .map((d) => d.code);
16532            document.querySelectorAll('[data-bp-cart-discount]').forEach((host) => {
16533              host.setAttribute('data-bp-existing-codes', applied.join(','));
16534              renderPills(host, applied);
16535            });
16536          })
16537          .catch(() => {});
16538      };
16539      if (document.readyState === 'loading') {
16540        document.addEventListener('DOMContentLoaded', run);
16541      } else {
16542        run();
16543      }
16544    })();
16545  })();
16546</script>
16546
16547
16548<div class="bp-cart-drawer__subtotal">
16549        <span class="bp-cart-drawer__subtotal-label">Subtotal:</span>
16550        <span class="bp-cart-drawer__subtotal-value" data-bp-cart-subtotal>$0</span><span class="totals__subtotal-value" aria-hidden="true" hidden></span>
16551      </div>
16552<div class="bp-cart-drawer__sp-skeleton" data-bp-sp-skeleton aria-hidden="true">
16553        <div class="bp-cart-drawer__sp-skeleton-head">
16554          <span class="bp-sp-skeleton-bar bp-cart-drawer__sp-skeleton-title"></span>
16555          <span class="bp-sp-skeleton-bar bp-cart-drawer__sp-skeleton-amt"></span>
16556        </div>
16557        <span class="bp-sp-skeleton-bar bp-cart-drawer__sp-skeleton-desc"></span>
16558      </div>
16559      <div
16560        id="narvar-cart-drawer-dp-widget"
16561        class="bp-cart-drawer__narvar-widget"
16562        data-skip-node-update
16563        data-skip-subtree-update
16564      ></div>
16565
16566      <p class="bp-cart-drawer__taxes">Taxes, Shipping, and Discounts calculated at checkout.</p><form id="CartDrawer-Form" action="/cart" method="post" novalidate class="bp-cart-drawer__form"><button
16567          type="submit"
16568          name="checkout"
16569          class="bp-cart-drawer__btn bp-cart-drawer__btn--primary"
16570          data-narvar-feature="CartCheckoutButton"
16571          data-skip-node-update
16572          data-skip-subtree-update
16573        >
16574          Checkout
16575        </button>
16576        <div
16577          id="narvar-cart-drawer-dp-buttons"
16578          class="bp-cart-drawer__narvar-buttons"
16579          data-skip-node-update
16580          data-skip-subtree-update
16581        ></div>
16582      </form>
16583      <a href="/cart" class="bp-cart-drawer__view-bag">View Bag</a>
16584    </footer>
16585  </dialog>
16586</bp-cart-drawer>
16587
16588<style data-shopify>
16589  /* ===== BP Cart Drawer ===== */
16590  bp-cart-drawer { display: contents; }
16591
16592  /* Trigger (icon button in header) — inherits header sizing. */
16593  .bp-cart-drawer__trigger {
16594    position: relative;
16595    background: transparent;
16596    border: 0;
16597    padding: 0;
16598    cursor: pointer;
16599    color: var(--color-foreground);
16600    display: inline-flex;
16601    align-items: center;
16602    justify-content: center;
16603    width: 44px;
16604    height: 44px;
16605  }
16606  .bp-cart-drawer__trigger svg { width: 24px; height: 24px; display: block; }
16607  .bp-cart-drawer__trigger-count {
16608    position: absolute;
16609    top: 4px;
16610    right: 4px;
16611    min-width: 18px;
16612    height: 18px;
16613    padding: 0 5px;
16614    /* 18×18 circular notification badge — kept as a circle (50%)
16615       rather than squared off per the "no rounded corners" sweep
16616       since notification bubbles are conventionally circular and
16617       9px on an 18×18 is geometrically a circle anyway. */
16618    border-radius: 50%;
16619    background: #EBAE55;
16620    /* Dark ink on the gold badge — white (#fff) on #EBAE55 is only 1.96:1,
16621       failing WCAG AA (QA). #171609 on the gold clears AA comfortably. The
16622       larger .bp-cart-drawer__bubble already uses this. */
16623    color: var(--bp-color-text);
16624    font-family: var(--bp-font-body);
16625    font-size: 11px;
16626    font-weight: 500;
16627    display: inline-flex;
16628    align-items: center;
16629    justify-content: center;
16630  }
16631  .bp-cart-drawer__trigger-count[hidden] { display: none; }
16632
16633  /* Dialog. */
16634  .bp-cart-drawer__dialog {
16635    position: fixed;
16636    inset: 0 0 0 auto;
16637    margin: 0;
16638    padding: 0;
16639    border: 0;
16640    width: calc(100vw / 3);
16641    min-width: 480px;
16642    max-width: 100vw;
16643    height: 100dvh;
16644    max-height: 100dvh;
16645    background: var(--bp-color-bg-page, #FEFFFA);
16646    color: var(--bp-color-text);
16647    box-shadow: -8px 0 30px rgb(0 0 0 / 0.12);
16648    overflow: hidden;
16649    font-family: var(--bp-font-body);
16650    z-index: 9999;
16651  }
16652  .bp-cart-drawer__dialog[open] {
16653    display: flex;
16654    flex-direction: column;
16655    animation: bpDrawerSlideIn 0.25s cubic-bezier(0.4, 0, 0.2, 1) forwards;
16656  }
16657  .bp-cart-drawer__dialog.is-closing {
16658    animation: bpDrawerSlideOut 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
16659  }
16660  .bp-cart-drawer__dialog::backdrop { background: rgb(0 0 0 / 0.3); }
16661  @media (max-width: 749px) {
16662    .bp-cart-drawer__dialog { width: 100vw; min-width: 0; }
16663    /* Tighter footer on mobile (QA 7/23, Brooke — Figma parity). */
16664    .bp-cart-drawer__foot { padding: 16px !important; gap: 4px !important; }
16665  }
16666
16667  /* Header. */
16668  .bp-cart-drawer__header {
16669    flex: 0 0 auto;
16670    display: flex;
16671    align-items: center;
16672    justify-content: space-between;
16673    padding: 20px 24px;
16674    border-bottom: 1px solid rgba(23, 22, 9, 0.08);
16675    background: var(--bp-color-bg-page, #FEFFFA);
16676  }
16677  .bp-cart-drawer__heading {
16678    margin: 0;
16679    display: inline-flex;
16680    align-items: center;
16681    gap: 12px;
16682    color: var(--bp-color-text);
16683    font-family: var(--bp-font-display);
16684    font-size: 28px;
16685    font-weight: 300;
16686    line-height: 120%;
16687    letter-spacing: -0.56px;
16688  }
16689  .bp-cart-drawer__bubble {
16690    /* Sunset pill (QA 7/23, Brooke — was 32px circle, white text) */
16691    display: flex;
16692    width: 40px;
16693    padding: 10px 0;
16694    justify-content: center;
16695    align-items: center;
16696    border-radius: 100px;
16697    background: #EBAE55;
16698    color: var(--bp-color-text);
16699    text-align: center;
16700    /* Body / Semi / Small */
16701    font-family: var(--bp-font-body);
16702    font-size: 14px;
16703    font-weight: 660;
16704    line-height: 145%;
16705    letter-spacing: -0.14px;
16706  }
16707  .bp-cart-drawer__close {
16708    background: transparent;
16709    border: 0;
16710    padding: 0;
16711    width: 32px;
16712    height: 32px;
16713    cursor: pointer;
16714    color: var(--bp-color-text);
16715    display: inline-flex;
16716    align-items: center;
16717    justify-content: center;
16718  }
16719  .bp-cart-drawer__close:hover { opacity: 0.6; }
16720
16721  .bp-cart-drawer__body {
16722    flex: 1 1 auto;
16723    overflow-y: auto;
16724    padding: 0 24px;
16725  }
16726
16727  /* Items list. */
16728  .bp-cart-drawer__items {
16729    margin: 0;
16730    padding: 0;
16731    list-style: none;
16732  }
16733
16734  .bp-cart-drawer__empty {
16735    padding: 48px 0;
16736    text-align: center;
16737    color: var(--bp-color-body-copy);
16738    font-family: var(--bp-font-body);
16739  }
16740  .bp-cart-drawer__empty-cta {
16741    /* CTA / CTA Regular */
16742    display: block;
16743    margin: 12px auto 0;
16744    background: transparent;
16745    border: 0;
16746    padding: 0;
16747    cursor: pointer;
16748    font-family: var(--bp-font-body);
16749    font-size: 17px;
16750    font-style: normal;
16751    font-weight: 500;
16752    line-height: normal;
16753    letter-spacing: -0.17px;
16754    leading-trim: both;
16755    text-edge: cap;
16756    color: var(--bp-color-text);
16757    text-decoration: underline;
16758    text-underline-offset: 3px;
16759  }
16760
16761  /* "Recommended for you" rail in the empty bag (QA 7/16). */
16762  .bp-cart-drawer__recs {
16763    margin-top: 40px;
16764    text-align: left;
16765  }
16766  .bp-cart-drawer__recs-head {
16767    display: flex;
16768    align-items: center;
16769    justify-content: space-between;
16770    gap: 12px;
16771    margin-bottom: 16px;
16772  }
16773  .bp-cart-drawer__recs-title {
16774    font-family: var(--bp-font-display);
16775    font-size: 18px;
16776    font-weight: 300;
16777    letter-spacing: -0.36px;
16778    color: var(--bp-color-text);
16779    margin: 0;
16780  }
16781  .bp-cart-drawer__recs-arrows { display: inline-flex; gap: 12px; flex-shrink: 0; }
16782  .bp-cart-drawer__recs-arrow {
16783    /* 44px hit area — same chevron frame as Complete the Look / YMAL. */
16784    width: 44px;
16785    height: 44px;
16786    background: transparent;
16787    border: 0;
16788    padding: 0;
16789    cursor: pointer;
16790    color: var(--bp-color-text);
16791    display: inline-flex;
16792    align-items: center;
16793    justify-content: center;
16794    transition: opacity 0.15s ease;
16795  }
16796  .bp-cart-drawer__recs-arrow:hover { opacity: 0.6; }
16797  /* Both buttons carry the right-pointing glyph; mirror the prev one. */
16798  .bp-cart-drawer__recs-arrow[data-bp-recs-prev] svg { transform: scaleX(-1); }
16799  .bp-cart-drawer__recs-track {
16800    display: flex;
16801    gap: 12px;
16802    margin: 0;
16803    padding: 0;
16804    list-style: none;
16805    overflow-x: auto;
16806    scroll-snap-type: x mandatory;
16807    scrollbar-width: none;
16808    -ms-overflow-style: none;
16809  }
16810  .bp-cart-drawer__recs-track::-webkit-scrollbar { display: none; }
16811  /* Each rail item holds a full bp-product-card (collection eyebrow, swatches,
16812     price). Fixed width so the cards peek in the horizontal rail. */
16813  .bp-cart-drawer__recs-card {
16814    /* % of the rail so ~2.3 cards show (two full + a peek of the third)
16815       regardless of drawer width, rather than three cramped ones (QA 7/27). */
16816    flex: 0 0 42%;
16817    scroll-snap-align: start;
16818  }
16819
16820  /* Complete the Look. */
16821  .bp-cart-drawer__ctl { padding: 24px 0 8px; }
16822  .bp-cart-drawer__ctl-head {
16823    display: flex;
16824    align-items: center;
16825    justify-content: space-between;
16826    margin-bottom: 12px;
16827  }
16828  .bp-cart-drawer__ctl-title {
16829    margin: 0;
16830    font-family: var(--bp-font-display);
16831    font-size: 20px;
16832    font-weight: 300;
16833    letter-spacing: -0.4px;
16834    color: var(--bp-color-text);
16835  }
16836  .bp-cart-drawer__ctl-arrows { display: inline-flex; gap: 12px; }
16837  .bp-cart-drawer__ctl-arrow {
16838    /* 44px hit area matches the Figma chevron frame (QA 7/23). */
16839    width: 44px;
16840    height: 44px;
16841    background: transparent;
16842    border: 0;
16843    padding: 0;
16844    cursor: pointer;
16845    color: var(--bp-color-text);
16846    display: inline-flex;
16847    align-items: center;
16848    justify-content: center;
16849    transition: opacity 0.15s ease;
16850  }
16851  .bp-cart-drawer__ctl-arrow:hover { opacity: 0.6; }
16852  /* Both buttons carry the right-pointing glyph; mirror the prev one. */
16853  .bp-cart-drawer__ctl-arrow[data-bp-ctl-prev] svg { transform: scaleX(-1); }
16854
16855  .bp-cart-drawer__ctl-track {
16856    display: flex;
16857    gap: 12px;
16858    overflow-x: auto;
16859    scroll-behavior: smooth;
16860    scroll-snap-type: x mandatory;
16861    -webkit-overflow-scrolling: touch;
16862    scrollbar-width: none;
16863    -ms-overflow-style: none;
16864  }
16865  .bp-cart-drawer__ctl-track::-webkit-scrollbar { display: none; }
16866  /* Scroll-progress indicator — ported from bp-product-carousel's
16867     .bp-pc__indicator (same thin bar + moving thumb). */
16868  .bp-cart-drawer__ctl-indicator {
16869    margin-top: 12px;
16870    height: 3px;
16871    background: rgba(23, 22, 9, 0.12);
16872    position: relative;
16873    overflow: hidden;
16874  }
16875  .bp-cart-drawer__ctl-indicator::after {
16876    content: '';
16877    position: absolute;
16878    top: 0;
16879    bottom: 0;
16880    left: calc(var(--bp-ctl-thumb-x, 0) * (100% - var(--bp-ctl-thumb-w, 100%)));
16881    width: var(--bp-ctl-thumb-w, 100%);
16882    background: var(--bp-color-text);
16883    transition: left 0.1s linear, width 0.1s linear;
16884  }
16885  .bp-cart-drawer__ctl-card {
16886    /* Fixed card width so cards don't stretch with the drawer/screen
16887       width (QA 7/23, Brooke): on wide screens a flex-fill basis made
16888       each card huge and the square cover image looked zoomed in.
16889       A fixed 175px basis keeps the card size constant and lets more
16890       cards fit per view as the drawer widens (2 on mobile → 3+ on
16891       desktop) instead of two ever-expanding cards. */
16892    flex: 0 0 175px;
16893    max-width: 175px;
16894    min-width: 0;
16895    scroll-snap-align: start;
16896    position: relative;
16897  }
16898  .bp-cart-drawer__ctl-badge {
16899    position: absolute;
16900    top: 8px;
16901    left: 8px;
16902    z-index: 1;
16903    padding: 4px 8px;
16904    background: var(--bp-color-bg-cream);
16905    color: var(--bp-color-text);
16906    font-family: var(--bp-font-body);
16907    font-size: 11px;
16908    font-weight: 500;
16909    letter-spacing: 0.04em;
16910  }
16911  .bp-cart-drawer__ctl-image {
16912    aspect-ratio: 3 / 4;
16913    background: var(--bp-color-bg-cream);
16914    overflow: hidden;
16915    margin-bottom: 8px;
16916  }
16917  .bp-cart-drawer__ctl-image svg,
16918  .bp-cart-drawer__ctl-image img {
16919    width: 100%;
16920    height: 100%;
16921    object-fit: contain;
16922    display: block;
16923  }
16924  .bp-cart-drawer__ctl-name {
16925    margin: 0;
16926    font-family: var(--bp-font-body);
16927    font-size: 13px;
16928    color: var(--bp-color-text);
16929  }
16930  .bp-cart-drawer__ctl-price {
16931    margin: 4px 0 0;
16932    font-family: var(--bp-font-body);
16933    font-size: 13px;
16934    color: var(--bp-color-text);
16935  }
16936  .bp-cart-drawer__ctl-sale { color: var(--bp-color-promo); margin-right: 6px; }
16937  .bp-cart-drawer__ctl-compare { color: var(--bp-color-body-copy); text-decoration: line-through; }
16938
16939  /* Promo code input — hidden in the cart flyout per request (still
16940     available on the /cart page). */
16941  .bp-cart-discount--drawer { display: none; }
16942
16943  /* Footer (sticky). */
16944  .bp-cart-drawer__foot {
16945    flex: 0 0 auto;
16946    background: var(--bp-color-bg-page);
16947    /* Horizontal padding must match .bp-cart-drawer__body/__header (24px) so
16948       the subtotal + checkout buttons line up with the product images/titles
16949       above (QA 7/27 — footer was 16px, 8px left of the body edge, Figma
16950       has them flush). */
16951    padding: 12px 24px 16px;
16952    border-top: 1px solid rgba(23, 22, 9, 0.08);
16953    display: flex;
16954    flex-direction: column;
16955    gap: 6px;
16956  }
16957  .bp-cart-drawer__subtotal {
16958    display: flex;
16959    justify-content: space-between;
16960    align-items: baseline;
16961  }
16962  .bp-cart-drawer__subtotal-label {
16963    /* Heading / H5 (was H4/24px) */
16964    font-family: var(--bp-font-display);
16965    font-size: 20px;
16966    font-style: normal;
16967    font-weight: 300;
16968    line-height: 120%;
16969    letter-spacing: -0.48px;
16970    color: var(--bp-color-text);
16971  }
16972  .bp-cart-drawer__subtotal-value {
16973    /* Body / Regular / Medium */
16974    font-family: var(--bp-font-body);
16975    font-size: 17px;
16976    font-style: normal;
16977    font-weight: 500;
16978    line-height: 145%;
16979    letter-spacing: -0.17px;
16980    color: var(--bp-color-text);
16981    text-align: right;
16982  }
16983
16984  /* Narvar mount slots. The footer's own flex `gap` already reserves
16985     even spacing around the widget whether it's empty or populated, so
16986     no margin here — an earlier `:not(:empty)` margin stacked on top of
16987     that gap once Narvar injected, doubling the space AND causing the
16988     surrounding rows to visibly jump apart as it populated (the opposite
16989     of the intended effect). The injected widget owns its own internal
16990     styling. */
16991  .bp-cart-drawer__narvar-widget,
16992  .bp-cart-drawer__narvar-buttons { width: 100%; }
16993  .bp-cart-drawer__narvar-buttons:not(:empty) { margin-top: 12px; }
16994  .bp-cart-drawer__protection {
16995    background: var(--bp-color-bg-cream);
16996    padding: 14px 16px;
16997    cursor: pointer;
16998    display: block;
16999  }
17000  .bp-cart-drawer__protection-toggle {
17001    position: absolute;
17002    opacity: 0;
17003    pointer-events: none;
17004  }
17005  .bp-cart-drawer__protection-row {
17006    display: flex;
17007    justify-content: space-between;
17008    align-items: baseline;
17009    gap: 8px;
17010  }
17011  .bp-cart-drawer__protection-label {
17012    /* Heading / H6 */
17013    font-family: var(--bp-font-display);
17014    font-size: 14px;
17015    font-weight: 300;
17016    line-height: 120%;
17017    letter-spacing: -0.28px;
17018    color: var(--bp-color-text);
17019    display: inline-flex;
17020    align-items: center;
17021    gap: 6px;
17022  }
17023  .bp-cart-drawer__protection-info {
17024    display: inline-flex;
17025    align-items: center;
17026    color: var(--bp-color-text);
17027    transform: translateY(1px);
17028  }
17029  .bp-cart-drawer__protection-price {
17030    /* Body / Book / Small */
17031    font-family: var(--bp-font-body);
17032    font-size: 14px;
17033    font-weight: 400;
17034    line-height: 145%;
17035    letter-spacing: -0.14px;
17036    color: var(--bp-color-text);
17037    text-align: right;
17038    flex: 0 0 auto;
17039  }
17040  .bp-cart-drawer__protection-help {
17041    /* Body / Book / Tiny */
17042    display: block;
17043    margin-top: 4px;
17044    font-family: var(--bp-font-body);
17045    font-size: 10px;
17046    font-weight: 400;
17047    line-height: 145%;
17048    letter-spacing: -0.1px;
17049    color: var(--bp-color-text);
17050  }
17051
17052  .bp-cart-drawer__taxes {
17053    /* Body / XSmall / Book */
17054    margin: 0;
17055    font-family: var(--bp-font-body);
17056    font-size: 12px;
17057    font-weight: 400;
17058    line-height: 145%;
17059    letter-spacing: -0.12px;
17060    color: var(--bp-color-text);
17061  }
17062
17063  .bp-cart-drawer__form { margin: 0; }
17064  .bp-cart-drawer__btn {
17065    /* CTA / CTA Regular */
17066    width: 100%;
17067    height: 52px;
17068    padding: 0 24px;
17069    border: 1px solid var(--bp-color-text);
17070    cursor: pointer;
17071    font-family: var(--bp-font-body);
17072    font-size: 17px;
17073    font-style: normal;
17074    font-weight: 500;
17075    line-height: normal;
17076    letter-spacing: -0.17px;
17077    leading-trim: both;
17078    text-edge: cap;
17079    transition: opacity 0.2s ease;
17080  }
17081  .bp-cart-drawer__btn--primary {
17082    background: var(--bp-color-text);
17083    color: var(--bp-color-cta-text);
17084  }
17085  .bp-cart-drawer__btn--primary:hover { opacity: 0.85; }
17086  /* Disabled checkout (empty / $0 subtotal): dimmed + non-interactive. */
17087  .bp-cart-drawer__btn--disabled,
17088  .bp-cart-drawer__btn--disabled:hover {
17089    opacity: 0.45;
17090    pointer-events: none;
17091    cursor: not-allowed;
17092  }
17093  .bp-cart-drawer__btn--secondary {
17094    background: var(--bp-color-bg-page);
17095    color: var(--bp-color-text);
17096  }
17097  .bp-cart-drawer__btn--secondary:hover { background: var(--bp-color-bg-cream); }
17098  .bp-cart-drawer__view-bag {
17099    /* CTA / CTA Regular */
17100    align-self: center;
17101    color: var(--bp-color-text);
17102    font-family: var(--bp-font-body);
17103    font-size: 14px;
17104    font-style: normal;
17105    font-weight: 500;
17106    line-height: normal;
17107    letter-spacing: -0.17px;
17108    leading-trim: both;
17109    text-edge: cap;
17110    text-decoration: underline;
17111    text-underline-offset: 3px;
17112    background: transparent;
17113    border: 0;
17114    padding: 0;
17115    cursor: pointer;
17116  }
17117
17118  @keyframes bpDrawerSlideIn {
17119    from { transform: translateX(100%); }
17120    to   { transform: translateX(0); }
17121  }
17122  @keyframes bpDrawerSlideOut {
17123    from { transform: translateX(0); }
17124    to   { transform: translateX(100%); }
17125  }
17126</style>
17127
17128<script type="module">
17129  // ---------------------------------------------------------------------------
17130  // Narvar shipping-protection config (QA 7/22). Narvar's order-sync app embed
17131  // (shopify-app-block, block id 16157100011046449464) emits window.NarvarDPData
17132  // globally, resolving the delivery-protection product via all_products[handle].
17133  // That hits Shopify's 20-UNIQUE-HANDLE all_products cap on product-heavy pages
17134  // (home/PLP render 20+ cards before the end-of-body embed runs), so its
17135  // variant_id/metafield come out BLANK there → `variant_id: ,` SyntaxError →
17136  // window.NarvarDPData never assigned → widget never renders. PDP/cart resolve
17137  // fewer handles, so Narvar's lookup succeeds there. (A Liquid source here fails
17138  // the SAME cap — confirmed — so these are hardcoded store constants instead.)
17139  //
17140  // ensureNarvarData() patches these into Narvar's OWN broken script on drawer
17141  // open and re-executes it, reusing Narvar's real cart_attributes + per-theme
17142  // settings verbatim. Narvar's own values win when present (the repair no-ops
17143  // when window.NarvarDPData is already set, e.g. PDP/cart).
17144  //
17145  // TODO (long-term): Narvar should source its DP variant/metafield from a shop
17146  // metafield / fixed variant ref (cap-proof), not all_products — then this can
17147  // be removed. If the DP product is ever recreated, update BP_NARVAR_DP_VARIANT
17148  // (or swap to a client-side fetch('/products/narvardeliveryprotection.js')).
17149  const BP_NARVAR_DP_VARIANT = 46514716934310; // narvardeliveryprotection variant
17150  const BP_NARVAR_DP_META_RAW = {"isRetailerActive":true,"US":{"version":9,"protectionType":"insurance","currency":"USD","minimumPremiumValue":3,"taxAdjustment":15,"l10ns":{"en":{"title":"Shipping Protection","description":"Protect your purchase from loss, damage, and theft with InsureShield.","tnc":"","dpLogoUrl":"https://assets.narvar.com/delivery-protection/ups-insureshield.png","privacyPolicyUrl":"","tosUrl":"","footerText":"By selecting coverage, you acknowledge you have read and agree to the","learnMoreText":"Program Terms and Conditions.","learnMoreUrl":"https://www.insureshield.com/content/terms-and-conditions/Narvar_TermsAndConditions.pdf","zeroPremiumText":"Your purchase includes complimentary coverage paid by Boston Proper for lost, damaged, and stolen packages with InsureShield.","merchantName":"Boston Proper"}},"eligibilityRule":{"shippingCountries":["US"],"maxOrderValue":2000},"premiumRule":{"condition":{"excludedCategories":[],"excludedShippingCountries":[]},"premium":{"type":"percentage","value":3}},"zeroPremiumRule":{"condition":{"customerTags":[""]}},"serviceFee":0,"insuranceType":"upsc"}};
17151  // Narvar's own code does `JSON.parse(metafield)`, so it must be the JSON STRING.
17152  const BP_NARVAR_DP_METAFIELD = JSON.stringify(BP_NARVAR_DP_META_RAW);
17153
17154  // Patch Narvar's blank config on home/PLP (see the full rationale on
17155  // BpCartDrawer.ensureNarvarData). Match Narvar's ASSIGNMENT script (not our
17156  // own references to the global — ours renders earlier and would self-match),
17157  // fill the blank variant_id/metafield, and re-execute so window.NarvarDPData
17158  // is set. Returns true if the global is now defined. No-op on PDP/cart, where
17159  // Narvar populates it itself.
17160  function bpEnsureNarvarData() {
17161    if (window.NarvarDPData) return true;
17162    const scripts = document.querySelectorAll('script:not([src])');
17163    for (let i = 0; i < scripts.length; i++) {
17164      const txt = scripts[i].textContent || '';
17165      if (!/window\.NarvarDPData\s*=\s*\{/.test(txt)) continue; // Narvar's assignment only
17166      if (!/variant_id:\s*,/.test(txt)) break;                  // already populated → nothing to fix
17167      try {
17168        const fixed = txt
17169          .replace(/variant_id:\s*,/, 'variant_id: ' + String(BP_NARVAR_DP_VARIANT) + ',')
17170          // metafield must be the JSON STRING Narvar's `JSON.parse` expects.
17171          .replace(/metafield:\s*JSON\.stringify\(\s*\)/, 'metafield: ' + JSON.stringify(BP_NARVAR_DP_METAFIELD));
17172        // eslint-disable-next-line no-new-func
17173        new Function(fixed)(); // runs in global scope; assigns window.NarvarDPData
17174      } catch (e) { /* leave undefined */ }
17175      break;
17176    }
17177    return !!window.NarvarDPData;
17178  }
17179
17180  // Run at MODULE LOAD. This module script (in the header) executes
17181  // after DOM parse but BEFORE Narvar's deferred widget bundle at end-of-body
17182  // (deferred scripts run in document order). So setting a valid
17183  // window.NarvarDPData here means Narvar's own bundle reads it and renders the
17184  // widget natively — no drawer-open trigger or narvarCartWidgetInit needed.
17185  // Narvar's inline config script (non-module, ran during parse) has already
17186  // executed by now, so its blank/broken output is present to patch.
17187  try { bpEnsureNarvarData(); } catch (e) { /* non-fatal */ }
17188
17189  // ----- Narvar checkout-CTA casing + whole-dollar price zeros -----
17190  // Narvar's app injects its checkout buttons ("Checkout", "Checkout Without
17191  // Shipping Protection") with `text-transform: uppercase` (its own
17192  // custom_css). The BP stylesheet override (bp-fonts) couldn't reliably
17193  // out-rank it — load order / re-injection let Narvar's uppercase win, so
17194  // the CTAs read ALL CAPS instead of the "first letter cap" the design
17195  // calls for. Fix it inline with !important, which beats any stylesheet
17196  // rule, the moment each button appears. `capitalize` == "first letter cap"
17197  // and is safe for a title- or lower-cased source label. One observer here
17198  // covers BOTH surfaces: the drawer buttons (CartDrawer-*) and the cart
17199  // page buttons (CartPage-*), since this drawer renders on every page.
17200  //
17201  // Same observer also strips ".00" off whole-dollar prices Narvar renders
17202  // itself (site-wide convention — see bp-htwi's stripPriceZeros): the
17203  // checkout button label ("Checkout - $42.00" once Narvar swaps in the
17204  // protection total) and the Shipping Protection widget price. The
17205  // subtotal is handled differently — see the NARVAR_WIDGET_SELECTORS
17206  // comment below for why.
17207  (function () {
17208    if (window.__bpNarvarCtaCasingWired) return;
17209    window.__bpNarvarCtaCasingWired = true;
17210    var IDS = [
17211      'CartDrawer-Checkout-DP-With', 'CartDrawer-Checkout-DP-Without',
17212      'CartPage-Checkout-DP-With', 'CartPage-Checkout-DP-Without'
17213    ];
17214    // The Narvar Shipping Protection mount is a live third-party React app
17215    // that can re-render its internal DOM continuously (toggle state,
17216    // animations). A persistent subtree+characterData observer on it would
17217    // re-run a full text-node walk on every one of those internal
17218    // mutations too, which spirals into a tight synchronous loop and hangs
17219    // the tab — keep this one to a one-shot strip per page-wide childList
17220    // mutation instead (QA 7/27, first crash).
17221    //
17222    // The subtotal element (`.totals__subtotal-value`, Narvar's configured
17223    // `subtotal_selector`) is NOT stripped by this script at all anymore —
17224    // Narvar appears to actively watch + re-assert that exact selector, so
17225    // a characterData observer on it fought Narvar's own logic in an
17226    // infinite write/react loop and froze the tab too (QA 7/27, second
17227    // crash). Narvar now gets its OWN hidden decoy node to own; the visible
17228    // subtotal shoppers see is a separate span we fully control (see
17229    // bp-cart-drawer.liquid's subtotal markup / bp-cart-page.liquid's twin).
17230    var NARVAR_WIDGET_SELECTORS = ['#narvar-cart-drawer-dp-widget', '#narvar-cart-page-dp-widget'];
17231    // Text-node-only walk (mirrors bp-htwi's stripPriceZeros) so element
17232    // structure (icons, nested spans) is left untouched. Idempotent — a
17233    // stripped "$39" has no ".00" left to match.
17234    function stripDotZero(root) {
17235      if (!root) return;
17236      var walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
17237      var node;
17238      while ((node = walker.nextNode())) {
17239        if (node.nodeValue && node.nodeValue.indexOf('.00') !== -1) {
17240          node.nodeValue = node.nodeValue.replace(/(\d)\.00\b/g, '$1');
17241        }
17242      }
17243    }
17244    // The page-wide observer below only watches childList/attributes, so it
17245    // catches an element FIRST APPEARING but not a later direct text-node
17246    // write to it. Give small static price elements (checkout buttons,
17247    // subtotal) their own characterData-watching observer so those later
17248    // writes get caught too.
17249    var watched = new WeakSet();
17250    function watchPriceText(el) {
17251      if (!el) return;
17252      stripDotZero(el);
17253      if (watched.has(el)) return;
17254      watched.add(el);
17255      try {
17256        new MutationObserver(function () { stripDotZero(el); })
17257          .observe(el, { childList: true, subtree: true, characterData: true });
17258      } catch (e) { /* observer unsupported */ }
17259    }
17260    var scheduled = false;
17261    function fixCasing() {
17262      scheduled = false;
17263      for (var i = 0; i < IDS.length; i++) {
17264        var btn = document.getElementById(IDS[i]);
17265        if (!btn) continue;
17266        if (btn.style.textTransform !== 'capitalize') {
17267          btn.style.setProperty('text-transform', 'capitalize', 'important');
17268        }
17269        watchPriceText(btn);
17270      }
17271      for (var k = 0; k < NARVAR_WIDGET_SELECTORS.length; k++) {
17272        stripDotZero(document.querySelector(NARVAR_WIDGET_SELECTORS[k]));
17273      }
17274      // Site convention: no ".00" on whole-dollar amounts (matches the drawer
17275      // subtotal's formatMoney + the Liquid `money | replace: '.00', ''`).
17276      // Narvar's #checkout-price span (subtotal + protection, shown on the
17277      // DP-With button now that #307 no longer hides it) renders "$40.00" —
17278      // strip the trailing .00 so it reads "$40" like the rest of the cart (QA
17279      // 7/27, Dragana). Guarded on a .00 match so our own edit doesn't loop the
17280      // observer. querySelectorAll (not getElementById) in case Narvar reuses
17281      // the id across the flyout + cart-page buttons.
17282      var priceEls = document.querySelectorAll('[id="checkout-price"]');
17283      for (var k = 0; k < priceEls.length; k++) {
17284        var txt = priceEls[k].textContent;
17285        if (txt && /\.00(\D|$)/.test(txt)) {
17286          priceEls[k].textContent = txt.replace(/\.00(\D|$)/g, '$1');
17287        }
17288      }
17289    }
17290    function schedule() {
17291      if (scheduled) return;
17292      scheduled = true;
17293      requestAnimationFrame(fixCasing);
17294    }
17295    // Narvar injects/mutates these buttons asynchronously (on load for the
17296    // cart page, on drawer open for the drawer), so watch for it. `style`
17297    // is intentionally NOT in attributeFilter — our own inline set would
17298    // re-trigger this page-wide pass (the per-element observers above cover
17299    // the text-content case that needed characterData).
17300    try {
17301      new MutationObserver(schedule).observe(document.documentElement, {
17302        childList: true, subtree: true, attributes: true, attributeFilter: ['id', 'class']
17303      });
17304    } catch (e) { /* observer unsupported — the initial pass below still runs */ }
17305    fixCasing();
17306  })();
17307
17308  // ----- Shipping Protection loading skeleton (QA 7/27, Dragana) -----
17309  // The SP widget is injected by Narvar's async bundle a few seconds after the
17310  // flyout opens / the cart page loads. A shimmer skeleton holds the box shape
17311  // until then (CSS `:has(.narvar-cart-widget-card)` hides it the instant the
17312  // real box renders). This JS is the belt-and-braces layer: it hides each
17313  // skeleton the moment its sibling mount gets a child (covers browsers without
17314  // `:has()`), and after a grace period hides any skeleton whose mount is still
17315  // empty — Narvar renders NO widget for ineligible carts (non-US / over the
17316  // max order value), and a lingering loading box would be misleading. Covers
17317  // both surfaces (this drawer renders on every page, incl. /cart). Supersedes
17318  // the earlier reserve-space approach (#307).
17319  (function () {
17320    if (window.__bpSpSkeletonWired) return;
17321    window.__bpSpSkeletonWired = true;
17322    function hide(skel) { if (skel) skel.classList.add('bp-sp-skeleton--hidden'); }
17323    function mountFor(skel) {
17324      // The Narvar mount is the skeleton's next element sibling.
17325      var el = skel.nextElementSibling;
17326      return (el && /narvar-cart-(drawer|page)-dp-widget/.test(el.id || '')) ? el : null;
17327    }
17328    var skels = document.querySelectorAll('[data-bp-sp-skeleton]');
17329    for (var i = 0; i < skels.length; i++) {
17330      (function (skel) {
17331        var mount = mountFor(skel);
17332        if (!mount) { hide(skel); return; }
17333        if (mount.firstChild) { hide(skel); return; } // already populated
17334        try {
17335          var mo = new MutationObserver(function () {
17336            if (mount.firstChild) { hide(skel); mo.disconnect(); }
17337          });
17338          mo.observe(mount, { childList: true });
17339        } catch (e) { /* no observer — the timeout below still resolves it */ }
17340      })(skels[i]);
17341    }
17342    // Grace period: drop any skeleton Narvar never filled (ineligible carts).
17343    window.setTimeout(function () {
17344      var s = document.querySelectorAll('[data-bp-sp-skeleton]');
17345      for (var j = 0; j < s.length; j++) {
17346        var m = s[j].nextElementSibling;
17347        if (!m || !m.firstChild) hide(s[j]);
17348      }
17349    }, 6000);
17350  })();
17351
17352  // ----- Line item delegation + cart mutation helper -----
17353  // Registered once per page from the drawer (which always renders),
17354  // not from the line item snippet (which doesn't render when the cart
17355  // is empty, leaving the empty-cart-then-add path with no listeners).
17356  if (!window.__bpCartLineWired) {
17357    window.__bpCartLineWired = true;
17358
17359    document.addEventListener('click', async (e) => {
17360      const line = e.target.closest('[data-bp-cart-line]');
17361      if (!line) return;
17362      const key = line.dataset.lineKey;
17363
17364      const stepBtn = e.target.closest('[data-bp-qty-step]');
17365      const removeBtn = e.target.closest('[data-bp-remove]');
17366      const saveBtn = e.target.closest('[data-bp-save]');
17367
17368      if (stepBtn) {
17369        const input = line.querySelector('[data-bp-qty-input]');
17370        const next = Math.max(1, (parseInt(input.value, 10) || 1) + parseInt(stepBtn.dataset.bpQtyStep, 10));
17371        await window.bpCartChange(key, next);
17372        return;
17373      }
17374      if (removeBtn) {
17375        await window.bpCartChange(key, 0);
17376        return;
17377      }
17378      if (saveBtn) {
17379        // Atlas parity — route the save through window.handleSaveForLater
17380        // (bp-swym-helpers). That fn calls Swym's AddToSmartWishlist,
17381        // removes the line from cart, updates the customer-scoped
17382        // local mirror (`save-for-later-items`), and dispatches the
17383        // wishlist + cart events the drawer + saved-drawer listen to.
17384        try {
17385          const cart = await fetch('/cart.js', { cache: 'no-store', credentials: 'same-origin' }).then((r) => r.json());
17386          const item = cart.items.find((i) => i.key === key);
17387          if (item) {
17388            const product = {
17389              product_id: item.product_id,
17390              id: item.product_id,
17391              handle: item.handle,
17392              variant_id: item.variant_id,
17393              variant_title: item.variant_title,
17394              variant_price: item.final_price,
17395              variant_compare_at_price: item.original_price,
17396              title: item.product_title,
17397              image: item.image,
17398              quantity: item.quantity,
17399              properties: item.properties,
17400              sku: item.sku,
17401              variant_sku: item.sku,
17402              line_key: item.key,
17403              tags: item.tags
17404            };
17405            if (typeof window.handleSaveForLater === 'function') {
17406              await window.handleSaveForLater({ preventDefault: () => {} }, product);
17407            } else {
17408              // Fallback if bp-swym-helpers hasn't loaded yet — drop the
17409              // line and stash a minimal snapshot under the legacy key
17410              // so the next page load can migrate it.
17411              const saved = JSON.parse(localStorage.getItem('bp.saved_for_later') || '[]');
17412              saved.unshift({
17413                variantId: item.variant_id, productId: item.product_id, key: item.key,
17414                title: item.product_title, variantTitle: item.variant_title,
17415                image: item.image, price: item.final_price, url: item.url,
17416                quantity: item.quantity, properties: item.properties, savedAt: Date.now()
17417              });
17418              localStorage.setItem('bp.saved_for_later', JSON.stringify(saved.slice(0, 50)));
17419              document.dispatchEvent(new CustomEvent('bp:saved:updated'));
17420              await window.bpCartChange(key, 0);
17421            }
17422            saveBtn.classList.add('is-saved');
17423          }
17424        } catch (err) { console.error('[bp-cart] save-for-later failed', err); }
17425        return;
17426      }
17427    });
17428
17429    document.addEventListener('change', (e) => {
17430      const input = e.target.closest('[data-bp-qty-input]');
17431      if (!input) return;
17432      const line = input.closest('[data-bp-cart-line]');
17433      if (!line) return;
17434      const next = Math.max(1, parseInt(input.value, 10) || 1);
17435      window.bpCartChange(line.dataset.lineKey, next);
17436    });
17437
17438    // Cart mutation helper — POSTs to /cart/change.js, then dis
17438patches
17439    // `cart:updated` with the new cart in event.detail so the drawer
17440    // updates line items in place without a page reload.
17441    window.bpCartChange = async (key, quantity) => {
17442      try {
17443        const res = await fetch('/cart/change.js', {
17444          method: 'POST',
17445          headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
17446          body: JSON.stringify({ id: key, quantity }),
17447          cache: 'no-store',
17448          credentials: 'same-origin'
17449        });
17450        if (!res.ok) throw new Error('HTTP ' + res.status);
17451        const cart = await res.json();
17452        document.dispatchEvent(new CustomEvent('cart:updated', { detail: { cart } }));
17453        return cart;
17454      } catch (e) { console.error('[bp-cart] change failed', e); }
17455    };
17456  }
17457
17458  if (!customElements.get('bp-cart-drawer')) {
17459    class BpCartDrawer extends HTMLElement {
17460      connectedCallback() {
17461        this.dialog = this.querySelector('[data-bp-cart-dialog]');
17462        this.opener = this.querySelector('[data-bp-cart-open]');
17463        if (!this.dialog || !this.opener) return;
17464
17465        this.opener.addEventListener('click', (e) => {
17466          e.preventDefault();
17467          this.open();
17468        });
17469
17470        this.dialog.addEventListener('click', (e) => {
17471          if (e.target.closest('[data-bp-cart-close]')) {
17472            e.preventDefault();
17473            this.close();
17474            return;
17475          }
17476          // Narvar's Shipping Protection info icon opens an info surface that
17477          // would be clipped by the drawer — close the drawer on click so it
17478          // shows (Narvar's own handler still runs; we don't preventDefault).
17479          if (e.target.closest('.narvar-cart-widget-info-icon')) {
17480            this.close();
17481            return;
17482          }
17483          if (e.target === this.dialog) this.close();
17484        });
17485
17486        this.dialog.addEventListener('cancel', (e) => {
17487          e.preventDefault();
17488          this.close();
17489        });
17490
17491        // Complete-the-Look arrow nav — same pattern as bp-cart-page.liquid.
17492        // Track + buttons are server-rendered empty/present up front (see
17493        // markup above), so wiring at connect time is safe even though the
17494        // track itself is populated later by bp-cart-recommendations.liquid.
17495        const ctlTrack = this.querySelector('[data-bp-ctl-track]');
17496        const ctlPrev = this.querySelector('[data-bp-ctl-prev]');
17497        const ctlNext = this.querySelector('[data-bp-ctl-next]');
17498        if (ctlTrack && ctlPrev && ctlNext) {
17499          const ctlStep = () => Math.max(160, ctlTrack.clientWidth / 4);
17500          ctlPrev.addEventListener('click', () => ctlTrack.scrollBy({ left: -ctlStep(), behavior: 'smooth' }));
17501          ctlNext.addEventListener('click', () => ctlTrack.scrollBy({ left: ctlStep(), behavior: 'smooth' }));
17502        }
17503
17504        // "Recommended for you" (empty-bag) arrow nav — same pattern. The rail is
17505        // a horizontal scroll track with no drag affordance on desktop, so the
17506        // arrows are the way to page through it (QA 8/05, Brooke).
17507        // "Recommended for you" (empty-bag) arrow nav — DELEGATED on the drawer
17508        // so it fires regardless of when the rail is rendered/re-rendered, and
17509        // can't be missed by a connect-time query. `scroll-snap-type: mandatory`
17510        // snaps a programmatic SMOOTH scroll straight back to 0, so we scroll
17511        // instantly (which lands + snaps cleanly) and page by ~2 whole cards so
17512        // the target sits on a snap point (QA 8/05, Brooke).
17513        this.addEventListener('click', (e) => {
17514          const t = e.target;
17515          const dir = (t.closest && t.closest('[data-bp-recs-next]')) ? 1
17516                    : (t.closest && t.closest('[data-bp-recs-prev]')) ? -1 : 0;
17517          if (!dir) return;
17518          e.preventDefault();
17519          const track = this.querySelector('.bp-cart-drawer__recs-track');
17520          if (!track) return;
17521          const card = track.querySelector('.bp-cart-drawer__recs-card');
17522          const pitch = card ? card.getBoundingClientRect().width + 12 : track.clientWidth * 0.42;
17523          track.scrollBy({ left: dir * Math.round(pitch) * 2 });
17524        });
17525
17526        // Listen for cart updates from anywhere (PDP add, quick-add, etc.).
17527        // BP-internal: `cart:updated` carries the cart in event.detail.cart.
17528        document.addEventListener('cart:updated', (e) => {
17529          if (e.detail && e.detail.cart) this.applyCart(e.detail.cart);
17530          else this.refresh();
17531        });
17532        document.addEventListener('product:added', (e) => {
17533          this.open();
17534          if (e.detail && e.detail.cart) this.applyCart(e.detail.cart);
17535          else this.refresh();
17536        });
17537        // Horizon-native: `cart:update` is dispatched by product-form on PDP
17538        // adds, by quick-add, by upsells, etc. Cart object lives in
17539        // event.detail.resource. Open the drawer + sync state.
17540        document.addEventListener('cart:update', (e) => {
17541          const detail = e.detail || {};
17542          if (detail.data && detail.data.didError) return;
17543          // Source may be 'product-form-component' (PDP), quick-add, or
17544          // cart-line edits. Auto-open only on add-to-cart-style sources.
17545          const source = detail.data && detail.data.source;
17546          const isAdd = source === 'product-form-component' ||
17547                        source === 'quick-add-component' ||
17548                        source === 'product-card-component';
17549          if (isAdd) this.open();
17550          if (detail.resource) this.applyCart(detail.resource);
17551          else this.refresh();
17552        });
17553        // Discount Kit (Helium) dispatches this when it adds/removes a
17554        // GWP line item in the cart. Mirror Atlas's CartFlyout behavior:
17555        // open the drawer so the customer sees the change, then refresh.
17556        document.addEventListener('discount_kit:cart_changed', () => {
17557          this.open();
17558          this.refresh();
17559        });
17560
17561        // Bulletproofing (QA 7/16, Critical): never allow checkout when there
17562        // are no REAL products — only the Narvar shipping-protection add-on can
17563        // linger ($3 orphan). Capture phase so it beats Narvar's own submit
17564        // handler on the injected DP buttons (they share this form). Falls
17565        // through to a full refresh, which clears any orphaned DP line.
17566        const checkoutForm = this.querySelector('#CartDrawer-Form');
17567        if (checkoutForm) {
17568          checkoutForm.addEventListener('submit', (e) => {
17569            if (this._realCount === 0) {
17570              e.preventDefault();
17571              e.stopImmediatePropagation();
17572              this.#showEmptyUI();
17573              this.refresh();
17574            }
17575          }, { capture: true });
17576        }
17577
17578        // Bundle upsell ("Complete the look") is rendered by the shared global
17579        // helper (snippets/bp-cart-bundle-upsell.liquid → window.bpBundleUpsell),
17580        // which self-wires off bp:cart-drawer:opened / bp:cart-lines:rendered /
17581        // cart:updated — no per-surface code here.
17582        //
17583        // Narvar config repair is intentionally NOT run at page load. Doing so
17584        // (and proactively calling narvarCartWidgetInit) double-fired Narvar's
17585        // own auto-init on the PDP and broke its render there. The repair runs
17586        // on drawer open instead (remountNarvar → ensureNarvarData), which is
17587        // the only place the drawer widget is actually needed and leaves
17588        // Narvar's page-load path untouched.
17589      }
17590
17591      open() {
17592        if (this.dialog.open) return;
17593        // Scroll suppression — freeze the page so the only scrollable area is
17594        // the cart body. `<html>` is not the scroller here and showModal()
17595        // alone doesn't stop the page behind the backdrop from scrolling, so
17596        // toggling html overflow did nothing. Pin the body in place at its
17597        // current offset (position:fixed) — the exact technique Horizon's
17598        // dialog.js uses. Restored + scroll position re-applied on close.
17599        const existingTop = document.body.style.top;
17600        const existingPosition = document.body.style.position;
17601        if (existingPosition === 'fixed' && existingTop) {
17602          this._lockScrollY = Math.abs(parseInt(existingTop, 10)) || 0;
17603        } else {
17604          this._lockScrollY = window.scrollY;
17605        }
17606
17607        document.body.style.width = '100%';
17608        document.body.style.position = 'fixed';
17609        document.body.style.top = `-${this._lockScrollY}px`;
17610
17611        if (typeof this.dialog.showModal === 'function') this.dialog.showModal();
17612        else this.dialog.setAttribute('open', '');
17613        // Notify the cart Complete-the-Look snippet (and anyone else
17614        // watching) that the drawer is now visible. The CTL snippet
17615        // re-syncs on this so cards appear the first time the drawer
17616        // opens, even when the cart was already populated server-side
17617        // and no cart mutation event has fired since.
17618        document.dispatchEvent(new CustomEvent('bp:cart-drawer:opened'));
17619
17620        // Narvar shipping-protection widget. Narvar's cart-widget script is
17621        // loaded on every page, but it only AUTO-renders on pages it detects as
17622        // a cart context (looks for `<cart-drawer>` + a `/cart` URL). Lana's
17623        // drawer is `<bp-cart-drawer>`, so on home / PLP the widget never
17624        // appeared. remountNarvar() calls Narvar's exposed init on open so it
17625        // renders into the drawer mount anywhere (QA 7/21).
17626        this.remountNarvar();
17627      }
17628
17629      ensureNarvarData() {
17630        // ROOT CAUSE (QA 7/21): Narvar's app-embed injects an end-of-body
17631        // script that sets window.NarvarDPData with variant_id and metafield
17632        // printed from the Liquid `product` object plus a static settings block.
17633        // On non-product pages (home, PLP) `product` is nil, so it renders
17634        // `variant_id: ,` (a bare comma → SyntaxError that aborts the whole
17635        // script before the assignment) AND `metafield: JSON.stringify()`
17636        // (evaluates to undefined). window.NarvarDPData is left unset, so the
17637        // widget has no config and never renders. On PDP/cart both are populated
17638        // → valid JS → it works. That is the "PDP+cart yes, home+PLP no" split.
17639        //
17640        // Both blank values are STORE CONSTANTS — the narvardeliveryprotection
17641        // product's variant + its narvar.dp_config metafield (the InsureShield
17642        // config the widget needs for its title/description/premium). We source
17643        // them in Liquid (BP_NARVAR_DP_VARIANT / BP_NARVAR_DP_METAFIELD) and
17644        // patch them into Narvar's OWN broken script, then re-execute it so the
17645        // rest — Narvar's real cart_attributes + per-theme settings — is reused
17646        // verbatim (we can't recompute the cart_attributes quote/aid blob).
17647        //
17648        // Narvar's own values take precedence: this no-ops when NarvarDPData is
17649        // already set (PDP/cart), and the `variant_id: ,` guard skips any valid
17650        // (populated) script. Runs on drawer OPEN only — a load-time re-run that
17651        // also called narvarCartWidgetInit double-fired Narvar's auto-init on the
17652        // PDP and broke its render, so we leave Narvar's page-load path alone.
17653        // Delegates to the module-level bpEnsureNarvarData (already run once at
17654        // module load). Re-invoked on drawer open as a belt-and-suspenders in
17655        // case Narvar's config script landed after our load-time pass.
17656        return bpEnsureNarvarData();
17657      }
17658
17659      remountNarvar() {
17660        // Narvar's cart-widget (React) observes the document and renders its
17661        // shipping-protection widget into #narvar-cart-drawer-dp-widget when it
17662        // detects the mount + a valid config. It auto-renders on the PDP + /cart
17663        // but not home/PLP — because window.NarvarDPData is unset there (see
17664        // ensureNarvarData). Repair the config first, then poll its exposed init
17665        // (window.narvarCartWidgetInit) so it renders into the (existing) drawer
17666        // mount on open, beating the async-load race ("open immediately = empty,
17667        // wait ~2s = loads").
17668        //
17669        // NON-DESTRUCTIVE: do NOT remove/replace the mount. Removing it yanked
17670        // the node out from under Narvar mid-render and broke the PDP/cart cases
17671        // that already worked — leave the mount in place and only invoke init.
17672        this.ensureNarvarData();
17673        const filled = () => {
17674          const w = this.querySelector('#narvar-cart-drawer-dp-widget');
17675          return !w || w.children.length > 0;
17676        };
17677        if (filled()) return;
17678
17679        let tries = 0;
17680        const MAX_TRIES = 24; // 24 × 250ms ≈ 6s
17681        const tick = () => {
17682          if (filled() || !this.dialog.open) return;   // done, or drawer closed
17683          if (typeof window.narvarCartWidgetInit === 'function') {
17684            try { window.narvarCartWidgetInit(); } catch (e) { /* keep retrying */ }
17685          }
17686          if (++tries < MAX_TRIES) setTimeout(tick, 250);
17687        };
17688        requestAnimationFrame(tick); // start polling next frame
17689      }
17690
17691      close() {
17692        if (this._closing || !this.dialog.open) return;
17693        this._closing = true;
17694        this.dialog.classList.add('is-closing');
17695        const onEnd = () => {
17696          this.dialog.classList.remove('is-closing');
17697          this._closing = false;
17698          try { this.dialog.close(); } catch (_) { this.dialog.removeAttribute('open'); }
17699          // Release the body scroll lock and restore the pre-open scroll
17700          // position (position:fixed had reset it to 0 visually via top offset).
17701          document.body.style.width = '';
17702          document.body.style.position = '';
17703          document.body.style.top = '';
17704          if (this._lockScrollY != null) {
17705            window.scrollTo({ top: this._lockScrollY, behavior: 'instant' });
17706            this._lockScrollY = null;
17707          }
17708        };
17709        this.dialog.addEventListener('animationend', onEnd, { once: true });
17710        setTimeout(() => { if (this._closing) onEnd(); }, 350);
17711      }
17712
17713      async refresh() {
17714        try {
17715          const res = await fetch('/cart.js', {
17716            headers: { Accept: 'application/json' },
17717            cache: 'no-store',
17718            credentials: 'same-origin'
17719          });
17720          const cart = await res.json();
17721          this.applyCart(cart);
17722        } catch (e) { console.error('[bp-cart-drawer] refresh failed', e); }
17723      }
17724
17725      applyCart(cart) {
17726        // The Narvar Shipping Protection line (SKU narvardeliveryprotection)
17727        // is an add-on, not a product the shopper chose — it must never count
17728        // toward the bag, and it must not keep the cart from reading as empty.
17729        const INSURANCE_SKU = 'narvardeliveryprotection';
17730        const items = Array.isArray(cart.items) ? cart.items : [];
17731        const insuranceLine = items.find((i) => (i.sku || '').toLowerCase() === INSURANCE_SKU);
17732        const realCount = items.reduce(
17733          (n, i) => ((i.sku || '').toLowerCase() === INSURANCE_SKU ? n : n + i.quantity),
17734          0
17735        );
17736
17737        // When every real product has been removed but the cart still carries
17738        // lines — the Narvar Shipping Protection add-on, which Narvar re-adds
17739        // while its toggle is on, so removing just that ONE line races the
17740        // re-add and it lingers with a $3 total you can still check out (QA
17741        // 7/16, Critical) — clear the WHOLE cart. /cart/clear drops every line
17742        // AND the cart attributes Narvar keys its toggle off, so the insurance
17743        // can't come back. Guarded so the resulting empty cart:updated doesn't
17744        // loop; return early so we never paint the transient "$3, no items"
17745        // state (which was also letting the checkout button show a price over
17746        // an empty bag).
17747        this._realCount = realCount;
17748        if (realCount === 0 && items.length > 0 && !this._clearingCart) {
17749          this._clearingCart = true;
17750          // Optimistically paint the empty state NOW. Without this the drawer
17751          // kept showing the stale items + footer + Narvar button/protection
17752          // during the async clear round-trip, so an "empty bag" could still
17753          // show "Checkout - $68" and a $3 protection line (QA 7/16, Critical).
17754          this.#showEmptyUI();
17755          fetch('/cart/clear.js', {
17756            method: 'POST',
17757            headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
17758            cache: 'no-store',
17759            credentials: 'same-origin'
17760          })
17761            .then((r) => r.json())
17762            .then((c) => document.dispatchEvent(new CustomEvent('cart:updated', { detail: { cart: c } })))
17763            .catch((e) => console.error('[bp-cart-drawer] clear failed', e))
17764            .finally(() => { this._clearingCart = false; });
17765          return;
17766        }
17767
17768        // Count bubble + trigger count — reflect real products only.
17769        const bubble = this.querySelector('[data-bp-cart-bubble]');
17770        const triggerCount = this.querySelector('[data-bp-cart-trigger-count]');
17771        if (bubble) bubble.textContent = realCount;
17772        if (triggerCount) {
17773          triggerCount.textContent = realCount;
17774          triggerCount.toggleAttribute('hidden', realCount === 0);
17775        }
17776        // a11y: announce the new cart count via Horizon's existing status
17777        // live region (header-actions.liquid) — it was rendered but never
17778        // written to, so cart changes were silent to screen readers.
17779        try {
17780          const live = document.querySelector('[data-testid="cart-count-live-region"]');
17781          // Only announce on an actual change — the first applyCart() primes
17782          // _bpLastCount silently so a page-load / drawer-open render with no
17783          // change doesn't speak the count.
17784          if (live && this._bpLastCount !== undefined && realCount !== this._bpLastCount) {
17785            live.textContent = realCount === 1
17786              ? '1 item in your bag'
17787              : realCount + ' items in your bag';
17788          }
17789          this._bpLastCount = realCount;
17790        } catch (_) { /* non-fatal */ }
17791        // Subtotal = merchandise only. cart.total_price INCLUDES the Narvar
17792        // Shipping Protection line (SKU narvardeliveryprotection); once Narvar
17793        // adds that line (e.g. after the checkout round-trip) total_price jumps
17794        // to products+protection while the rows still show products only, so
17795        // the Subtotal read as a "lie" ($372.42 instead of $360, QA 8/04,
17796        // Dragana). Sum the non-protection lines — same formula as the Liquid
17797        // render + the visible row prices; protection stays in its own box.
17798        const bpMerchSubtotal = cart.items.reduce(
17799          (sum, i) => ((i.sku || '').toLowerCase() === 'narvardeliveryprotection' ? sum : sum + i.final_line_price),
17800          0
17801        );
17802        const subtotal = this.querySelector('[data-bp-cart-subtotal]');
17803        if (subtotal) subtotal.textContent = this.formatMoney(bpMerchSubtotal);
17804
17805        // Disable checkout when there's nothing to pay for ($0 subtotal). Covers
17806        // the primary Checkout button plus any Narvar-injected DP checkout
17807        // buttons that share the form, so a $0 bag can never start checkout.
17808        const noSubtotal = !(bpMerchSubtotal > 0);
17809        this.querySelectorAll(
17810          '.bp-cart-drawer__btn--primary, #CartDrawer-Form [name="checkout"], #narvar-cart-drawer-dp-buttons button, #narvar-cart-drawer-dp-buttons a'
17811        ).forEach((btn) => {
17812          if ('disabled' in btn) btn.disabled = noSubtotal;
17813          btn.toggleAttribute('aria-disabled', noSubtotal);
17814          btn.classList.toggle('bp-cart-drawer__btn--disabled', noSubtotal);
17815        });
17816
17817        // Per-line updates: walk every existing line and either update qty/price
17818        // in place or remove it if its product is genuinely gone.
17819        //
17820        // Match by line key first, then fall back to VARIANT id. The server-
17821        // rendered `data-line-key` () doesn't always byte-match the
17822        // AJAX cart's `item.key`; when it didn't, the line was treated as "gone"
17823        // — it faded out and syncItemsList re-added it, so a simple qty step made
17824        // the row disappear and reappear. Matching by variant keeps the row and
17825        // updates it in place (and re-syncs its key so later updates match
17826        // exactly). existingKeys tracks the RESOLVED cart keys so hasNewItems
17827        // below can't false-positive off the same mismatch and re-render.
17828        const byKey = new Map(cart.items.map((i) => [i.key, i]));
17829        const byVariant = new Map();
17830        cart.items.forEach((i) => {
17831          const arr = byVariant.get(i.variant_id) || [];
17832          arr.push(i);
17833          byVariant.set(i.variant_id, arr);
17834        });
17835        const existingKeys = new Set();
17836        this.querySelectorAll('[data-bp-cart-line]').forEach((line) => {
17837          let item = byKey.get(line.dataset.lineKey);
17838          if (!item) {
17839            const vid = parseInt(line.dataset.variant, 10);
17840            const bucket = byVariant.get(vid);
17841            if (bucket && bucket.length) {
17842              item = bucket.shift();           // consume one line of this variant
17843              line.dataset.lineKey = item.key; // re-sync so future updates key-match
17844            }
17845          }
17846          if (!item) {
17847            line.style.transition = 'opacity 0.2s ease, transform 0.2s ease';
17848            line.style.opacity = '0';
17849            line.style.transform = 'translateX(8px)';
17850            setTimeout(() => line.remove(), 220);
17851            return;
17852          }
17853          existingKeys.add(item.key);
17854          const qty = line.querySelector('[data-bp-qty-input]');
17855          if (qty && qty.value !== String(item.quantity)) qty.value = item.quantity;
17856          const price = line.querySelector('[data-bp-line-price]');
17857          if (price) price.textContent = this.formatMoney(item.final_line_price);
17858          // Original price — struck through, shown only while a discount
17859          // (promo code, etc.) actually lowers the line. Mirrors the
17860          // Liquid render's hidden-by-default state (bp-cart-line-item.liquid)
17861          // so applying/removing a code updates it live without a refetch.
17862          const compare = line.querySelector('[data-bp-line-compare]');
17863          if (compare) {
17864            const hasDiscount = item.original_line_price > item.final_line_price;
17865            compare.hidden = !hasDiscount;
17866            if (hasDiscount) compare.textContent = this.formatMoney(item.original_line_price);
17867          }
17868        });
17869
17870        // If any item in the cart doesn't have a row in the drawer yet
17871        // (e.g., PDP add introduced a new line), fetch a fresh render of
17872        // the header section and swap in the new items list HTML.
17873        // Exclude the insurance line — it never gets a drawer row, so counting
17874        // it here would trigger a needless re-render fetch on every cart update.
17875        const hasNewItems = items.some(
17876          (i) => (i.sku || '').toLowerCase() !== INSURANCE_SKU && !existingKeys.has(i.key)
17877        );
17878        if (hasNewItems) this.syncItemsList();
17879
17880        // Empty-state vs items-list + footer/CTL visibility.
17881        const itemsList = this.querySelector('[data-bp-cart-items]');
17882        const emptyState = this.querySelector('[data-bp-cart-empty]');
17883        const foot = this.querySelector('.bp-cart-drawer__foot');
17884        const ctl = this.querySelector('[data-bp-ctl]');
17885        const isEmpty = realCount === 0;
17886        if (itemsList) itemsList.toggleAttribute('hidden', isEmpty);
17887        if (emptyState) emptyState.toggleAttribute('hidden', !isEmpty);
17888        if (foot) foot.toggleAttribute('hidden', isEmpty);
17889        if (ctl) ctl.toggleAttribute('hidden', isEmpty);
17890
17891        // Bundle upsell ("Complete the look") is owned by the shared global
17892        // helper window.bpBundleUpsell (snippets/bp-cart-bundle-upsell.liquid),
17893        // which self-renders off cart:updated / bp:cart-lines:rendered — nothing
17894        // needed here.
17895      }
17896
17897      // Force the drawer's empty presentation immediately. Used optimistically
17898      // while /cart/clear round-trips (so no stale items / Narvar checkout price
17899      // / $3 protection line flashes over an empty bag) and as the submit-guard
17900      // fallback. Zeroes counts + subtotal and hides the footer + CTL.
17901      #showEmptyUI() {
17902        this._realCount = 0;
17903        const bubble = this.querySelector('[data-bp-cart-bubble]');
17904        const triggerCount = this.querySelector('[data-bp-cart-trigger-count]');
17905        if (bubble) bubble.textContent = '0';
17906        if (triggerCount) { triggerCount.textContent = '0'; triggerCount.setAttribute('hidden', ''); }
17907        const subtotal = this.querySelector('[data-bp-cart-subtotal]');
17908        if (subtotal) subtotal.textContent = this.formatMoney(0);
17909        const itemsList = this.querySelector('[data-bp-cart-items]');
17910        const emptyState = this.querySelector('[data-bp-cart-empty]');
17911        const foot = this.querySelector('.bp-cart-drawer__foot');
17912        const ctl = this.querySelector('[data-bp-ctl]');
17913        if (itemsList) itemsList.setAttribute('hidden', '');
17914        if (emptyState) emptyState.removeAttribute('hidden');
17915        if (foot) foot.setAttribute('hidden', '');
17916        if (ctl) ctl.setAttribute('hidden', '');
17917      }
17918
17919      async syncItemsList() {
17920        try {
17921          let html = '';
17922
17923          // 1. Try Shopify Section Rendering API. Faster + lighter when it works.
17924          //    Walk every ancestor section wrapper and ask each one in parallel —
17925          //    one of them is the section that renders the cart drawer.
17926          const sectionWrappers = [];
17927          let el = this.parentElement;
17928          while (el) {
17929            if (el.id && el.id.startsWith('shopify-section-')) sectionWrappers.push(el.i
17929d.replace(/^shopify-section-/, ''));
17930            el = el.parentElement;
17931          }
17932
17933          for (const sectionId of sectionWrappers) {
17934            try {
17935              const res = await fetch(`${window.location.pathname}?sections=${sectionId}`, {
17936                headers: { Accept: 'application/json' },
17937                cache: 'no-store',
17938                credentials: 'same-origin'
17939              });
17940              if (!res.ok) continue;
17941              const json = await res.json();
17942              const candidate = json[sectionId];
17943              if (candidate && candidate.includes('data-bp-cart-items')) {
17944                html = candidate;
17945                break;
17946              }
17947            } catch (_) { /* try next */ }
17948          }
17949
17950          // 2. Fallback: fetch the full page HTML and extract the drawer items.
17951          //    Bigger payload but guaranteed to include the drawer markup.
17952          if (!html) {
17953            const res = await fetch(window.location.pathname, {
17954              cache: 'no-store',
17955              credentials: 'same-origin'
17956            });
17957            if (!res.ok) return;
17958            html = await res.text();
17959          }
17960
17961          const doc = new DOMParser().parseFromString(html, 'text/html');
17962          const freshList = doc.querySelector('[data-bp-cart-items]');
17963          const currentList = this.querySelector('[data-bp-cart-items]');
17964          if (freshList && currentList) {
17965            currentList.innerHTML = freshList.innerHTML;
17966            currentList.hidden = false;
17967            // The cart lines are the only place bp_style exists on the
17968            // client (/cart.js carries no metafields), and `cart:updated`
17969            // fires the moment /cart/change.js returns — well before this
17970            // section fetch lands. Anything that reads [data-bp-style]
17971            // (Complete the Look's in-bag exclusion) would otherwise be
17972            // looking at the PRE-mutation lines and miss the item just
17973            // added. Announce that the lines are actually in the DOM.
17974            document.dispatchEvent(new CustomEvent('bp:cart-lines:rendered'));
17975          }
17976        } catch (e) { console.error('[bp-cart-drawer] syncItemsList failed', e); }
17977      }
17978
17979      formatMoney(cents) {
17980        // Drop the .00 on whole-dollar prices (site-wide convention). Intl
17981        // adds the thousands separator so a JS-updated total matches the
17982        // Liquid `money | replace: '.00', ''` render (QA 7/24).
17983        return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' })
17984          .format(cents / 100).replace(/\.00$/, '');
17985      }
17986    }
17987    customElements.define('bp-cart-drawer', BpCartDrawer);
17988  }
17989</script>
17989
17990
17991  
17992
17993  <span
17994    ref="liveRegion"
17995    class="visually-hidden"
17996    role="status"
17997    data-testid="cart-count-live-region"
17998  ></span>
17999</header-actions>
18000
18001<script
18002  type="module"
18003  src="//www.bostonproper.com/cdn/shop/t/1521/assets/header-actions.js?v=121308165565653895611790713714"
18004  fetchpriority="low"
18005></script>
18005
18006
18007
18008
18009          
18010        
18011      
18012    </div>
18013        </div>
18014      </div>
18015    
18016  
18017    
18018
18019    
18020
18021    
18022    
18023  
18024
18025  
18026    <div class="header__row header__navigation-bar-row color-scheme-1">
18027      
18028
18029
18030    
18031  
18032
18033<style data-shopify>
18034  .header__underlay {
18035    --color-submenu: rgb(254 255 250 / 1.0);
18036  }
18037</style>
18038
18039
18040
18041
18042    </div>
18043  
18044</header-component>
18045
18046<script
18047  src="//www.bostonproper.com/cdn/shop/t/1521/assets/header.js?v=36718054510661947891790713714"
18048  type="module"
18049></script>
18049
18050
18051
18052
18053
18054  
18054<script type="module">
18055    import { hydrate } from '@theme/section-hydration';
18056    const url = new URL(window.location.href);
18057    url.searchParams.delete('page');
18058    hydrate('sections--29563569635494__header_section', url);
18059  </script>
18059
18060
18061
18062
18063</header>
18064<!-- END sections: header-group -->
18065    </div>
18066
18067    
18067<script>
18068      // Inline header height and menu style calculations to prevent layout shift
18069      // Note: Updates in calculateHeaderGroupHeight(), updateTransparentHeaderOffset() and setHeaderMenuStyle() utilities.js should be kept in sync with this function
18070      (function setHeaderHeighCustomProperties() {
18071        /*
18072         * Header calculation functions for maintaining CSS variables
18073         * Mimic calculateHeaderGroupHeight() in utilities.js
18074         */
18075        const header = document.querySelector('header-component');
18076        const headerGroup = document.querySelector('#header-group');
18077        const hasHeaderSection = headerGroup?.querySelector('.header-section');
18078
18079        if (!header || !headerGroup) return;
18080
18081        const headerTopRow = header.querySelector('.header__row--top');
18082        const headerHeight = header.offsetHeight;
18083
18084        // Calculate the total height of the header group
18085        let headerGroupHeight = 0;
18086        const children = headerGroup.children;
18087        for (let i = 0; i < children.length; i++) {
18088          const element = children[i];
18089          if (element === header || !(element instanceof HTMLElement)) continue;
18090          headerGroupHeight += element.offsetHeight;
18091        }
18092
18093        // Check for transparent header special case
18094        if (header.hasAttribute('transparent') && header.parentElement?.nextElementSibling) {
18095          headerGroupHeight += headerHeight;
18096        }
18097
18098        // Set CSS variables
18099        document.body.style.setProperty('--header-height', `${headerHeight}px`);
18100        document.body.style.setProperty('--header-group-height', `${headerGroupHeight}px`);
18101
18102        if (headerTopRow) {
18103          window.requestAnimationFrame(function () {
18104            document.body.style.setProperty('--top-row-height', `${headerTopRow.offsetHeight}px`);
18105          });
18106        }
18107
18108        /**
18109         * Updates CSS custom properties for transparent header offset calculation
18110         * Mimic updateTransparentHeaderOffset() in utilities.js
18111         */
18112
18113        if (!hasHeaderSection || !header?.hasAttribute('transparent')) {
18114          document.body.style.setProperty('--transparent-header-offset-boolean', '0');
18115          return;
18116        }
18117
18118        const hasImmediateSection = hasHeaderSection.nextElementSibling?.classList.contains('shopify-section');
18119
18120        const shouldApplyOffset = !hasImmediateSection ? '1' : '0';
18121        document.body.style.setProperty('--transparent-header-offset-boolean', shouldApplyOffset);
18122      })();
18123
18124      (function setHeaderMenuStyle() {
18125        const headerComponent = document.querySelector('#header-component');
18126        if (headerComponent) {
18127          const isTouchDevice = 'ontouchstart' in window && navigator.maxTouchPoints > 0;
18128          const overflowList = headerComponent?.querySelector('overflow-list');
18129          const hasReachedMinimum = overflowList && overflowList.hasAttribute('minimum-reached');
18130          headerComponent.dataset.menuStyle = isTouchDevice || hasReachedMinimum ? 'drawer' : 'menu';
18131        }
18132      })();
18133
18134      /* Boston Proper: force drawer mode below 1024px (mobile + tablet).
18135         Above 1024px we DO NOT force 'menu' — we let Horizon's overflow-list
18136         logic in setHeaderMenuStyle() (assets/utilities.js) decide. That logic
18137         flips to 'drawer' at intermediate desktop widths where menu items can't
18138         fit (e.g. the Shopify theme editor iframe at ~1500px), preventing the
18139         right-side action icons from being pushed off-screen.
18140
18141         The MutationObserver only re-asserts when we're below the breakpoint —
18142         so Horizon's debounced resize handler (header-menu.js:47-49) can switch
18143         the dataset freely on desktop, but can't undo our drawer mode on mobile. */
18144      (function bpResponsiveMenuStyle() {
18145        const headerComponent = document.querySelector('#header-component');
18146        if (!headerComponent) return;
18147        const mq = window.matchMedia('(min-width: 1024px)');
18148        const isTouchDevice = 'ontouchstart' in window && navigator.maxTouchPoints > 0;
18149        function shouldForceDrawer() {
18150          return isTouchDevice || !mq.matches;
18151        }
18152        function enforce() {
18153          if (!shouldForceDrawer()) return; // desktop: let Horizon decide
18154          if (headerComponent.dataset.menuStyle !== 'drawer') {
18155            headerComponent.dataset.menuStyle = 'drawer';
18156          }
18157        }
18158        function onChange() {
18159          enforce();
18160          if (!shouldForceDrawer()) {
18161            // Crossing up to desktop — let Horizon recompute now.
18162            window.dispatchEvent(new Event('resize'));
18163          }
18164        }
18165        if (mq.addEventListener) {
18166          mq.addEventListener('change', onChange);
18167        } else if (mq.addListener) {
18168          mq.addListener(onChange);
18169        }
18170        new MutationObserver(enforce).observe(headerComponent, {
18171          attributes: true,
18172          attributeFilter: ['data-menu-style']
18173        });
18174        enforce();
18175      })();
18176
18177      /* Boston Proper: compact-nav state machine.
18178
18179         Behavior (per design): the resting nav is IN FLOW and scrolls
18180         away with the page. Once it has fully scrolled out of view, a
18181         compact fixed bar takes over. Positioning + variant styles live
18182         in snippets/bp-fonts.liquid, keyed off data-bp-nav.
18183
18184         ── Why this is not Horizon's data-sticky-state ──────────────
18185         Horizon's #observeStickyPosition writes data-sticky-state from
18186         an IntersectionObserver on the header itself. The compact
18187         variant changes the header's height AND its position, so keying
18188         it off that flag makes the styles perturb the geometry that
18189         produces the flag: observer writes -> header resizes/unpins ->
18190         observer re-fires -> writes the opposite -> the header strobes
18191         between variants mid-scroll. Measured 2026-07-14 in Chrome: at
18192         threshold: 1, isIntersecting is false at ratio 0.9888 and true
18193         at ratio 1, so Horizon's flag flips at exactly rect.top === 0 —
18194         the one offset where a header pinned at top: -1px hands off
18195         from in-flow to pinned, and precisely where the strobe showed.
18196
18197         This machine reads window.scrollY instead. Because
18198         .header-section reserves the resting height via
18199         --bp-header-rest-h even while the child is fixed, engaging the
18200         compact bar reflows nothing, so scrollY cannot be perturbed by
18201         the state it produces. The loop is broken at the source rather
18202         than damped. The dead band below is belt-and-braces for
18203         sub-pixel scroll noise at the threshold.
18204
18205         Horizon still writes data-sticky-state; it only drives opacity
18206         and view-transition-name now (sections/header.liquid:562-577),
18207         no geometry, so the two writers can't interact. */
18208      (function bpCompactNav() {
18209        const header = document.querySelector('#header-component[sticky="always"]');
18210        if (!header) return;
18211        const section = header.closest('.header-section');
18212        if (!section) return;
18213
18214        const DEAD_BAND = 8;
18215        let restBottom = 0;
18216        let rafId = null;
18217
18218        /* The resting height is only measurable while the header is in
18219           its resting layout — when compact it is fixed and shrunken.
18220           Drop to rest, measure, restore. Runs on load + resize only,
18221           never per scroll frame, so the forced reflow is not on the
18222           hot path. */
18223        function measure() {
18224          const wasCompact = header.dataset.bpNav === 'compact';
18225          if (wasCompact) header.dataset.bpNav = 'rest';
18226
18227          const restHeight = header.offsetHeight;
18228          section.style.setProperty('--bp-header-rest-h', restHeight + 'px');
18229          /* Document-space bottom edge of the resting header. section is
18230             static and its reserved height never changes, so this is
18231             stable regardless of the current state. */
18232          restBottom = section.getBoundingClientRect().top + window.scrollY + restHeight;
18233
18234          if (wasCompact) header.dataset.bpNav = 'compact';
18235        }
18236
18237        function update() {
18238          rafId = null;
18239          const y = window.scrollY;
18240          const isCompact = header.dataset.bpNav === 'compact';
18241          if (!isCompact && y >= restBottom) {
18242            header.dataset.bpNav = 'compact';
18243          } else if (isCompact && y < restBottom - DEAD_BAND) {
18244            header.dataset.bpNav = 'rest';
18245          }
18246        }
18247
18248        function onScroll() {
18249          if (rafId !== null) return;
18250          rafId = window.requestAnimationFrame(update);
18251        }
18252
18253        function onResize() {
18254          measure();
18255          onScroll();
18256        }
18257
18258        document.addEventListener('scroll', onScroll, { passive: true });
18259        window.addEventListener('resize', onResize, { passive: true });
18260
18261        header.dataset.bpNav = 'rest';
18262        measure();
18263        update();
18264        /* Fonts/images landing after first paint change the resting
18265           height; re-measure once the page has settled. */
18266        window.addEventListener('load', onResize, { once: true });
18267      })();
18268
18269      /* Boston Proper: a11y patch for the third-party promo-bar iframe
18270         (id "PBarNextFrame*" — the free-gift/promo bar app embed, e.g.
18271         Discount Kit). The vendor injects this iframe client-side with
18272         no title/aria-label, which fails the axe "frame-title" rule.
18273         We don't control that markup, so we watch for the iframe and
18274         label it the moment it lands in the DOM (works whether it's
18275         already present, or the app mounts/remounts it later). */
18276      (function bpLabelPromoBarFrame() {
18277        const SELECTOR = 'iframe[id^="PBarNextFrame"]';
18278
18279        function label(frame) {
18280          if (!frame || frame.hasAttribute('title')) return;
18281          frame.setAttribute('title', 'Store promotion');
18282        }
18283
18284        const existing = document.querySelector(SELECTOR);
18285        if (existing) label(existing);
18286
18287        new MutationObserver(function (mutations) {
18288          for (const mutation of mutations) {
18289            for (const node of mutation.addedNodes) {
18290              if (!(node instanceof Element)) continue;
18291              if (node.matches(SELECTOR)) {
18292                label(node);
18293              } else {
18294                const frame = node.querySelector && node.querySelector(SELECTOR);
18295                if (frame) label(frame);
18296              }
18297            }
18298          }
18299        }).observe(document.documentElement, { childList: true, subtree: true });
18300      })();
18301    </script>
18301
18302
18303    <main
18304      id="MainContent"
18305      class="content-for-layout"
18306      role="main"
18307      tabindex="-1"
18308      data-page-transition-enabled="false"
18309      data-product-transition="false"
18310      data-template="product"
18311    >
18312      <div id="shopify-section-template--29563577761958__main" class="shopify-section">
18313
18314<script type="application/ld+json">
18315  {"@context":"http:\/\/schema.org\/","@id":"\/products\/boston-proper-printed-scarf-with-love-bp#product","@type":"ProductGroup","brand":{"@type":"Brand","name":"Boston Proper"},"category":"Promotions","description":"","hasVariant":[{"@id":"\/products\/boston-proper-printed-scarf-with-love-bp?variant=56389031657638#variant","@type":"Product","image":"https:\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198\u0026width=1920","name":"Boston Proper Printed Scarf With Love BP - With Love BP \/ One Size","offers":{"@id":"\/products\/boston-proper-printed-scarf-with-love-bp?variant=56389031657638#offer","@type":"Offer","availability":"http:\/\/schema.org\/InStock","price":"50.00","priceCurrency":"USD","url":"https:\/\/www.bostonproper.com\/products\/boston-proper-printed-scarf-with-love-bp?variant=56389031657638"},"sku":"2CT8071000"}],"name":"Boston Proper Printed Scarf With Love BP","productGroupID":"15286962618534","url":"https:\/\/www.bostonproper.com\/products\/boston-proper-printed-scarf-with-love-bp"}
18316</script>
18316
18317
18318
18319
18320
18321
18322
18323
18324
18325
18326
18327
18328
18329<div class="section-background color-scheme-1"></div>
18330<div
18331  class="product-information section section--page-width spacing-style color-scheme-1 relative"
18332  style="--padding-block-start: 20px;--padding-block-end: max(20px, calc(var(--spacing-scale) * 40px)); --gap: 20px;"
18333  data-testid="product-information"
18334>
18335  
18336    
18337    <a
18338  class="skip-to-content-link button-secondary"
18339  href="#ProductInformation-template--29563577761958__main"
18340>
18341  Skip to product information
18342</a>
18343
18344
18345
18346  
18347  <div
18348    class="product-information__grid product-information--media-left"
18349    data-product-grid-content
18350  >
18351    
18352    
18353
18354    
18355      
18356        
18357      <div
18358        class="product-information__media"
18359        data-testid="product-information-media"
18360      >
18361        
18362<bp-pdp-gallery
18363    class="product-slider product-slider-main-images relative"
18364    data-section-id="template--29563577761958__main"
18365    data-product-id="15286962618534"
18366    data-bp-style="2CT8071"
18367    data-bp-amplience-base="https://media.bostonproper.com"
18368    data-bp-max-items="10"
18369    data-bp-media-count="2"
18370    data-bp-image-count="2"
18371    data-bp-product-title="Boston Proper Printed Scarf With Love BP"
18372    
18373    
18374  ><nav class="bp-pdp-gallery__crumbs bp-crumbs" aria-label="Breadcrumb">
18375      <ol class="bp-crumbs__list">
18376        <li class="bp-crumbs__item">
18377          <a class="bp-crumbs__link" href="https://www.bostonproper.com/">Homepage</a>
18378          <span class="bp-crumbs__sep" aria-hidden="true">/</span>
18379        </li><li class="bp-crumbs__item bp-crumbs__item--current">
18380          <span aria-current="page">Boston Proper Printed Scarf With Love BP</span>
18381        </li>
18382      </ol>
18383    </nav>
18383<script>
18384      (function () {
18385        var el = document.querySelector('.bp-pdp-gallery__crumbs [data-bp-crumb-handle]');
18386        if (!el) return;
18387        var h = el.getAttribute('data-bp-crumb-handle');
18388        if (!h) return;
18389        function apply(n) {
18390          n = (n || '').trim();
18391          if (n && n !== el.textContent.trim()) el.textContent = n;
18392        }
18393        function readMap() {
18394          try {
18395            return JSON.parse(sessionStorage.getItem('bp_coll_names') || '{}');
18396          } catch (e) {
18397            return {};
18398          }
18399        }
18400        var map = readMap();
18401        if (map[h]) {
18402          apply(map[h]);
18403          return;
18404        }
18405        var pendKey = 'bp_coll_name_pending_' + h;
18406        if (sessionStorage.getItem(pendKey)) return;
18407        try {
18408          sessionStorage.setItem(pendKey, '1');
18409        } catch (e) {}
18410        fetch('/collections/' + encodeURIComponent(h) + '?view=crumb-title', {
18411          credentials: 'same-origin',
18412          headers: { 'X-Requested-With': 'fetch' },
18413        })
18414          .then(function (r) {
18415            return r.ok ? r.text() : '';
18416          })
18417          .then(function (t) {
18418            var n = (t || '').trim();
18419            if (!n || n.length > 120 || n.indexOf('<') !== -1) return;
18420            apply(n);
18421            var m = readMap();
18422            m[h] = n;
18423            try {
18424              sessionStorage.setItem('bp_coll_names', JSON.stringify(m));
18425            } catch (e) {}
18426          })
18427          .catch(function () {})
18428          .finally(function () {
18429            try {
18430              sessionStorage.removeItem(pendKey);
18431            } catch (e) {}
18432          });
18433      })();
18434    </script>
18434<div class="bp-pdp-gallery__stage">
18435      <div class="bp-pdp-gallery__rail" data-bp-pdp-rail><div class="bp-pdp-gallery__slide" data-index="0" data-media-type="image">
18436            <div class="product-media">
18437              <img
18438                class="bp-pdp-gallery__img product-media__image"
18439                data-bp-zoomable
18440                data-bp-zoom-index="0"
18441                data-bp-amp-primary
18442                src="https://media.bostonproper.com/s/bostonproper/2CT8071_SET/1?w=1400&fmt=auto"
18443                srcset="
18444                  https://media.bostonproper.com/s/bostonproper/2CT8071_SET/1?w=400&fmt=auto 400w,
18445                  https://media.bostonproper.com/s/bostonproper/2CT8071_SET/1?w=800&fmt=auto 800w,
18446                  https://media.bostonproper.com/s/bostonproper/2CT8071_SET/1?w=1200&fmt=auto 1200w,
18447                  https://media.bostonproper.com/s/bostonproper/2CT8071_SET/1?w=1600&fmt=auto 1600w,
18448                  https://media.bostonproper.com/s/bostonproper/2CT8071_SET/1?w=1920&fmt=auto 1920w,
18449                  https://media.bostonproper.com/s/bostonproper/2CT8071_SET/1?w=2560&fmt=auto 2560w
18450                "
18451                sizes="(min-width: 1024px) calc(50vw - 60px), 100vw"
18452                alt="Boston Proper Printed Scarf With Love BP"
18453                width="1400"
18454                height="1750"
18455                loading="eager"
18456                fetchpriority="high"
18457                onerror="if(!this.dataset.bpFellBack){this.dataset.bpFellBack='1';this.removeAttribute('srcset');this.src='//www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198&width=1400';}"
18458              >
18459            </div>
18460          </div><div
18461                class="bp-pdp-gallery__slide"
18462                data-index="1"
18463                data-media-type="image"
18464                data-bp-amp-placeholder
18465              ></div></div><div class="bp-pdp-gallery__first-cell" aria-hidden="true">
18466        <div
18467          class="bp-pdp-save-later bp-pdp-save-later--overlay"
18468          data-bp-pdp-save-later
18469          data-product-id="15286962618534"
18470        >
18471          <button
18472            type="button"
18473            class="bp-pdp-save-later__btn"
18474            data-bp-pdp-save-later-btn
18475            aria-label="Add to Wishlist"
18476            aria-pressed="false"
18477          >
18478            <svg
18479              class="bp-pdp-save-later__icon"
18480              width="20"
18481              height="20"
18482              viewBox="0 0 24 24"
18483              fill="none"
18484              stroke="currentColor"
18485              stroke-width="1.5"
18486              stroke-linecap="round"
18487              stroke-linejoin="round"
18488              aria-hidden="true"
18489            >
18490              <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/>
18491            </svg>
18492          </button>
18493        </div><button
18494            type="button"
18495            class="bp-pdp-gallery__htwi"
18496            data-bp-gallery-htwi
18497            aria-label="Scroll to How to Wear It"
18498            hidden
18499          >
18500            <span class="bp-pdp-gallery__htwi-label">How to Wear It</span></button></div>
18501    </div><template data-bp-shopify-fallback><div class="bp-pdp-gallery__slide" data-index="0" data-media-type="image">
18502            <div class="product-media"><img
18503                  class="bp-pdp-gallery__img product-media__image"
18504                  data-bp-zoomable
18505                  data-bp-zoom-index="0"
18506                  src="//www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198&width=1400"
18507                  srcset="
18508                    //www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198&width=400 400w,
18509                    //www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198&width=800 800w,
18510                    //www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198&width=1200 1200w,
18511                    //www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198&width=1600 1600w,
18512                    //www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198&width=1920 1920w,
18513                    //www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198&width=2560 2560w
18514                  "
18515                  sizes="(min-width: 1024px) calc(50vw - 60px), 100vw"
18516                  alt="Boston Proper Printed Scarf With Love BP"
18517                  width="1639"
18518                  height="2048"
18519                  loading="lazy"
18520                  fetchpriority="auto"
18521                ></div>
18522          </div><div class="bp-pdp-gallery__slide" data-index="1" data-media-type="image">
18523            <div class="product-media"><img
18524                  class="bp-pdp-gallery__img product-media__image"
18525                  data-bp-zoomable
18526                  data-bp-zoom-index="1"
18527                  src="//www.bostonproper.com/cdn/shop/files/2_af52291f-802d-4184-8815-c64ea15071dd.jpg?v=1791009198&width=1400"
18528                  srcset="
18529                    //www.bostonproper.com/cdn/shop/files/2_af52291f-802d-4184-8815-c64ea15071dd.jpg?v=1791009198&width=400 400w,
18530                    //www.bostonproper.com/cdn/shop/files/2_af52291f-802d-4184-8815-c64ea15071dd.jpg?v=1791009198&width=800 800w,
18531                    //www.bostonproper.com/cdn/shop/files/2_af52291f-802d-4184-8815-c64ea15071dd.jpg?v=1791009198&width=1200 1200w,
18532                    //www.bostonproper.com/cdn/shop/files/2_af52291f-802d-4184-8815-c64ea15071dd.jpg?v=1791009198&width=1600 1600w,
18533                    //www.bostonproper.com/cdn/shop/files/2_af52291f-802d-4184-8815-c64ea15071dd.jpg?v=1791009198&width=1920 1920w,
18534                    //www.bostonproper.com/cdn/shop/files/2_af52291f-802d-4184-8815-c64ea15071dd.jpg?v=1791009198&width=2560 2560w
18535                  "
18536                  sizes="(min-width: 1024px) calc(50vw - 60px), 100vw"
18537                  alt="Boston Proper Printed Scarf With Love BP"
18538                  width="1639"
18539                  height="2048"
18540                  loading="lazy"
18541                  fetchpriority="auto"
18542                ></div>
18543          </div></template>
18543<script type="application/json" id="bp-pdp-save-data-15286962618534">
18544      {
18545        "id": "15286962618534",
18546        "handle": "boston-proper-printed-scarf-with-love-bp",
18547        "title": "Boston Proper Printed Scarf With Love BP",
18548        "image": "\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198\u0026width=484",
18549        "variants": {"56389031657638": {
18550              "id": "56389031657638",
18551              "title": "With Love BP \/ One Size",
18552              "price": "5000",
18553              "compare_at_price": "5000",
18554              "sku": "2CT8071000","image": "\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198\u0026width=484"
18555            }}
18556      }
18557    </script>
18557<div
18558          class="bp-pdp-gallery__indicator"
18559          data-bp-pdp-indicator
18560          aria-hidden="true"
18561        ></div></bp-pdp-gallery>
18562
18563
18564
18565
18566
18567      </div>
18568    
18569      
18570    
18571      
18572        
18573  
18574<div
18575  id="ProductInformation-template--29563577761958__main"
18576  class="
18577    product-details
18578     sticky-content--desktop
18579    "
18580  style="--details-position: flex-start;"
18581  data-testid="product-information-details"
18582  
18583>
18584  
18585
18586  <div
18587  class="
18588    group-block
18589    group-block--height-fit
18590    group-block--width-fill
18591    border-style
18592    spacing-style
18593    size-style
18594    
18595    
18596  "
18597  style="
18598    --border-width: 1px; --border-style: none; --border-color:
18599rgb(var(--color-border-rgb) / 1.0); --border-radius:
186000px; 
18601
18602    --padding-block-start: max(20px, calc(var(--spacing-scale) * 36px));--padding-block-end: max(20px, calc(var(--spacing-scale) * 24px));--padding-inline-start: 0px;--padding-inline-end: 0px;
18603    --size-style-width: 100%;--size-style-height: fit;--size-style-width-mobile: 100%; --size-style-width-mobile-min: 5rem;
18604    
18605  "
18606  
18607  data-testid="group-block"
18608><div class="group-block__media-wrapper">
18609    
18610
18611
18612
18613    
18614  </div>
18615
18616  <div
18617    class="
18618      group-block-content
18619      
18620      layout-panel-flex
18621      layout-panel-flex--column
18622      
18623    "
18624    style="--flex-direction: column; --flex-wrap: nowrap; --flex-wrap-mobile: wrap;
18625
18626--gap: 8px;
18627
18628--horizontal-alignment: ; --vertical-alignment: ;
18629--vertical-alignment-mobile: ;
18630"
18631  >
18632    <div class="view-product-title">
18633      <a
18634        href="/products/boston-proper-printed-scarf-with-love-bp?variant=56389031657638"
18635        class="link"
18636      >Boston Proper Printed Scarf With Love BP
18637      </a>
18638    </div>
18639    
18640
18641
18642<div
18643  class="
18644    group-block
18645    group-block--height-fit
18646    group-block--width-fill
18647    border-style
18648    spacing-style
18649    size-style
18650    
18651    
18652  "
18653  style="
18654    --border-width: 1px; --border-style: none; --border-color:
18655rgb(var(--color-border-rgb) / 1.0); --border-radius:
186560px; 
18657
18658    --padding-block-start: 0px;--padding-block-end: 0px;--padding-inline-start: 0px;--padding-inline-end: 0px;
18659    --size-style-width: 100%;--size-style-height: fit;--size-style-width-mobile: 100%; --size-style-width-mobile-min: 5rem;
18660    
18661  "
18662  
18663  data-testid="group-block"
18664><div class="group-block__media-wrapper">
18665    
18666
18667
18668
18669    
18670  </div>
18671
18672  <div
18673    class="
18674      group-block-content
18675      
18676      layout-panel-flex
18677      layout-panel-flex--column
18678       mobile-column
18679    "
18680    style="--flex-direction: column; --flex-wrap: nowrap; --flex-wrap-mobile: wrap;
18681
18682--gap: 8px;
18683
18684--horizontal-alignment: flex-start; --vertical-alignment: center;
18685--vertical-alignment-mobile: center;
18686"
18687  >
18688  <a class="bp-collection-eyebrow bp-collection-eyebrow--link" href="/collections/charmeuse" >Charmeuse</a>
18689
18690
18691<div
18692    class="bp-yotpo-stars yotpo-widget-instance"
18693    data-yotpo-instance-id="659034"
18694    data-yotpo-product-id="15286962618534"
18695    data-yotpo-cart-product-id="15286962618534"
18696    data-yotpo-section-id="product-rating"
18697    data-bp-product-url="/products/boston-proper-printed-scarf-with-love-bp"
18698    
18699  ></div>
18700
18701
18702
18703
18704
18705
18706
18707
18708
18709
18710
18711  <div class=" spacing-style text-block text-block--AMHlxeTlWeC9RNHpmZ__text_xrnftG h3    text-block--align-left  "  style="    --padding-block-start: 0px; --padding-block-end:0px; --padding-inline-start:0px; --padding-inline-end:0px;         --width: 100%;    --max-width: var(--max-width--body-normal);          --text-align: left;          ">
18712    <h1>Boston Proper Printed Scarf With Love BP</h1>
18713  </div>
18714
18715
18716
18717
18718
18719
18720
18721
18722
18723<product-price
18724  class="text-block text-block--align-left rte text-left paragraph spacing-style"
18725  data-block-id="AU3BiYjdBRFBJMG1WV__price_tVjtKg"
18726  data-product-id="15286962618534"
18727  style="
18728    
18729--color: var(--color-foreground);
18730    --padding-block-start: 4px;--padding-block-end: 0px;--padding-inline-start: 0px;--padding-inline-end: 0px;
18731    --width: 100%;
18732  "
18733  
18734>
18735  <div ref="priceContainer">
18736  
18737    
18738    <div
18739      class="
18740        price__regular
18741        
18742      "
18743    >
18744      <span class="price">$50</span>
18745    </div>
18746    <div
18747      class="
18748        price__sale
18749        
18750          price__hidden
18751        
18752      "
18753    >
18754      
18755        <span class="price-item__group">
18756          <span class="visually-hidden">Sale price&nbsp;</span>
18757          <span class="price-item--sale price">$50</span>
18758        </span>
18759        <span class="price-item__group">
18760          <span class="visually-hidden">Regular price&nbsp;</span>
18761          <span class="price-item--regular compare-at-price">$50</span>
18762        </span>
18763      
18764    </div>
18765  
18766</div>
18767
18768  
18769</product-price>
18770
18771
18772<span class="bp-promo-line" data-bp-promo-line >Free gift with purchase of $400+</span>
18773
18774
18775
18776
18777<ul class="bp-pills bp-pills--empty" data-bp-pills data-block-id="AWmVZMFVpYWlCSzg4M__bp_tag_pills" ></ul>
18777<script>
18778    (function () {
18779      var list = document.querySelector('[data-bp-pills][data-block-id="AWmVZMFVpYWlCSzg4M__bp_tag_pills"]');
18780      if (!list) return;
18781      var pid = 15286962618534;
18782      // Defer the badge membership fetch (pathways.dxpapi.com, reached via
18783      // applyToPdpPills → fetchPids) to idle so it doesn't compete with the
18784      // LCP on the PDP. The pill is a minor "Popular / Trending" affordance —
18785      // fine to pop in shortly after paint. Mirrors bp-badges.js's card scan.
18786      var run = function () {
18787        var tries = 30;
18788        (function tick() {
18789          if (window.BpBadges) { window.BpBadges.applyToPdpPills(list, pid); return; }
18790          if (tries-- <= 0) return;
18791          setTimeout(tick, 100);
18792        })();
18793      };
18794      if ('requestIdleCallback' in window) {
18795        requestIdleCallback(run, { timeout: 2000 });
18796      } else {
18797        setTimeout(run, 1200);
18798      }
18799    })();
18800  </script>
18800
18801
18802
18803
18804</div>
18805</div>
18806
18807
18808
18809
18810
18811
18812
18813<div
18814  class="divider divider-AcUdqV0pEbE5HVHh2N__divider_VJhene spacing-style"
18815  style="
18816    --divider-justify-content: center;
18817    --padding-block-start: 0px;--padding-block-end: 0px;
18818  "
18819  
18820
18821>
18822  <span
18823    class="divider__line"
18824    style="
18825      --divider-border-thickness: 1px;
18826      
18827        --divider-border-rounded: 0;
18828      
18829      --divider-flex-basis: 100%;
18830    "
18831  ></span>
18832</div>
18833
18834
18835
18836
18837
18838<div
18839    class="bp-colors"
18840    data-bp-colors
18841    data-bp-inv5-handle="boston-proper-printed-scarf"
18842    data-bp-current-handle="boston-proper-printed-scarf-with-love-bp"
18843    data-bp-group-tag="YGroup_2CT80"
18844    
18845  >
18846    <p class="bp-colors__label">
18847      <span class="bp-colors__label-prefix">Color</span>
18848      <span class="bp-colors__label-name" data-bp-active-color>With Love Bp</span>
18849    </p>
18850    <ul class="bp-colors__swatches" role="list"><li
18851          class="bp-colors__item bp-colors__item--pending"
18852          data-bp-color-name="Americana Bandana"
18853          data-bp-color-handle="boston-proper-printed-scarf-americana-bandana"
18854          data-bp-color-style="2CT8031"
18855        ><a
18856              class="bp-colors__swatch"href="/products/boston-proper-printed-scarf-americana-bandana"
18857              data-bp-swatch
18858              aria-label="Americana Bandana"style="background-image: url('https://media.bostonproper.com/i/bostonproper/2CT8031_2?$poiswatch$&img404=2CT8031_1');"></a><span class="bp-colors__discount" data-bp-color-discount aria-label="60% off">-60%</span></li><li
18859          class="bp-colors__item bp-colors__item--pending"
18860          data-bp-color-name="Florence Fleur"
18861          data-bp-color-handle="boston-proper-printed-scarf-florence-fleur"
18862          data-bp-color-style="2CT8091"
18863        ><a
18864              class="bp-colors__swatch"href="/products/boston-proper-printed-scarf-florence-fleur"
18865              data-bp-swatch
18866              aria-label="Florence Fleur"style="background-image: url('https://media.bostonproper.com/i/bostonproper/2CT8091_2?$poiswatch$&img404=2CT8091_1');"></a></li><li
18867          class="bp-colors__item bp-colors__item--pending"
18868          data-bp-color-name="Flowers Of Hope"
18869          data-bp-color-handle="boston-proper-printed-scarf-flowers-of-hope"
18870          data-bp-color-style="2CT8070"
18871        ><a
18872              class="bp-colors__swatch"href="/products/boston-proper-printed-scarf-flowers-of-hope"
18873              data-bp-swatch
18874              aria-label="Flowers Of Hope"style="background-image: url('https://media.bostonproper.com/i/bostonproper/2CT8070_2?$poiswatch$&img404=2CT8070_1');"></a></li><li
18875          class="bp-colors__item bp-colors__item--pending"
18876          data-bp-color-name="Iris Garden"
18877          data-bp-color-handle="boston-proper-printed-scarf-iris-garden"
18878          data-bp-color-style="2CT8090"
18879        ><a
18880              class="bp-colors__swatch"href="/products/boston-proper-printed-scarf-iris-garden"
18881              data-bp-swatch
18882              aria-label="Iris Garden"style="background-image: url('https://media.bostonproper.com/i/bostonproper/2CT8090_2?$poiswatch$&img404=2CT8090_1');"></a></li><li
18883          class="bp-colors__item bp-colors__item--pending"
18884          data-bp-color-name="Party Polka"
18885          data-bp-color-handle="boston-proper-printed-scarf-party-polka"
18886          data-bp-color-style="2CT8020"
18887        ><a
18888              class="bp-colors__swatch"href="/products/boston-proper-printed-scarf-party-polka"
18889              data-bp-swatch
18890              aria-label="Party Polka"style="background-image: url('https://media.bostonproper.com/i/bostonproper/2CT8020_2?$poiswatch$&img404=2CT8020_1');"></a></li><li
18891          class="bp-colors__item bp-colors__item--pending"
18892          data-bp-color-name="Stunning Sealife"
18893          data-bp-color-handle="boston-proper-printed-scarf-stunning-sealife"
18894          data-bp-color-style="2CT8030"
18895        ><a
18896              class="bp-colors__swatch"href="/products/boston-proper-printed-scarf-stunning-sealife"
18897              data-bp-swatch
18898              aria-label="Stunning Sealife"style="background-image: url('https://media.bostonproper.com/i/bostonproper/2CT8030_2?$poiswatch$&img404=2CT8030_1');"></a></li><li
18899          class="bp-colors__item is-active"
18900          data-bp-color-name="With Love Bp"
18901          data-bp-color-handle="boston-proper-printed-scarf-with-love-bp"
18902          data-bp-color-style="2CT8071"
18903        ><span
18904              class="bp-colors__swatch"
18905              data-bp-swatch
18906              aria-current="true"style="background-image: url('https://media.bostonproper.com/i/bostonproper/2CT8071_2?$poiswatch$&img404=2CT8071_1');"></span>
18907            <span class="bp-colors__sr">With Love Bp (current)</span></li></ul>
18908  </div>
18909
18910  
18910<script>
18911    /* Canonical colour-family hydration is shared with the quick-add / quick-view
18912       drawer — see window.bpColorSiblings.hydrateRoot in snippets/bp-shop-globals.
18913       The union-crawl + canonical bp_style ordering used to live inline here; it
18914       now lives once in the shared helper so the PDP and the drawer render the
18915       identical drift-free swatch set + order (the drawer can't run this inline
18916       script tag — Horizon's morph doesn't execute theme-block inline scripts). */
18917    (function () {
18918      var root = document.querySelector('[data-bp-colors][data-bp-inv5-handle="boston-proper-printed-scarf"]');
18919      if (!root) return;
18920      var QV = '';
18921      if (window.bpColorSiblings && window.bpColorSiblings.hydrateRoot) {
18922        window.bpColorSiblings.hydrateRoot(root, { qv: QV });
18923      } else {
18924        // bpColorSiblings is rendered globally before this block, so this path is
18925        // defensive only: at minimum reveal the active swatch so the row isn't blank.
18926        var active = root.querySelector('.bp-colors__item.is-active');
18927        if (active) active.classList.remove('bp-colors__item--pending');
18928      }
18929    })();
18930  </script>
18930
18931
18932
18933
18934
18935
18936  
18937
18938
18939  
18940  <variant-picker
18941    class="variant-picker spacing-style variant-picker--left"
18942    style="--color-strikethrough-mix: #000; --padding-block-start: 0px;--padding-block-end: 0px;--padding-inline-start: 0px;--padding-inline-end: 0px;"
18943    data-section-id="template--29563577761958__main"
18944    data-product-id="15286962618534"
18945    data-block-id="ARHVvWmlKWlNHRFpid__variant_picker_R3rGDr"
18946    data-product-url="/products/boston-proper-printed-scarf-with-love-bp"
18947    ref="mainVariantPicker"
18948    
18949      data-template-product-match="true"
18950    
18951    
18952    
18953  >
18954    <form class="variant-picker__form"><div
18955            class="variant-option"
18956            data-testid="variant-option-single"
18957          >Color<span
18958              class="variant-option__swatch-value"
18959              data-testid="variant-option-single-value"
18960            >With Love BP</span>
18961          </div><div
18962            class="variant-option"
18963            data-testid="variant-option-single"
18964          >Size<span
18965              class="variant-option__swatch-value"
18966              data-testid="variant-option-single-value"
18967            >One Size</span>
18968          </div>
18968<script type="application/json">
18969        {"id":56389031657638,"title":"With Love BP \/ One Size","option1":"With Love BP","option2":"One Size","option3":null,"sku":"2CT8071000","requires_shipping":true,"taxable":true,"featured_image":{"id":80304586948774,"product_id":15286962618534,"position":1,"created_at":"2026-10-03T02:33:16-04:00","updated_at":"2026-10-03T02:33:18-04:00","alt":null,"width":1639,"height":2048,"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198","variant_ids":[56389031657638]},"available":true,"name":"Boston Proper Printed Scarf With Love BP - With Love BP \/ One Size","public_title":"With Love BP \/ One Size","options":["With Love BP","One Size"],"price":5000,"weight":0,"compare_at_price":5000,"inventory_management":"shopify","barcode":null,"featured_media":{"alt":null,"id":70645919449254,"position":1,"preview_image":{"aspect_ratio":0.8,"height":2048,"width":1639,"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198"}},"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}
18970      </script>
18970
18971    </form>
18972  </variant-picker>
18973
18974
18975
18976
18977
18978
18979
18980<div class="bp-size-chart-link"  data-bp-size-chart-resolved="true">
18981  <button
18982    type="button"
18983    class="bp-size-chart-link__btn"
18984    data-bp-size-chart-open
18985    aria-controls="bp-size-chart-drawer"
18986    aria-haspopup="dialog"
18987  ><span>Size Chart</span>
18988  </button></div>
18989
18990
18991<div
18992    data-bp-fma-mount
18993    
18994  ><div
18995      class="tfc-fitrec-product"
18996      data-styleid="15286962618534"
18997      data-locale="en_US"
18998      data-userid=""
18999    ></div>
19000  </div>
19001
19002  
19002<script>
19003    (function () {
19004      // Re-run TrueFit's calculate when this block paints so the
19005      // tfc-fitrec-product mount picks up the latest variant. Same
19006      // pattern as Atlas's useEffect in ProductMainForm.
19007      const calc = () => {
19008        if (typeof window.tfcapi === 'function') {
19009          try { window.tfcapi('calculate'); } catch (_) {}
19010        }
19011      };
19012      calc();
19013      document.addEventListener('variant:update', calc);
19014      document.addEventListener('variant:change', calc);
19015    })();
19016  </script>
19016
19017
19018
19019
19020<div
19021    class="bp-notify-trigger"
19022    data-bp-notify-trigger
19023    data-section-product="15286962618534"
19024    data-bp-current-variant="56389031657638"
19025    data-bp-current-available="true"
19026    style="display: none;"
19027    
19028  >
19029    <button
19030      type="button"
19031      class="bp-notify-trigger__btn"
19032      data-bp-notify-open
19033      data-bp-notify-variant-id="56389031657638"
19034    ><span>Notify Me When Available</span>
19035    </button>
19036  </div>
19036<script type="application/json" id="bp-notify-variants-15286962618534">
19037    {"56389031657638": {
19038          "available": true,
19039          "fullPrice": true,
19040          "gates": {
19041  "isPreOrder": true,
19042  "dcDate": null,
19043  "currentInv": 2617,
19044  "inboundInv": 0
19045}
19046
19047        }
19048}
19049  </script>
19049
19050
19051  
19051<script>
19052    (function () {
19053      const trigger = document.querySelector('[data-bp-notify-trigger][data-section-product="15286962618534"]');
19054      if (!trigger) return;
19055      const table = JSON.parse(document.getElementById('bp-notify-variants-15286962618534').textContent || '{}');
19056      // Track which variant is "current" so the trigger opens the drawer
19057      // for the right SKU even if the user hasn't clicked yet.
19058      let currentVariantId = parseInt(trigger.dataset.bpCurrentVariant, 10) || null;
19059      window.bpCurrentVariantId = currentVariantId;
19060
19061      const setVisible = (vid) => {
19062        // Re-query the trigger fresh each time: Horizon re-renders (morphs) the
19063        // buy box on variant:update, which can REPLACE the notify trigger — the
19064        // once-captured reference then points at a detached node, so toggling
19065        // it did nothing. Switching between two sold-out sizes hid the ATC
19066        // (Notify swap) but "showed" a detached trigger → the CTA vanished
19067        // entirely (QA 7/21). A fresh lookup targets the live element.
19068        const trigger = document.querySelector('[data-bp-notify-trigger][data-section-product="15286962618534"]');
19069        if (!trigger) return;
19070        const entry = table[String(vid)] || {};
19071        const available = entry.available !== false;
19072        const gates = entry.gates || {};
19073        const currentInv = Number(gates.currentInv) || 0;
19074        const inboundInv = Number(gates.inboundInv) || 0;
19075        // Restock-eligible: see block doc comment (Atlas parity —
19076        // ProductMainForm.js's showVariantLevelNotifyMe). Only sold-out
19077        // variants that are full price, have no on-hand stock, and have
19078        // no inbound restock already scheduled get the Notify Me swap.
19079        const restockEligible = !available && !!entry.fullPrice && currentInv <= 0 && inboundInv <= 0;
19080        // Toggle Notify trigger
19081        trigger.style.display = restockEligible ? '' : 'none';
19082        // Hide Horizon's ATC + accelerated checkout ONLY when the Notify Me
19083        // trigger is actually visible in its place. A sold-out-but-ineligible
19084        // variant keeps Horizon's own disabled "Sold out" button
19085        // (blocks/buy-buttons.liquid). And if the trigger can't render for any
19086        // reason (mid-morph / detached / hidden section), `offsetParent` is
19087        // null — keep the disabled out-of-stock button so the buy box is NEVER
19088        // left empty (Ernie 7/21: switching to a crossed-out size dropped the
19089        // CTA; a disabled out-of-stock button should show in that case).
19090        // Reading offsetParent forces the reflow so it reflects the display we
19091        // just set. We scope to the same product-information section so other
19092        // PDPs / quick-view modals aren't affected.
19093        const section = trigger.closest('[data-section-id]') || document;
19094        const notifyShown = restockEligible && trigger.offsetParent !== null;
19095        section.querySelectorAll(
19096          '.buy-buttons,' +
19097          'button[name="add"],' +
19098          'add-to-cart-component,' +
19099          'accelerated-checkout-component,' +
19100          '[data-shop-pay-button]'
19101        ).forEach((el) => {
19102          el.style.display = notifyShown ? 'none' : '';
19103        });
19104        // Keep the open trigger's variantId attribute current.
19105        const btn = trigger.querySelector('[data-bp-notify-open]');
19106        if (btn) btn.setAttribute('data-bp-notify-variant-id', String(vid));
19107        window.bpCurrentVariantId = vid;
19108      };
19109
19110      // Initial render — DEFERRED. This block is parsed BEFORE the
19111      // buy-buttons block (its block_order precedes buy_buttons in
19112      // templates/product.json), and this inline script runs synchronously
19113      // during parse. Running setVisible now means the section's
19114      // querySelectorAll for button[name="add"] / add-to-cart-component
19115      // finds NOTHING (not parsed yet), so on an initial out-of-stock load
19116      // the Sold Out button is never hidden and BOTH it and Notify Me show
19117      // (QA 7/22). Wait until the DOM is parsed so the buy box exists.
19118      const initialRender = () => {
19119        setVisible(currentVariantId);
19120        requestAnimationFrame(() => setVisible(currentVariantId));
19121      };
19122      if (document.readyState === 'loading') {
19123        document.addEventListener('DOMContentLoaded', initialRender, { once: true });
19124      } else {
19125        initialRender();
19126      }
19127
19128      // Horizon dispatches `variant:update` (see assets/events.js
19129      // → ThemeEvents.variantUpdate = 'variant:update'). Also keep the
19130      // older `variant:change` / `variantchange` listeners for
19131      // forward-compat with theme apps that still dispatch those.
19132      const onChange = (e) => {
19133        const vid =
19134          e?.detail?.resource?.id ||
19135          e?.detail?.variant?.id ||
19136          e?.detail?.id;
19137        if (!vid) return;
19138        // Run twice: once now, and once after Horizon finishes morphing the
19139        // buy box. `variant:update` can fire BEFORE the add-to-cart / buy-
19140        // buttons re-render, so a synchronous-only pass hid the ATC on the
19141        // pre-morph DOM and the freshly morphed "Sold out" button came back
19142        // visible OR was left in a half-applied state — switching from an
19143        // in-stock size to a crossed-out one dropped the CTA entirely
19144        // (Medium, Ernie 7/21). The rAF pass re-asserts on the FINAL DOM.
19145        setVisible(vid);
19146        requestAnimationFrame(() => setVisible(vid));
19147      };
19148      document.addEventListener('variant:update', onChange);
19149      document.addEventListener('variant:change', onChange);
19150      document.addEventListener('variantchange', onChange);
19151
19152      // Fallback observer — two jobs:
19153      //  1. Catch variant changes that don't come through an event.
19154      //  2. Re-assert after Horizon MORPHS the buy box. variant:update
19155      //     triggers an ASYNC section re-render; the sync + rAF passes in
19156      //     onChange run BEFORE that morph lands, so a freshly re-rendered
19157      //     (default-visible) ATC/Sold-out button can override the Notify
19158      //     swap, OR — when switching to a crossed-out size — the buy box is
19159      //     briefly re-rendered and our stale display state leaves it empty
19160      //     (QA 7/22, lemon-drop). Re-running setVisible on the post-morph
19161      //     DOM guarantees exactly one of {ATC/Sold-out, Notify} is shown and
19162      //     the buy box is never left blank.
19163      const sectionRoot = trigger.closest('[data-section-id]');
19164      if (sectionRoot) {
19165        let rafPending = false;
19166        const obs = new MutationObserver((mutations) => {
19167          const input = sectionRoot.querySelector('input[name="id"]');
19168          const vid = input ? parseInt(input.value, 10) : null;
19169          if (vid && vid !== window.bpCurrentVariantId) { setVisible(vid); return; }
19170          // Only react to NODE morphs (childList), not our own display
19171          // (attribute) writes — otherwise setVisible would loop. Coalesce
19172          // via rAF so a burst of morph mutations re-asserts once.
19173          const morphed = mutations.some((m) =>
19174            m.type === 'childList' && (m.addedNodes.length || m.removedNodes.length));
19175          if (!morphed || rafPending) return;
19176          rafPending = true;
19177          requestAnimationFrame(() => {
19178            rafPending = false;
19179            if (window.bpCurrentVariantId) setVisible(window.bpCurrentVariantId);
19180          });
19181        });
19182        obs.observe(sectionRoot, { attributes: true, childList: true, subtree: true });
19183      }
19184    })();
19185  </script>
19185
19186
19187
19188
19189
19190
19191<span
19192  class="buy-buttons-block buy-buttons-block--AU01KdzgrSDJ3K2Zxa__buy_buttons_eYQEYi"
19193  
19194><product-form-component
19195      data-section-id="template--29563577761958__main"
19196      data-product-id="15286962618534"
19197      data-product-url="/products/boston-proper-printed-scarf-with-love-bp"
19198      on:submit="/handleSubmit"
19199      data-quantity-default="1"
19200      data-quantity-error-max="This item has a maximum of {{ maximum }}"
19201    >
19202      <div
19203        class="visually-hidden"
19204        aria-live="assertive"
19205        role="status"
19206        aria-atomic="true"
19207        ref="liveRegion"
19208      ></div><form method="post" action="/cart/add" id="BuyButtons-ProductForm-template--29563577761958__main" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" data-type="add-to-cart-form"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /><input
19209          type="hidden"
19210          name="id"
19211          ref="variantId"
19212          value="56389031657638"
19213        ><div
19214          class="product-form-buttons spacing-style product-form-buttons--stacked"
19215          style="--padding-block-start: 0px;--padding-block-end: 0px;--padding-inline-start: 0px;--padding-inline-end: 0px;"
19216          ref="productFormButtons"
19217        ><span
19218              class="product-form-text__error hidden"
19219              ref="addToCartTextError"
19220            >
19221              <span class="svg-wrapper"><svg aria-hidden="true" class="icon icon-error" viewBox="0 0 13 13">
19222  <circle cx="6.5" cy="6.5" r="5.5" stroke="#fff" stroke-width="var(--icon-stroke-width)"/>
19223  <circle cx="6.5" cy="6.5" r="5.5" fill="#EB001B" stroke="#EB001B" stroke-width=".7"/>
19224  <path fill="#fff" d="m5.874 3.528.1 4.044h1.053l.1-4.044zm.627 6.133c.38 0 .68-.288.68-.656s-.3-.656-.68-.656-.681.288-.681.656.3.656.68.656"/>
19225  <path fill="#fff" stroke="#EB001B" stroke-width=".7" d="M5.874 3.178h-.359l.01.359.1 4.044.008.341h1.736l.008-.341.1-4.044.01-.359H5.873Zm.627 6.833c.56 0 1.03-.432 1.03-1.006s-.47-1.006-1.03-1.006-1.031.432-1.031 1.006.47 1.006 1.03 1.006Z"/>
19226</svg>
19227</span>
19228            </span>
19229
19230
19231
19232<div
19233  class="quantity-selector-wrapper"
19234  ref="quantitySelectorWrapper"
19235>
19236  <quantity-selector-component
19237    class="quantity-selector"
19238    data-variant-id="56389031657638"
19239    
19240ref="quantitySelector"
19241    
19242  >
19243    <button
19244      class="button quantity-minus button-unstyled"
19245      type="button"
19246      name="minus"
19247      on:click="/decreaseQuantity"
19248      ref="minusButton"
19249      
19250    >
19251      <span class="visually-hidden">Decrease quantity</span
19252      ><span class="svg-wrapper icon-plus"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
19253  <path d="M2.75 7H11.25" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round"/>
19254</svg>
19255</span>
19256    </button>
19257    <input
19258      type="number"
19259      name="quantity"
19260      value="1"
19261      data-cart-quantity="0"
19262      min="1"
19263      data-min="1"
19264      on:blur="/setQuantity"
19265      on:focus="/selectInputValue"
19266      ref="quantityInput"
19267      aria-live="polite"
19268      aria-label="Quantity"
19269      
19270      
19271      step="1"
19272      
19273    >
19274    <button
19275      class="button quantity-plus button-unstyled"
19276      type="button"
19277      name="plus"
19278      on:click="/increaseQuantity"
19279      ref="plusButton"
19280      
19281    >
19282      <span class="visually-hidden">Increase quantity</span
19283      ><span class="svg-wrapper icon-plus"><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
19284  <path class="vertical" d="M2.75 7H11.25" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round"/>
19285  <path class="horizontal" d="M7 2.75L7 11.25" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round"/>
19286</svg>
19287</span>
19288    </button>
19289  </quantity-selector-component></div>
19290
19291
19292
19293
19294
19295
19296
19297
19298
19299<span
19300  
19301  style="--add-to-cart-font-case: ;"
19302>
19303  <add-to-cart-component
19304  ref="addToCartButtonContainer"
19305  data-product-variant-media="//www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198&width=100"
19306  data-add-to-cart-animation="true"
19307>
19308  <button
19309    
19310      id="BuyButtons-ProductSubmitButton-AeE9EOHozN01sMFF3b__add-to-cart"
19311    
19312    type="submit"
19313    name="add"
19314    ref="addToCartButton"
19315    on:click="/handleClick"
19316    class="button add-to-cart-button button"
19317    
19318      data-testid="standalone-add-to-cart"
19319    
19320    
19321  >
19322    <span
19323      class="add-to-cart-text"
19324    >
19325      
19326        <span
19327          aria-hidden="true"
19328          class="svg-wrapper add-to-cart-icon"
19329        ><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="var(--icon-stroke-width)" d="M16.608 9.421V6.906H3.392v8.016c0 .567.224 1.112.624 1.513.4.402.941.627 1.506.627H8.63M8.818 3h2.333c.618 0 1.212.247 1.649.686a2.35 2.35 0 0 1 .683 1.658v1.562H6.486V5.344c0-.622.246-1.218.683-1.658A2.33 2.33 0 0 1 8.82 3"/><path stroke="currentColor" stroke-linecap="round" stroke-width="var(--icon-stroke-width)" d="M14.608 12.563v5m2.5-2.5h-5"/></svg>
19330</span>
19331      
19332      <span class="add-to-cart-text__content">
19333        <span>
19334          <span>Add to bag</span>
19335        </span>
19336      </span>
19337    </span>
19338    
19339    <span class="add-to-cart__added">
19340      <span class="svg-wrapper add-to-cart__added-icon"><svg aria-hidden="true" class="checkmark-burst" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
19341  <g class="check">
19342    <circle class="ring" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
19343    <path class="tick" d="M9 12.75L11.25 15L15 9.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
19344  </g>
19345  <g class="burst">
19346    <g style="--index: 0;">
19347      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
19348    </g>
19349    <g style="--index: 1;">
19350      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
19351    </g>
19352    <g style="--index: 2;">
19353      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
19354    </g>
19355    <g style="--index: 3;">
19356      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
19357    </g>
19358    <g style="--index: 4;">
19359      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
19360    </g>
19361    <g style="--index: 5;">
19362      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
19363    </g>
19364    <g style="--index: 6;">
19365      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
19366    </g>
19367    <g style="--index: 7;">
19368      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
19369    </g>
19370  </g>
19371</svg>
19372</span>
19373    </span>
19374  </button>
19375</add-to-cart-component>
19376
19377</span>
19378
19379
19380
19381
19382          
19383
19384
19385
19386
19387
19388  <div
19389    class="accelerated-checkout-block"
19390    ref="acceleratedCheckoutButtonContainer"
19391    
19392    
19393    
19394  >
19395    
19396  
19397    <div data-shopify="payment-button" class="shopify-payment-button"> <shopify-accelerated-checkout recommended="{&quot;supports_subs&quot;:true,&quot;supports_def_opts&quot;:false,&quot;name&quot;:&quot;shop_pay&quot;,&quot;wallet_params&quot;:{&quot;shopId&quot;:52960723110,&quot;merchantName&quot;:&quot;Boston Proper&quot;,&quot;personalized&quot;:true}}" fallback="{&quot;supports_subs&quot;:true,&quot;supports_def_opts&quot;:true,&quot;name&quot;:&quot;buy_it_now&quot;,&quot;wallet_params&quot;:{}}" access-token="eb9ee10d84a005c2b8e778780263a9d2" buyer-country="US" buyer-locale="en" buyer-currency="USD" variant-params="[{&quot;id&quot;:56389031657638,&quot;requiresShipping&quot;:true}]" shop-id="52960723110" enabled-flags="[&quot;1172c16a&quot;,&quot;a1d1f9a1&quot;,&quot;f5afabb3&quot;,&quot;370070f3&quot;]" > <div class="shopify-payment-button__button" role="button" disabled aria-hidden="true" style="background-color: transparent; border: none"> <div class="shopify-payment-button__skeleton">&nbsp;</div> </div> <div class="shopify-payment-button__more-options shopify-payment-button__skeleton" role="button" disabled aria-hidden="true">&nbsp;</div> </shopify-accelerated-checkout> </div>
19398  
19399
19400  </div>
19401
19402
19403
19404
19405
19406
19407
19408        </div><input type="hidden" name="product-id" value="15286962618534" /><input type="hidden" name="section-id" value="template--29563577761958__main" /></form></product-form-component></span>
19409
19410
19411
19412
19413
19414
19415
19416<bp-require-size ></bp-require-size>
19417
19418
19419
19420
19421
19422
19423<bp-line-item-props data-initial-vid="56389031657638">
19424  
19424<script type="application/json" class="bp-lip-data">
19425    {
19426  "static": {
19427    "_final_sale": "no"
19428  },
19429  "variants": {"56389031657638": {
19430        "_catalog_id": "799",
19431        "_price_status": "Full Price",
19432        "compare_at_price": 50.0,
19433        "price": "$50.00"
19434      }
19435}
19436}
19437
19438  </script>
19438
19439  </bp-line-item-props>
19440<p class="bp-pay-in-4" >
19441  Pay in full or in 4 interest-free installments with
19442  <img class="bp-pay-in-4__shop-pay-mark" src="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-shop-pay-logo.svg?v=68994295948588378181790713714" alt="Shop Pay" width="42" height="10" loading="lazy" style="width:auto;height:12px;">
19443</p>
19444
19445
19446
19447
19448<p
19449    class="bp-preorder-line"
19450    data-bp-preorder-line
19451    data-section-product="15286962618534"
19452    hidden
19453  >
19454    <span class="bp-preorder-line__label">Expected to ship:</span>
19455    <span class="bp-preorder-line__date" data-bp-preorder-date></span>
19456  </p>
19457
19458  
19458<script type="application/json" id="bp-preorder-variants-15286962618534">
19459    {
19460      "_originalOverride": null,
19461      "variants": {"56389031657638": {
19462  "isPreOrder": true,
19463  "dcDate": null,
19464  "currentInv": 2617,
19465  "inboundInv": 0
19466}
19467
19468}
19469    }
19470  </script>
19470
19471
19472  
19472<script>
19473    (function () {
19474      const line = document.querySelector('[data-bp-preorder-line][data-section-product="15286962618534"]');
19475      if (!line) return;
19476      const data = JSON.parse(document.getElementById('bp-preorder-variants-15286962618534').textContent || '{}');
19477      const variants = data.variants || {};
19478      const originalOverride = data._originalOverride || '';
19479      const dateEl = line.querySelector('[data-bp-preorder-date]');
19480      // Atlas hardcodes shippingInventoryThreshold = 1 in
19481      // updateLineItemProperties.js:31. Same here — schema knob is
19482      // ignored to keep the gate deterministic across environments.
19483      const THRESHOLD = 1;
19484
19485      // Auto-enable debug when the URL carries ?bp-preorder-debug=1 so
19486      // merchants can share a link that produces console output without
19487      // asking them to flip a global in DevTools.
19488      try {
19489        if (new URLSearchParams(location.search).get('bp-preorder-debug') === '1') {
19490          window.bpPreorderDebug = true;
19491        }
19492      } catch (_) {}
19493      // Always park the init snapshot on `window.bpPreorderInit` (a
19494      // per-product map so multiple product blocks don't clobber each
19495      // other) so it's inspectable from DevTools even without the
19496      // debug flag: just type `bpPreorderInit` in console.
19497      window.bpPreorderInit = window.bpPreorderInit || {};
19498      window.bpPreorderInit[15286962618534] = {
19499        productId: 15286962618534,
19500        threshold: THRESHOLD,
19501        originalOverride,
19502        variants
19503      };
19504      if (window.bpPreorderDebug) {
19505        console.log('[bp-preorder] init', window.bpPreorderInit[15286962618534]);
19506      }
19507
19508      // Mirror the displayed date into a hidden line-item property on the
19509      // product add-to-cart form so the cart line can render it (the cart
19510      // reads it LIP-only — no metafield fallback). Underscore-prefixed
19511      // `_expected_ship_date` matches Atlas (updateLineItemProperties.js)
19512      // and the Save-for-Later path; it stays hidden from Shopify's native
19513      // UI while BP renders it manually. Disabled when no pre-order date so
19514      // FormData omits it entirely (Atlas clears it to "" for the same reason).
19515      const LIP_NAME = 'properties[_expected_ship_date]';
19516      // BP: was `line.closest('[data-section-id]')`, which never
19517      // matched anything — that attribute only exists on
19518      // <product-form-component> (blocks/buy-buttons.liquid), and this
19519      // block is buy-buttons' SIBLING, not its descendant, so the
19520      // closest() walk up from `line` never reached it. sectionRoot was
19521      // silently always null, ensureLip() always returned null, and the
19522      // hidden LIP input was never created — the date showed on the PDP
19523      // (that doesn't depend on sectionRoot) but never reached the cart.
19524      // #ProductInformation-template--29563577761958__main (blocks/_product-details.liquid)
19525      // is the actual shared ancestor of every block on the product,
19526      // including buy-buttons, so anchor there instead.
19527      const sectionRoot = line.closest('.product-details');
19528      let lipInput = null;
19529      // Lazily resolve the add-to-cart form + hidden input. The form may
19530      // parse after this block (block order isn't guaranteed), so resolve
19531      // on demand rather than once up front.
19532      const ensureLip = () => {
19533        if (lipInput && lipInput.isConnected) return lipInput;
19534        const form = sectionRoot && sectionRoot.querySelector('form[action$="/cart/add"]');
19535        if (!form) return null;
19536        lipInput = form.querySelector('input[name="' + LIP_NAME + '"]');
19537        if (!lipInput) {
19538          lipInput = document.createElement('input');
19539          lipInput.type = 'hidden';
19540          lipInput.name = LIP_NAME;
19541          lipInput.setAttribute('data-bp-expected-ship-lip', '');
19542          lipInput.disabled = true;
19543          form.appendChild(lipInput);
19544        }
19545        return lipInput;
19546      };
19547      const syncLip = (value) => {
19548        const input = ensureLip();
19549        if (!input) return;
19550        if (value) {
19551          input.value = value;
19552          input.disabled = false;
19553        } else {
19554          input.value = '';
19555          input.disabled = true;
19556        }
19557      };
19558
19559      // Gate check + weekend/holiday date math now live in
19560      // window.bpPreorder (assets/bp-preorder-dates.js), shared with
19561      // the cart drawer/cart page (snippets/bp-cart-line-item.liquid)
19562      // so both surfaces show/hide and format the date identically.
19563      const shouldShow = (entry) => {
19564        const ok = window.bpPreorder.shouldShow(entry);
19565        if (!ok) console.log('[bp-preorder] hidden', entry || 'no entry for variant');
19566        return ok;
19567      };
19568      const formatDate = (raw) => window.bpPreorder.formatDate(raw, originalOverride);
19569
19570      // Move the rendered <p> next to the Color label, right after
19571      // "Color  Olive Night" (Figma: "Color   Olive Night   EXPECTED
19572      // SHIP DATE: MAY 18, 2026"). The Color row is NOT part of
19573      // Horizon's native variant-option fieldset system — BP fully
19574      // replaces it with blocks/bp-color-siblings.liquid, which renders
19575      // <p class="bp-colors__label"><span class="…prefix">Color</span>
19576      // <span class="…name">Olive Night</span></p> inside either
19577      // [data-bp-colors] (INV5/INV7 sibling-product colorways) or
19578      // [data-bp-variant-colors] (same-product Color variant, no
19579      // sibling products). Append inside that <p> — .bp-colors__label
19580      // is a flex row with `gap`, so the line spaces itself
19581      // automatically without extra margin.
19582      //
19583      // Falls back to the first native variant-option fieldset (usually
19584      // Size) when neither BP color block rendered — e.g. a product
19585      // with no color concept at all — so the line still shows up
19586      // somewhere instead of staying silently detached.
19587      const relocateToLegend = () => {
19588        const root = sectionRoot || document;
19589        // Evict any stale preorder line parked elsewhere by a previous
19590        // swatch/product morph (incl. a different colorway's product id)
19591        // before re-placing ours — prevents duplicate/stacked ship-date lines.
19592        root.querySelectorAll('.bp-preorder-line').forEach((el) => {
19593          if (el !== line) el.remove();
19594        });
19595        // Place the ship-date line directly BELOW the size chart row (QA:
19596        // Amber — move "Expected to ship" below the size chart, on the PDP and
19597        // in the quick-add flyout). Insert as a sibling right after the size
19598        // chart link block.
19599        const sizeChart = root.querySelector('.bp-size-chart-link');
19600        if (sizeChart) {
19601          if (sizeChart.nextElementSibling !== line) {
19602            sizeChart.insertAdjacentElement('afterend', line);
19603          }
19604          return;
19605        }
19606        // Fallback (no size chart, e.g. BWL/collective): sit it next to the
19607        // Color label as before, so it still shows somewhere.
19608        const colorLabel = root.querySelector(
19609          '[data-bp-colors] .bp-colors__label, [data-bp-variant-colors] .bp-colors__label'
19610        );
19611        const mount = colorLabel || root.querySelector('fieldset.variant-option legend');
19612        if (mount && line.parentElement !== mount) {
19613          mount.appendChild(line);
19614        }
19615      };
19616      relocateToLegend();
19617
19618      // A size must be actively chosen before we commit to a ship date —
19619      // it's variant-specific, and the buy box requires selection. If any
19620      // multi-value option fieldset has no checked radio, treat it as
19621      // "no size selected" and hide the line. (Merged back from main —
19622      // the refactor dropped this gate, so the date showed pre-selection.)
19623      const bpSizeSelected = () => {
19624        const root = sectionRoot || document;
19625        const picker = root.querySelector('variant-picker');
19626        if (!picker) return true;
19627        const fs = picker.querySelectorAll('fieldset.variant-option');
19628        for (let i = 0; i < fs.length; i++) {
19629          if (fs[i].querySelectorAll('input[type="radio"]').length <= 1) continue;
19630          if (!fs[i].querySelector('input[type="radio"]:checked')) return false;
19631        }
19632        return true;
19633      };
19634
19635      const update = (variantId, source) => {
19636        console.log('[bp-preorder] update()', { variantId, source });
19637        if (!bpSizeSelected()) {
19638          line.hidden = true;
19639          syncLip('');
19640          return;
19641        }
19642        const entry = variants[String(variantId)];
19643        if (!shouldShow(entry)) {
19644          line.hidden = true;
19645          syncLip('');
19646          return;
19647        }
19648        const formatted = formatDate(entry.dcDate);
19649        if (!formatted) {
19650          console.log('[bp-preorder] formatDate returned null', { dcDate: entry.dcDate, originalOverride });
19651          line.hidden = true;
19652          syncLip('');
19653          return;
19654        }
19655        console.log('[bp-preorder] SHOWING', { variantId, formatted, entry });
19656        dateEl.textContent = formatted;
19657        line.hidden = false;
19658        syncLip(formatted);
19659      };
19660
19661      // Initial selected variant
19662      update(window.bpCurrentVariantId || 56389031657638, 'init');
19663
19664      // React to variant changes. Horizon fires `variant:update` on
19665      // document via events.js — bubbles=true, detail.resource.id is
19666      // the new variant id. Keep the other names as fallbacks in case
19667      // another integration dispatches them.
19668      const onChange = (e) => {
19669        const vid =
19670          e?.detail?.resource?.id ||
19671          e?.detail?.variant?.id ||
19672          e?.detail?.id;
19673        console.log('[bp-preorder] event', e.type, { vid, detail: e.detail });
19674        if (!vid) return;
19675        update(vid, e.type);
19676      };
19677      document.addEventListener('variant:update', onChange);
19678      document.addEventListener('variant:change', onChange);
19679      document.addEventListener('variantchange', onChange);
19680      document.addEventListener('variant:selected', onChange);
19681
19682      // Horizon's variant picker morphs its own <fieldset>/<legend> on
19683      // variant change (variant-picker.js:399). That morph removes the
19684      // <p> we just appended to the legend. Re-attach after each morph.
19685      document.addEventListener('variant:update', () => setTimeout(relocateToLegend, 0));
19686
19687      // Fallback — watch the product form's hidden input for id changes.
19688      // sectionRoot was resolved above (inside ensureLip); reuse it here.
19689      if (sectionRoot) {
19690        let lastSeen = null;
19691        const obs = new MutationObserver(() => {
19692          const input = sectionRoot.querySelector('input[name="id"]');
19693          if (!input) return;
19694          const vid = parseInt(input.value, 10);
19695          if (vid && vid !== lastSeen) {
19696            lastSeen = vid;
19697            update(vid);
19698          }
19699        });
19700        obs.observe(sectionRoot, { attributes: true, childList: true, subtree: true });
19701      }
19702    })();
19703  </script>
19703
19704
19705
19706
19707
19708
19709
19710
19711
19712
19713
19714
19715
19716
19717
19718<div class="bp-acc" data-bp-acc ><details class="bp-acc__item" name="bp-acc-AaTJqeCs3S1EvVmVPc__bp_product_accordion">
19719        <summary class="bp-acc__summary">
19720          <span>Product Detail</span>
19721          <svg class="bp-acc__chevron" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
19722            <polyline points="6 9 12 15 18 9"/>
19723          </svg>
19724        </summary>
19725        <div class="bp-acc__body"><p class="bp-acc__intro">Add a versatile pop of style with our Boston Proper Printed Scarf. This lightweight essential is perfect as a headscarf, necktie, or bag accent. Effortlessly elevate casual outfits, office wear, or vacation looks with this chic, year-round accessory.</p><ul class="bp-acc__list"><li>100% polyester</li><li>Hand wash</li><li>Imported</li></ul><p class="bp-acc__sku" data-bp-acc-sku>
19726            SKU: <span data-bp-detail-sku>2CT8071</span>
19727          </p>
19728        </div>
19729      </details><details class="bp-acc__item" name="bp-acc-AaTJqeCs3S1EvVmVPc__bp_product_accordion">
19730        <summary class="bp-acc__summary">
19731          <span>Size & Fit</span>
19732          <svg class="bp-acc__chevron" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
19733            <polyline points="6 9 12 15 18 9"/>
19734          </svg>
19735        </summary>
19736        <div class="bp-acc__body">
19737          <ul class="bp-acc__list"><li>27 inch L X 27 inch W</li><li>One Size</li></ul>
19738        </div>
19739      </details><details class="bp-acc__item" name="bp-acc-AaTJqeCs3S1EvVmVPc__bp_product_accordion">
19740        <summary class="bp-acc__summary">
19741          <span>Shipping & Returns</span>
19742          <svg class="bp-acc__chevron" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
19743            <polyline points="6 9 12 15 18 9"/>
19744          </svg>
19745        </summary>
19746        <div class="bp-acc__body"><table class="bp-acc__ship-table">
19747              <thead>
19748                <tr>
19749                  <th></th>
19750                  <th>Estimated Delivery*</th>
19751                  <th>Price</th>
19752                </tr>
19753              </thead>
19754              <tbody>
19755                <tr><td>Standard Shipping</td><td>3-7 Business Days</td><td>$9.95</td></tr>
19756                <tr><td>Two Day Shipping</td><td>2 Business Days</td><td>$18.90</td></tr>
19757                <tr><td>Next Day Shipping</td><td>Next Business Day</td><td>$24.90</td></tr>
19758              </tbody>
19759            </table>
19760            <p>*Delivery estimates are for <strong>in-stock items only</strong>. Two Day and Next Day estimates are for orders placed by 10AM EST.</p>
19761            <p>We offer easy online returns and exchanges within 30 days of shipment date, <strong>excluding clearance items marked as Final Sale</strong>. Exchanges for like items (same style and color in a different size) are free. For returns, a $6.95 return postage charge will be deducted from your refund. <a href="/pages/returns-exchanges">View the Returns &amp; Exchanges policy.</a></p></div>
19762      </details></div>
19762<script type="application/json" class="bp-acc-sku-data" data-block="AaTJqeCs3S1EvVmVPc__bp_product_accordion">
19763    {"56389031657638": "2CT8071"}
19764  </script>
19764
19765  
19765<script>
19766    (function () {
19767      var dataEl = document.querySelector('script.bp-acc-sku-data[data-block="AaTJqeCs3S1EvVmVPc__bp_product_accordion"]');
19768      if (!dataEl) return;
19769      var acc = dataEl.previousElementSibling;
19770      var span = acc && acc.querySelector('[data-bp-detail-sku]');
19771      var wrap = acc && acc.querySelector('[data-bp-acc-sku]');
19772      if (!span) return;
19773      var map;
19774      try { map = JSON.parse(dataEl.textContent || '{}'); } catch (_) { return; }
19775      document.addEventListener('variant:update', function (e) {
19776        var vid = e && e.detail && e.detail.resource && e.detail.resource.id;
19777        if (!vid) return;
19778        var sku = map[String(vid)];
19779        if (sku == null) return;
19780        span.textContent = sku;
19781        if (wrap) wrap.hidden = (sku === '');
19782      });
19783    })();
19784  </script>
19784
19785
19786
19787<bp-ctl
19788    class="bp-ctl"
19789    data-bp-ctl
19790    data-bp-ctl-style="2CT8071"
19791    data-bp-ctl-max="4"
19792    data-bp-ctl-amplience="https://media.bostonproper.com"
19793    hidden
19794    
19795  >
19796    <h2 class="bp-ctl__heading">Complete The Look</h2>
19797    <div class="bp-ctl__carousel" data-bp-ctl-carousel>
19798      <button
19799        type="button"
19800        class="bp-ctl__arrow bp-ctl__arrow--prev"
19801        data-bp-ctl-prev
19802        aria-label="View previous outfit item"
19803      >
19804        <svg xmlns="http://www.w3.org/2000/svg" width="6" height="13" viewBox="0 0 6 13" fill="none" style="transform: rotate(180deg);">
19805          <path d="M0 1.26164L1.40796 0.020813L6 6.30252L1.40796 12.7941L0 11.5168L3.67363 6.30252L0 1.26164Z" fill="#232323"/>
19806        </svg>
19807      </button>
19808      <ul class="bp-ctl__rail" data-bp-ctl-rail role="list"></ul>
19809      <button
19810        type="button"
19811        class="bp-ctl__arrow bp-ctl__arrow--next"
19812        data-bp-ctl-next
19813        aria-label="View next outfit item"
19814      >
19815        <svg xmlns="http://www.w3.org/2000/svg" width="6" height="13" viewBox="0 0 6 13" fill="none">
19816          <path d="M0 1.26164L1.40796 0.020813L6 6.30252L1.40796 12.7941L0 11.5168L3.67363 6.30252L0 1.26164Z" fill="#232323"/>
19817        </svg>
19818      </button>
19819    </div>
19820  </bp-ctl>
19821
19822
19823
19824
19825
19826
19827
19828
19829
19830<script type="application/ld+json">
19831    {
19832      "@context": "https://schema.org",
19833      "@type": "Product",
19834      "name": "Boston Proper Printed Scarf With Love BP",
19835      "url": "https://www.bostonproper.com/products/boston-proper-printed-scarf-with-love-bp",
19836      "sku": "2CT8071",
19837      "description": "",
19838      "image": ["//www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198&width=1200",
19839"//www.bostonproper.com/cdn/shop/files/2_af52291f-802d-4184-8815-c64ea15071dd.jpg?v=1791009198&width=1200"
19840],
19841      "brand": { "@type": "Brand", "name": "Boston Proper" },
19842      "color": "With Love BP",
19843      "material": "100% Polyester",
19844      "pattern": null,
19845      "audience": { "@type": "PeopleAudience", "suggestedGender": "female" },
19846      "additionalProperty": [{ "@type": "PropertyValue", "name": "Product Detail", "value": "100% polyester" },{ "@type": "PropertyValue", "name": "Product Detail", "value": "Hand wash" },{ "@type": "PropertyValue", "name": "Product Detail", "value": "Imported" },{ "@type": "PropertyValue", "name": "Product Fit", "value": "27 inch L X 27 inch W" },{ "@type": "PropertyValue", "name": "Product Fit", "value": "One Size" },{ "@type": "PropertyValue", "name": "Style", "value": "2CT8071" },
19847        { "@type": "PropertyValue", "name": "Occasion", "value": "Work " },
19848        { "@type": "PropertyValue", "name": "Neckline", "value": null },
19849        { "@type": "PropertyValue", "name": "Care Instructions", "value": "Hand wash" }
19850      ],"aggregateRating": {
19851        "@type": "AggregateRating",
19852        "ratingValue": "4.8",
19853        "reviewCount": "75",
19854        "bestRating": "5",
19855        "worstRating": "1"
19856      },"offers": {
19857        "@type": "AggregateOffer",
19858        "priceCurrency": "USD",
19859        "lowPrice": "50.0",
19860        "highPrice": "50.0",
19861        "offerCount": 1,
19862        "offers": [{
19863              "@type": "Offer",
19864              "sku": "2CT8071000",
19865              "url": "https://www.bostonproper.com/products/boston-proper-printed-scarf-with-love-bp?variant=56389031657638",
19866              "price": "50.0",
19867              "priceCurrency": "USD",
19868              "priceValidUntil": "2026-12-31",
19869              "availability": "https://schema.org/InStock",
19870              "itemCondition": "https://schema.org/NewCondition",
19871              "hasMerchantReturnPolicy": {
19872                "@type": "MerchantReturnPolicy",
19873                "applicableCountry": "US",
19874                "returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
19875                "merchantReturnDays": 60,
19876                "returnMethod": "https://schema.org/ReturnByMail",
19877                "returnFees": "https://schema.org/ReturnShippingFees"
19878              },
19879              "shippingDetails": {
19880                "@type": "OfferShippingDetails",
19881                "shippingRate": { "@type": "MonetaryAmount", "value": "9.95", "currency": "USD" }
19882              }
19883            }
19884]
19885      }
19886    }
19887  </script>
19887<script type="application/ld+json">
19888    {
19889      "@context": "https://schema.org",
19890      "@type": "BreadcrumbList",
19891      "itemListElement": [
19892        { "@type": "ListItem", "position": 1, "name": "Home", "item": "https:\/\/www.bostonproper.com\/" },{ "@type": "ListItem", "position": 2, "name": "All", "item": "https://www.bostonproper.com/collections/all" },
19893        { "@type": "ListItem", "position": 3, "name": "Boston Proper Printed Scarf With Love BP", "item": "https://www.bostonproper.com/products/boston-proper-printed-scarf-with-love-bp" }]
19894    }
19895  </script>
19895
19896
19897  </div>
19898</div>
19899
19900
19901
19902</div>
19903
19904
19905
19906
19907
19908
19909      
19910    
19911  </div>
19912
19913  
19914  
19915
19916</div>
19917
19918
19919
19920
19921</div><section id="shopify-section-template--29563577761958__bp_how_to_wear_it" class="shopify-section"><bp-htwi
19922    class="bp-htwi bp-stylitics"
19923    data-bp-htwi
19924    data-bp-htwi-style="2CT8071"
19925    data-bp-htwi-max="6"
19926    data-bp-htwi-product-id="15286962618534"
19927    data-section-id="template--29563577761958__bp_how_to_wear_it"
19928  >
19929    <div id="how-to-wear-it"></div>
19930    <h2 class="bp-htwi__heading bp-stylitics__heading" data-bp-htwi-heading hidden>How to Wear It</h2><p class="bp-htwi__subtitle stylitics-composer-subtitle" data-bp-htwi-subtitle hidden>On Model Look</p><div class="bp-stylitics__target stylitics-composer-widget" data-bp-htwi-target></div>
19931  </bp-htwi>
19932
19933
19934
19935
19936</section><section id="shopify-section-template--29563577761958__bp_collection_details_7WJmXd" class="shopify-section"><style data-bp-section-knobs="template--29563577761958__bp_collection_details_7WJmXd">
19937  [data-bp-section][data-section-id="template--29563577761958__bp_collection_details_7WJmXd"] {
19938    --bp-knobs-pad-x-d: 40px;
19939    --bp-knobs-pad-x-m: 16px;
19940    --bp-knobs-pad-y-d: 40px;
19941    --bp-knobs-pad-y-m: 32px;
19942
19943
19944
19945    --bp-knobs-align-d: start;
19946    --bp-knobs-align-m: start;
19947  }
19948</style>
19949
19950
19951<bp-collection-details
19952  class="bp-cd"
19953  data-bp-section
19954  data-section-id="template--29563577761958__bp_collection_details_7WJmXd"
19955  data-bp-mode-d="padded"
19956  data-bp-mode-m="padded"
19957  data-collection-handle=""
19958  data-namespace="custom"
19959  data-key="pdp_collection_story"
19960  data-max-cards="5"
19961  data-sf-token="04534ca2c4aa793f02c0c735d5d6160c"
19962  hidden
19963>
19964  <div class="bp-section__inner bp-cd__inner">
19965    <div class="bp-cd__head" data-bp-cd-head hidden>
19966      <h2 class="bp-section__title bp-cd__headline" data-bp-cd-headline></h2>
19967      <p class="bp-cd__subcopy" data-bp-cd-subcopy></p>
19968    </div>
19969    <div class="bp-cd__grid" data-bp-cd-grid></div>
19970  </div>
19971</bp-collection-details>
19972
19973
19974
19975
19976
19977
19978</section><section id="shopify-section-template--29563577761958__bp_yotpo_reviews" class="shopify-section bp-pdp-extras-section"><div class="bp-pdp-extras" data-section-id="template--29563577761958__bp_yotpo_reviews">
19979    <section id="bp-pdp-reviews" class="bp-pdp-extras__reviews"><div
19980        class="yotpo-widget-instance"
19981        data-yotpo-instance-id="437236"
19982        data-yotpo-product-id="15286962618534"
19983        data-yotpo-name="Boston Proper Printed Scarf With Love BP"
19984        data-yotpo-url="https://www.bostonproper.com/products/boston-proper-printed-scarf-with-love-bp"
19985        data-yotpo-image-url="https://www.bostonproper.com/cdn/shop/files/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236_large.jpg?v=1791009198"
19986        data-yotpo-price="50.0"
19987        data-yotpo-currency="USD"
19988        data-yotpo-description=""
19989      ></div>
19990    </section>
19991
19992    
19992<script>
19993    (function () {
19994      // #bp-pdp-reviews landing: the browser's native hash-scroll fires
19995      // before the Yotpo widget + lazy images hydrate, so the user ends
19996      // up at the wrong Y-offset once content settles. Suppress the
19997      // initial jump, then re-scroll once the section stops growing OR a
19998      // hard timeout expires.
19999      if (window.location.hash !== '#bp-pdp-reviews') return;
20000      if (window.__bpPdpReviewsScrollScheduled) return;
20001      window.__bpPdpReviewsScrollScheduled = true;
20002
20003      try { if ('scrollRestoration' in history) history.scrollRestoration = 'manual'; } catch (_) {}
20004      window.scrollTo(0, 0);
20005
20006      var target = document.getElementById('bp-pdp-reviews');
20007      if (!target) return;
20008
20009      var HEADER_OFFSET_VAR = '--header-group-height';
20010      var STABLE_MS = 500;
20011      var HARD_TIMEOUT = 6000;
20012      var lastMutation = Date.now();
20013      var scrolled = false;
20014
20015      function headerOffset() {
20016        var css = getComputedStyle(document.body).getPropertyValue(HEADER_OFFSET_VAR);
20017        var n = parseInt(css, 10);
20018        return isFinite(n) ? n : 0;
20019      }
20020      function doScroll() {
20021        if (scrolled) return;
20022        scrolled = true;
20023        var rect = target.getBoundingClientRect();
20024        var y = rect.top + window.pageYOffset - headerOffset() - 16;
20025        window.scrollTo({ top: Math.max(0, y), behavior: 'smooth' });
20026      }
20027
20028      var mo = new MutationObserver(function () { lastMutation = Date.now(); });
20029      mo.observe(target, { childList: true, subtree: true, attributes: true });
20030
20031      var start = Date.now();
20032      var poll = setInterval(function () {
20033        var elapsed = Date.now() - start;
20034        var quiet = Date.now() - lastMutation;
20035        if (quiet >= STABLE_MS || elapsed >= HARD_TIMEOUT) {
20036          clearInterval(poll);
20037          mo.disconnect();
20038          doScroll();
20039        }
20040      }, 200);
20041
20042      window.addEventListener('load', function () {
20043        setTimeout(function () {
20044          if (!scrolled) {
20045            clearInterval(poll);
20046            mo.disconnect();
20047            doScroll();
20048          }
20049        }, 800);
20050      });
20051    })();
20052    </script>
20052
20053  </div>
20054
20055
20056
20057
20058</section><section id="shopify-section-template--29563577761958__bp_youll_also_love" class="shopify-section"><section
20059  class="bp-yall js-recommendation-container"
20060  data-section-type="product-recommendations"
20061  data-section-id="template--29563577761958__bp_youll_also_love"
20062  data-recommendation-url="/recommendations/products"
20063  data-product-id="15286962618534"
20064  data-limit="12"
20065  data-bp-amplience="https://media.bostonproper.com" data-bp-yall-use-br="true"
20066></section>
20066<script src="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-card-hydrate.js?v=169242559010489351881790713714" defer></script>
20066<script>
20067  (function () {
20068    const BP_YALL_BR_WIDGET = '09z4d58l';
20069    const BP_YALL_BR_HOST   = 'https://pathways.dxpapi.com/api/v2/widgets/item/';
20070    // `sku`/`slug` were requested but never consumed by the render — dropped
20071    // to trim payload (BR audit: minimize fl on non-PDP calls).
20072    const BP_YALL_BR_FIELDS = 'pid,title,url,brand,price,sale_price,thumb_image';
20073    // Shopping-bag icon for the BR cards' quick-add trigger (matches
20074    // snippets/bp-product-card.liquid). fill=currentColor so it inherits
20075    // the .bp-card__quick color + hover state.
20076    const BAG_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M4.18929 5.74434H16.5343H16.6292L16.6729 5.74549C16.9007 5.75099 17.1328 5.87803 17.2448 6.08089C17.3145 6.20157 17.3382 6.30372 17.3547 6.43048C17.6354 9.18806 17.9008 11.996 18.3051 14.7356C18.3771 15.2467 18.4466 15.758 18.5137 16.2697C18.5163 16.2917 18.5195 16.336 18.5207 16.3582C18.5378 16.6193 18.4156 16.9263 18.1508 17.0687C17.9651 17.1752 17.7807 17.1763 17.5845 17.1755C16.1978 17.1755 4.69428 17.1755 3.34023 17.1755C3.20422 17.1726 3.01496 17.1862 2.86505 17.1451C2.45036 17.0406 2.25213 16.656 2.31666 16.2445C2.41071 15.5271 2.58579 14.2489 2.68621 13.5185C2.95476 11.5399 3.15849 9.46674 3.35962 7.47459C3.37582 7.3571 3.44296 6.63739 3.45714 6.52887L3.46698 6.43424L3.46814 6.42237C3.46814 6.41948 3.46901 6.4134 3.47045 6.40559C3.5156 6.02417 3.79254 5.74028 4.18929 5.74434ZM4.18929 6.6125C4.2136 6.6125 4.24804 6.59601 4.27872 6.57343C4.30302 6.55491 4.3201 6.53089 4.32704 6.51845C4.33457 6.50601 4.33486 6.50138 4.33399 6.50427C4.33341 6.50803 4.33225 6.51353 4.33138 6.51758C4.33138 6.51758 4.33081 6.51932 4.33052 6.52424L4.32936 6.5361L4.31923 6.63044C4.132 8.4151 3.9054 10.3181 3.74624 12.1016C3.63685 13.4481 3.56103 15.0256 3.46727 16.3753L3.46582 16.3915V16.3961C3.46582 16.3961 3.46611 16.3973 3.4664 16.3915C3.4664 16.3872 3.4664 16.375 3.46351 16.3588C3.45396 16.2908 3.41721 16.2161 3.3602 16.1507C3.29306 16.0798 3.20422 16.0246 3.12319 16.0162C3.11856 16.0162 3.13361 16.0173 3.15647 16.0176C4.67199 16.0182 16.0117 16.0176 17.5848 16.0176H17.6719C17.6823 16.017 17.6916 16.0168 17.6962 16.0165C17.7014 16.0162 17.7034 16.0159 17.6991 16.0162C17.5752 16.0286 17.4268 16.1591 17.3857 16.2795C17.3576 16.3556 17.3617 16.3788 17.362 16.3941C17.362 16.3921 17.362 16.393 17.362 16.3886L17.3605 16.3724C17.254 14.8543 17.1872 13.3292 17.0509 11.8148C16.8906 10.0895 16.6752 8.23163 16.4883 6.50456C16.495 6.52019 16.5161 6.55433 16.5468 6.57575C16.5714 6.59485 16.5989 6.60585 16.6145 6.60961L16.6243 6.61192H16.6284C16.6284 6.61192 16.6298 6.61279 16.6304 6.61279C16.6318 6.61279 16.6336 6.61279 16.633 6.61279C16.6324 6.61279 16.635 6.61279 16.6292 6.61279C16.5783 6.61221 16.4 6.61337 16.3445 6.61279H4.18929V6.6125Z"/><path d="M6.08301 8.78064C6.1788 7.5189 6.20658 6.21405 6.58539 4.98907C7.15432 3.11007 8.4421 2.11631 10.414 2.12673C13.8001 2.13338 14.5031 4.87997 14.6721 7.71395C14.6964 8.07453 14.7158 8.43453 14.745 8.78035L13.5874 8.77485C13.6172 8.46057 13.6575 8.02649 13.6754 7.71858C13.801 5.83351 13.5976 3.34129 11.3988 2.81605C10.7575 2.6676 10.0702 2.6676 9.42892 2.81605C7.61503 3.24811 7.15143 5.0374 7.12683 6.6872C7.11121 7.36929 7.17545 8.09132 7.24056 8.77485L6.08301 8.78035V8.78064Z"/></svg>';
20077
20078    const SELECTORS = {
20079      container: '[data-section-id="template--29563577761958__bp_youll_also_love"]',
20080      arrowNext: '.js-recommendations-next',
20081      arrowPrev: '.js-recommendations-prev',
20082      rail: '.js-recommendations',
20083    };
20084
20085    const root = document.querySelector(SELECTORS.container);
20086    if (!root) return;
20087    // Note: `bpInitialized` is marked inside start() (the actual load), NOT
20088    // here — start() is deferred behind IntersectionObserver, so marking it
20089    // up-front would let a re-run bail while the recs never rendered. start()
20090    // is idempotent, so a duplicate script tag / double IO can't double-load.
20091    if (root.dataset.bpInitialized === 'true') return;
20092
20093    const limit     = root.dataset.limit;
20094    const productId = root.dataset.productId;
20095    const sectionId = root.dataset.sectionId;
20096    const recsUrl   = root.dataset.recommendationUrl;
20097    const useBr     = root.dataset.bpYallUseBr === 'true';
20098
20099    async function loadShopify() {
20100      try {
20101        const url = `${recsUrl}?section_id=${sectionId}&product_id=${productId}&limit=${limit}`;
20102        const res = await fetch(url, { credentials: 'same-origin' });
20103        if (!res.ok) throw new Error('recs HTTP ' + res.status);
20104        const text = await res.text();
20105        const wrap = document.createElement('div');
20106        wrap.innerHTML = text;
20107        const fresh = wrap.querySelector('.js-recommendation-container');
20108        if (fresh && fresh.innerHTML.trim().length) {
20109          root.innerHTML = fresh.innerHTML;
20110          wireArrows();
20111          bindBags(root);
20112        } else {
20113          root.style.display = 'none';
20114        }
20115      } catch (err) {
20116        console.warn('[bp-yall] section fetch failed', err);
20117        root.style.display = 'none';
20118      }
20119    }
20120
20121    async function loadBloomreach() {
20122      try {
20123        const br = (window.shop && window.shop.br) || {};
20124        const accountId = br.accountId || '';
20125        const domainKey = br.domainKey || 'bostonproper';
20126        // Empty (not a fabricated uid=0:v=app:ts=0:hc=1 sentinel) when the BR
20127        // cookie is absent — BR flags that sentinel as invalid. The empty
20128        // param is stripped below so anonymous calls simply omit _br_uid_2.
20129        const uidMatch  = document.cookie.match(/(?:^|;\s*)_br_uid_2=([^;]+)/);
20130        const uid       = uidMatch ? decodeURIComponent(uidMatch[1]) : '';
20131
20132        const params = new URLSearchParams({
20133          account_id: accountId,
20134          domain_key: domainKey,
20135          item_ids:   productId,
20136          rows:       String(limit),
20137          fields:     BP_YALL_BR_FIELDS,
20138          _br_uid_2:  uid,
20139          url:        window.location.href,
20140          ref_url:    document.referrer || window.location.href,
20141        });
20142        if (!params.get('_br_uid_2')) params.delete('_br_uid_2');
20143
20144        const fetchUrl = `${BP_YALL_BR_HOST}${BP_YALL_BR_WIDGET}?${params}`;
20145        const res = await fetch(fetchUrl, { credentials: 'omit' });
20146        if (!res.ok) throw new Error('BR HTTP ' + res.status);
20147        const data = await res.json();
20148        const docs = (data.response && data.response.docs) || [];
20149
20150        if (!docs.length) { root.style.display = 'none'; return; }
20151
20152        const MONEY = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' });
20153        // Whole-dollar prices drop the .00 — matches snippets/bp-product-card
20154        // (`money | replace: '.00', ''`) and assets/bp-card-hydrate money(), so
20155        // the initial BR-card price and the swatch-change repaint agree
20156        // (Ernie QA 7/22: $XX.XX on load flipped to $XX on swatch change).
20157        const money = (n) => MONEY.format(Number(n)).replace(/\.00$/, '');
20158        const esc = (s) => String(s || '').replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]));
20159
20160        // Normalize BR's absolute URL to a same-origin `/products/<handle>`
20161        // path — BR staging emits `staging.example.com` as the host on
20162        // every doc, prod emits `www.bostonproper.com` which can be wrong
20163        // depending on the visitor's current subdomain. Same-origin
20164        // relative paths always resolve to the shop the user is on.
20165        const hrefFromDoc = (doc) => {
20166          const m = String(doc.url || '').match(/\/products\/([^/?#]+)/);
20167          return m ? `/products/${m[1]}` : (doc.url || '#');
20168        };
20169        const itemsHtml = docs.map((doc) => {
20170          const onSale = doc.sale_price != null && doc.price != null && Number(doc.sale_price) < Number(doc.price) - 0.001;
20171          const price  = money(onSale ? doc.sale_price : doc.price);
20172          const compareVal = onSale ? money(doc.price) : '';
20173          const href = hrefFromDoc(doc);
20174          const compare = compareVal ? `<s class="bp-card__compare">${esc(compareVal)}</s>` : '';
20175          // Canonical BP product card (matches assets/bp-bloomreach.js
20176          // renderCard + snippets/bp-product-card.liquid) so BR cards get
20177          // the same quick-add bag: hover on desktop, ALWAYS shown on
20178          // mobile (data-bp-card-qv-vis-m="shown"). The bag markup is
20179          // hydrated on click by bindBags() below via BpCardHydrate.
20180          return `
20181            <li class="bp-yall__item">
20182              <product-card class="bp-card-host">
20183                <article class="bp-card"
20184                         data-product-id="${esc(doc.pid)}"
20185                         data-product-url="${esc(href)}"
20186                         data-bp-card-qb-style="button"
20187                         data-bp-card-qv-dest="drawer"
20188                         data-bp-card-qv-vis-d="hover"
20189                         data-bp-card-qv-vis-m="shown"
20190                         data-bp-source="bloomreach">
20191                  <div class="bp-card__media">
20192                    <a class="bp-card__media-link" href="${esc(href)}" aria-label="${esc(doc.title)}" ref="productCardLink" data-bp-card-product-link>
20193                      <img class="bp-card__image bp-card__image--primary" src="${esc(doc.thumb_image)}" alt="${esc(doc.title)}" loading="lazy" data-bp-card-image-primary>
20194                    </a>
20195                    <div class="bp-card__badges" data-bp-card-badges></div>
20196                    <button type="button" class="bp-card__quick" aria-label="Quick add ${esc(doc.title)}" data-product-id="${esc(doc.pid)}" data-bp-card-qv-trigger>${BAG_SVG}</button>
20197                  </div>
20198                  <div class="bp-card__body">
20199                    <h3 class="bp-card__title"><a href="${esc(href)}">${esc(doc.title)}</a></h3>
20200                    <div class="bp-card__price-row">
20201                      <span class="bp-card__price">${esc(price)}</span>${compare}
20202                    </div>
20203                  </div>
20204                </article>
20205              </product-card>
20206            </li>`;
20207        }).join('');
20208
20209        root.innerHTML = `
20210          <div class="bp-yall__head">
20211            <h2 class="bp-yall__heading">You'll Also Love</h2>
20212            <div class="bp-yall__nav" role="group" aria-label="Carousel navigation">
20213              <button type="button" class="bp-yall__arrow js-recommendations-prev" aria-label="Previous recommendations">
20214                <svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true"><path d="M25.8674 13.8674C25.9116 13.8244 25.9558 13.7814 26 13.7385C26.0872 13.8256 26.1744 13.9128 26.2615 14C26.2186 14.0442 26.1756 14.0884 26.1326 14.1326C25.8696 14.4029 25.6066 14.6733 25.3436 14.9436C22.9768 17.3768 20.6099 19.8099 18.2431 22.2431V21.7569C20.6762 24.1238 23.1094 26.4906 25.5425 28.8575C25.8129 29.1205 26.0832 29.3835 26.3536 29.6464C26.473 29.7627 26.5925 29.8789 26.712 29.9951C26.473 30.2341 26.2341 30.473 25.9951 30.712C25.8789 30.5925 25.7627 30.473 25.6464 30.3536C25.3835 30.0832 25.1205 29.8129 24.8575 29.5425C22.4906 27.1094 20.1238 24.6762 17.7569 22.2431L17.514 21.9933L17.7569 21.7569C20.1901 19.3901 22.6232 17.0232 25.0564 14.6564C25.3267 14.3934 25.5971 14.1304 25.8674 13.8674Z" fill="#171609"/><path d="M25.6464 13.6464C25.7627 13.527 25.8789 13.4075 25.9951 13.288C26.2341 13.527 26.473 13.7659 26.712 14.0049C26.5925 14.1211 26.473 14.2373 26.3536 14.3536C26.0832 14.6165 25.8129 14.8795 25.5425 15.1425C23.1094 17.5094 20.6762 19.8762 18.2431 22.2431V21.7569C20.6099 24.1901 22.9768 26.6232 25.3436 29.0564C25.6066 29.3267 25.8696 29.5971 26.1326 29.8674C26.1756 29.9116 26.2186 29.9558 26.2615 30C26.1744 30.0872 26.0872 30.1744 26 30.2615C25.9558 30.2186 25.9116 30.1756 25.8674 30.1326C25.5971 29.8696 25.3267 29.6066 25.0564 29.3436C22.6232 26.9768 20.1901 24.6099 17.7569 22.2431L17.514 21.9933L17.7569 21.7569C20.1238 19.3238 22.4906 16.8906 24.8575 14.4575C25.1205 14.1871 25.3835 13.9168 25.6464 13.6464Z" fill="#171609"/></svg>
20215              </button>
20216              <button type="button" class="bp-yall__arrow js-recommendations-next" aria-label="Next recommendations">
20217                <svg xmlns="http://www.w3.org/2000/svg" width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true"><path d="M18.1326 13.8674C18.0884 13.8244 18.0442 13.7814 18 13.7385C17.9128 13.8256 17.8256 13.9128 17.7385 14C17.7814 14.0442 17.8244 14.0884 17.8674 14.1326C18.1304 14.4029 18.3934 14.6733 18.6564 14.9436C21.0232 17.3768 23.3901 19.8099 25.7569 22.2431V21.7569C23.3238 24.1238 20.8906 26.4906 18.4575 28.8575C18.1871 29.1205 17.9168 29.3835 17.6464 29.6464C17.527 29.7627 17.4075 29.8789 17.288 29.9951C17.527 30.2341 17.7659 30.473 18.0049 30.712C18.1211 30.5925 18.2373 30.473 18.3536 30.3536C18.6165 30.0832 18.8795 29.8129 19.1425 29.5425C21.5094 27.1094 23.8762 24.6762 26.2431 22.2431L26.486 21.9933L26.2431 21.7569C23.8099 19.3901 21.3768 17.0232 18.9436 14.6564C18.6733 14.3934 18.4029 14.1304 18.1326 13.8674Z" fill="#171609"/><path d="M18.3536 13.6464C18.2373 13.527 18.1211 13.4075 18.0049 13.288C17.7659 13.527 17.527 13.7659 17.288 14.0049C17.4075 14.1211 17.527 14.2373 17.6464 14.3536C17.9168 14.6165 18.1871 14.8795 18.4575 15.1425C20.8906 17.5094 23.3238 19.8762 25.7569 22.2431V21.7569C23.3901 24.1901 21.0232 26.6232 18.6564 29.0564C18.3934 29.3267 18.1304 29.5971 17.8674 29.8674C17.8244 29.9116 17.7814 29.9558 17.7385 30C17.8256 30.0872 17.9128 30.1744 18 30.2615C18.0442 30.2186 18.0884 30.1756 18.1326 30.1326C18.4029 29.8696 18.6733 29.6066 18.9436 29.3436C21.3768 26.9768 23.8099 24.6099 26.2431 22.2431L26.486 21.9933L26.2431 21.7569C23.8762 19.3238 21.5094 16.8906 19.1425 14.4575C18.8795 14.1871 18.6165 13.9168 18.3536 13.6464Z" fill="#171609"/></svg>
20218              </button>
20219            </div>
20220          </div>
20221          <div class="bp-yall__carousel">
20222            <ul class="bp-yall__rail js-recommendations" role="list">${itemsHtml}</ul>
20223          </div>`;
20224
20225        wireArrows();
20226        handOffToHydrate(root);
20227        bindBags(root);
20228      } catch (err) {
20229        console.warn('[bp-yall] BR fetch failed', err);
20230        root.style.display = 'none';
20231      }
20232    }
20233
20234    // BR's item widget doesn't return sibling-color data, so swatches
20235    // are hydrated the same way the PLP does it: assets/bp-card-hydrate.js
20236    // reads each card's data-product-url and fetches
20237    // /products/<handle>?view=hydrate for the sibling list. That script
20238    // loads deferred (see the conditional script tag above), so poll
20239    // briefly in case this fetch resolves first.
20240    function handOffToHydrate(scope) {
20241      const tick = (left) => {
20242        if (window.BpCardHydrate && typeof window.BpCardHydrate.observeCards === 'function') {
20243          window.BpCardHydrate.observeCards(scope);
20244          return;
20245        }
20246        if (left <= 0) return;
20247        setTimeout(() => tick(left - 100), 100);
20248      };
20249      tick(3000);
20250    }
20251
20252    function wireArrows() {
20253      const rail = root.querySelector(SELECTORS.rail);
20254      const prev = root.querySelector(SELECTORS.arrowPrev);
20255      const next = root.querySelector(SELECTORS.arrowNext);
20256      if (!rail) return;
20257
20258      const update = () => {
20259        const max = rail.scrollWidth - rail.clientWidth;
20260        if (prev) prev.toggleAttribute('disabled', rail.scrollLeft <= 1);
20261        if (next) next.toggleAttribute('disabled', rail.scrollLeft >= max - 1);
20262      };
20263      const step = () => rail.clientWidth * 0.9;
20264      if (prev) prev.addEventListener('click', () => rail.scrollBy({ left: -step(), behavior: 'smooth' }));
20265      if (next) next.addEventListener('click', () => rail.scrollBy({ left: step(), behavior: 'smooth' }));
20266      rail.addEventListener('scroll', update, { passive: true });
20267      update();
20268    }
20269
20270    // Wire each card's quick-add bag to the BP product drawer (mirrors
20271    // bp-collection.bindBagIcons). Liquid / section-fetch cards
20272    // (bp-product-card) carry the quick-add markup inline, so the trigger
20273    // is found immediately; BR cards are hydrated on demand via
20274    // BpCardHydrate, then opened. Idempotent per bag.
20275    function bindBags(scope) {
20276      (scope || root).querySelectorAll('.bp-card__quick').forEach((bag) => {
20277        if (bag.dataset.bpBound) return;
20278        bag.dataset.bpBound = '1';
20279        bag.addEventListener('click', (e) => {
20280          e.preventDefault();
20281          e.stopPropagation();
20282          const card = bag.closest('.bp-card');
20283          if (!card) return;
20284          const open = () => {
20285            const trigger = card.querySelector('.quick-add__button--choose');
20286            if (!trigger) return false;
20287            if (typeof window.bpOpenProductDrawer === 'function') window.bpOpenProductDrawer(trigger);
20288            else trigger.click();
20289            return true;
20290          };
20291          if (open()) return;
20292          const handle = (card.dataset.productUrl || '').match(/\/products\/([^/?#]+)/);
20293          if (!handle || card.dataset.bpQaLoading === '1' || !window.BpCardHydrate) return;
20294          card.dataset.bpQaLoading = '1';
20295          window.BpCardHydrate.hydrateHandle(handle[1])
20296            .then((data) => { window.BpCardHydrate.applyHydration(card, data); })
20297            .then(() => { card.dataset.bpQaLoading = '0'; open(); })
20298            .catch(() => { card.dataset.bpQaLoading = '0'; });
20299        });
20300      });
20301    }
20302
20303    function start() {
20304      // Idempotent: mark only on real load, and bail if already loaded so a
20305      // duplicate IO/script can't double-fetch.
20306      if (root.dataset.bpInitialized === 'true') return;
20307      root.dataset.bpInitialized = 'true';
20308      if (useBr) {
20309        loadBloomreach();
20310      } else if (root.querySelector(SELECTORS.rail)) {
20311        wireArrows();
20312        bindBags(root);
20313      } else {
20314        loadShopify();
20315      }
20316    }
20317
20318    // Below-the-fold on the PDP — defer the recommendations fetch/render
20319    // until the section is near the viewport so it doesn't compete with
20320    // the LCP at page load. The section can be display:none while empty
20321    // (the :empty rule on the non-BR path) and IntersectionObserver can't
20322    // observe a box-less element, so anchor a 1px sentinel at the section's
20323    // DOM position (always in layout) and observe that. Once, ~600px lead.
20324    if ('IntersectionObserver' in window && root.parentNode) {
20325      const sentinel = document.createElement('div');
20326      sentinel.setAttribute('aria-hidden', 'true');
20327      sentinel.style.cssText = 'width:1px;height:1px;';
20328      root.parentNode.insertBefore(sentinel, root);
20329      const io = new IntersectionObserver((entries, obs) => {
20330        if (entries.some((e) => e.isIntersecting)) { obs.disconnect(); sentinel.remove(); start(); }
20331      }, { rootMargin: '600px 0px' });
20332      io.observe(sentinel);
20333    } else {
20334      start();
20335    }
20336  })();
20337</script>
20337
20338
20339
20340
20341
20342</section>
20343    </main>
20344
20345    <footer>
20346      <!-- BEGIN sections: footer-group -->
20347<div id="shopify-section-sections--29563569504422__bp_footer_main" class="shopify-section shopify-section-group-footer-group section-wrapper"><bp-footer
20348  class="bp-footer"
20349  data-section-id="sections--29563569504422__bp_footer_main"
20350  style="
20351    --bp-footer-heading-color: #171609;
20352    --bp-footer-body-color: #595750;
20353    --bp-footer-link-color: #595750;
20354    --bp-footer-social-border: #e1e0d4;
20355  "><div class="bp-footer__top">
20356
20357    <!-- Newsletter + Social: mobile copy (visible < 1024px only) -->
20358    <div class="bp-footer__newsletter bp-footer__newsletter--mobile"><p class="bp-footer__newsletter-heading">Join the list</p><p class="bp-footer__newsletter-copy">Sign up for email and SMS and get 20% OFF your order.</p><button
20359        type="button"
20360        class="bp-footer__signup-btn klaviyo_form_trigger_footer"
20361        data-bp-klaviyo-form-id="X8v8qM"
20362      >Sign Up</button><div class="bp-footer__legal"><p>By signing up via email or text, you agree to our <a href="/pages/terms-of-use" title="Terms of Use">Terms</a> & <a href="/pages/privacy-policy" title="Privacy Policy">Privacy</a>.</p></div><div class="bp-footer__social" role="list" aria-label="Social media links"><span role="listitem">
20363            <a
20364              href="https://www.instagram.com/bostonproperofficial/"
20365              class="bp-footer__social-icon"
20366              target="_blank"
20367              rel="noopener noreferrer"
20368              aria-label="Instagram"
20369            ><svg class="bp-footer__social-svg" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
20370
20371
20372<path
20373      fill-rule="evenodd"
20374      d="M13.23 3.492c-.84-.037-1.096-.046-3.23-.046-2.144 0-2.39.01-3.238.055-.776.027-1.195.164-1.487.273a2.43 2.43 0 0 0-.912.593 2.486 2.486 0 0 0-.602.922c-.11.282-.238.702-.274 1.486-.046.84-.046 1.095-.046 3.23 0 2.134.01 2.39.046 3.229.004.51.097 1.016.274 1.495.145.365.319.639.602.913.282.282.538.456.92.602.474.176.974.268 1.479.273.848.046 1.103.046 3.238.046 2.134 0 2.39-.01 3.23-.046.784-.036 1.203-.164 1.486-.273.374-.146.648-.329.921-.602.283-.283.447-.548.602-.922.177-.476.27-.979.274-1.486.037-.84.046-1.095.046-3.23 0-2.134-.01-2.39-.055-3.229-.027-.784-.164-1.204-.274-1.495a2.43 2.43 0 0 0-.593-.913 2.604 2.604 0 0 0-.92-.602c-.284-.11-.703-.237-1.488-.273ZM6.697 2.05c.857-.036 1.131-.045 3.302-.045 1.1-.014 2.202.001 3.302.045.664.014 1.321.14 1.943.374a3.968 3.968 0 0 1 1.414.922c.41.397.728.88.93 1.414.23.622.354 1.279.365 1.942C18 7.56 18 7.824 18 10.005c0 2.17-.01 2.444-.046 3.292-.036.858-.173 1.442-.374 1.943-.2.53-.474.976-.92 1.423a3.896 3.896 0 0 1-1.415.922c-.51.191-1.095.337-1.943.374-.857.036-1.122.045-3.302.045-2.171 0-2.445-.009-3.302-.055-.849-.027-1.432-.164-1.943-.364a4.152 4.152 0 0 1-1.414-.922 4.128 4.128 0 0 1-.93-1.423c-.183-.51-.329-1.085-.365-1.943C2.009 12.45 2 12.167 2 10.004c0-2.161 0-2.435.055-3.302.027-.848.164-1.432.365-1.942a4.44 4.44 0 0 1 .92-1.414 4.18 4.18 0 0 1 1.415-.93c.51-.183 1.094-.33 1.943-.366Zm.427 4.806a4.105 4.105 0 1 1 5.805 5.805 4.105 4.105 0 0 1-5.805-5.805Zm1.882 5.371a2.668 2.668 0 1 0 2.042-4.93 2.668 2.668 0 0 0-2.042 4.93Zm5.922-5.942a.958.958 0 1 1-1.355-1.355.958.958 0 0 1 1.355 1.355Z"
20375      clip-rule="evenodd"
20376    /></svg></a>
20377            </span><span role="listitem">
20378            <a
20379              href="https://www.tiktok.com/@bostonproperofficial"
20380              class="bp-footer__social-icon"
20381              target="_blank"
20382              rel="noopener noreferrer"
20383              aria-label="Tiktok"
20384            ><svg class="bp-footer__social-svg" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
20385
20386
20387<path d="M10.511 1.705h2.74s-.157 3.51 3.795 3.768v2.711s-2.114.129-3.796-1.158l.028 5.606A5.073 5.073 0 1 1 8.213 7.56h.708v2.785a2.298 2.298 0 1 0 1.618 2.205L10.51 1.705Z" /></svg></a>
20388            </span><span role="listitem">
20389            <a
20390              href="https://www.youtube.com/@bostonproper"
20391              class="bp-footer__social-icon"
20392              target="_blank"
20393              rel="noopener noreferrer"
20394              aria-label="Youtube"
20395            ><svg class="bp-footer__social-svg bp-footer__social-svg--youtube" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="13 13 14 14">
20396                    <path d="M26.3926 16.7286C26.2389 16.1458 25.7886 15.6865 25.2175 15.5295C24.1741 15.2383 20.0005 15.2383 20.0005 15.2383C20.0005 15.2383 15.827 15.2383 14.7837 15.5185C14.2235 15.6752 13.7622 16.1459 13.6086 16.7286C13.334 17.7929 13.334 20.0002 13.334 20.0002C13.334 20.0002 13.334 22.2187 13.6086 23.2718C13.7624 23.8545 14.2126 24.3139 14.7838 24.4708C15.8381 24.7621 20.0007 24.7621 20.0007 24.7621C20.0007 24.7621 24.1741 24.7621 25.2175 24.4819C25.7887 24.325 26.2389 23.8657 26.3927 23.283C26.6672 22.2187 26.6672 20.0114 26.6672 20.0114C26.6672 20.0114 26.6783 17.7929 26.3926 16.7286ZM18.6717 22.0394V17.9609L22.1423 20.0002L18.6717 22.0394Z" fill="currentColor"/>
20397                  </svg></a>
20398            </span><span role="listitem">
20399            <a
20400              href="https://www.facebook.com/bostonproper"
20401              class="bp-footer__social-icon"
20402              target="_blank"
20403              rel="noopener noreferrer"
20404              aria-label="Facebook"
20405            ><svg class="bp-footer__social-svg bp-footer__social-svg--facebook" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 6 12">
20406                    <path d="M1.26991 2.53971V3.80952H0V5.71429H1.26991V11.4286H3.80952V5.71429H5.49848L5.71429 3.80952H3.80952V2.69848C3.80952 2.18419 3.86029 1.91114 4.65391 1.91114H5.71429V0H4.01276C1.98095 9.52381e-05 1.26991 0.952381 1.26991 2.53971Z" fill="currentColor"/>
20407                  </svg></a>
20408            </span><span role="listitem">
20409            <a
20410              href="https://www.pinterest.com/bostonproper/"
20411              class="bp-footer__social-icon"
20412              target="_blank"
20413              rel="noopener noreferrer"
20414              aria-label="Pinterest"
20415            ><svg class="bp-footer__social-svg" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
20416
20417
20418<path d="M10 2.01c2.124.01 4.16.855 5.666 2.353a8.087 8.087 0 0 1 1.277 9.68A7.952 7.952 0 0 1 10 18.04a8.164 8.164 0 0 1-2.276-.307c.403-.653.672-1.24.816-1.729l.567-2.2c.134.27.393.5.768.702.384.192.768.297 1.19.297.836 0 1.585-.24 2.248-.72a4.678 4.678 0 0 0 1.537-1.969c.37-.89.554-1.848.537-2.8
2041813 0-1.249-.48-2.315-1.43-3.227a5.061 5.061 0 0 0-3.65-1.374c-.893 0-1.729.154-2.478.461a5.023 5.023 0 0 0-3.236 4.552c0 .72.134 1.355.413 1.902.269.538.672.922 1.22 1.152.096.039.182.039.25 0 .066-.028.114-.096.143-.192l.173-.653c.048-.144.02-.288-.105-.432a2.257 2.257 0 0 1-.548-1.565 3.803 3.803 0 0 1 3.976-3.861c1.047 0 1.863.288 2.44.855.585.576.883 1.315.883 2.228 0 .768-.106 1.479-.317 2.122a3.813 3.813 0 0 1-.893 1.556c-.384.384-.836.576-1.345.576-.413 0-.749-.144-1.018-.451-.259-.307-.345-.672-.25-1.085.147-.514.298-1.026.452-1.537l.173-.701c.057-.25.086-.451.086-.624 0-.346-.096-.634-.269-.855-.192-.22-.451-.336-.797-.336-.432 0-.797.192-1.085.595-.288.394-.442.893-.442 1.499.005.374.063.746.173 1.104l.058.144c-.576 2.478-.913 3.938-1.037 4.36-.116.528-.154 1.153-.125 1.863A8.067 8.067 0 0 1 2 10.03c0-2.208.778-4.11 2.343-5.666A7.721 7.721 0 0 1 10 2.001v.01Z" /></svg></a>
20419            </span></div></div>
20420
20421    <!-- Nav columns: up to 3 top-level items from the selected menu -->
20422    <nav class="bp-footer__nav" aria-label="Footer navigation"><div class="bp-footer__col">
20423          <p class="bp-footer__col-heading"><a href="/collections/all" class="bp-footer__col-heading-link">Shop</a></p><ul class="bp-footer__links" role="list"><li>
20424                  <a href="/pages/catalog-request" class="bp-footer__link">Request a Catalog</a>
20425                </li><li>
20426                  <a href="/pages/coupons-promotions" class="bp-footer__link">Coupons & Promotions</a>
20427                </li><li>
20428                  <a href="/pages/digital-catalog" class="bp-footer__link">Online Catalog</a>
20429                </li><li>
20430                  <a href="https://www.bostonproper.com/products/gift-card" class="bp-footer__link">Purchase a Gift Card</a>
20431                </li><li>
20432                  <a href="/pages/check-gift-card-balance" class="bp-footer__link">Check Gift Card Balance</a>
20433                </li><li>
20434                  <a href="/blogs/styleedit" class="bp-footer__link">styleEDIT Blog</a>
20435                </li><li>
20436                  <a href="/pages/refer-a-friend" class="bp-footer__link">Refer a Friend</a>
20437                </li></ul></div><div class="bp-footer__col">
20438          <p class="bp-footer__col-heading"><a href="/pages/about-us" class="bp-footer__col-heading-link">Learn</a></p><ul class="bp-footer__links" role="list"><li>
20439                  <a href="/pages/about-us" class="bp-footer__link">About Us</a>
20440                </li><li>
20441                  <a href="/pages/careers" class="bp-footer__link">Careers</a>
20442                </li><li>
20443                  <a href="https://www.ascendpartner.com/affiliate/registration" class="bp-footer__link">Affiliate Program</a>
20444                </li><li>
20445                  <a href="https://www.bostonproper.com/pages/accessibility-statement" class="bp-footer__link">Accessibility Statement</a>
20446                </li><li>
20447                  <a href="/pages/use-of-ai" class="bp-footer__link">Use of AI</a>
20448                </li></ul></div><div class="bp-footer__col">
20449          <p class="bp-footer__col-heading"><a href="/pages/customer-service" class="bp-footer__col-heading-link">Connect</a></p><ul class="bp-footer__links" role="list"><li>
20450                  <a href="/pages/customer-service" class="bp-footer__link">Customer Care</a>
20451                </li><li>
20452                  <a href="/pages/order-lookup" class="bp-footer__link">Order Status</a>
20453                </li><li>
20454                  <a href="https://www.bostonproper.com/pages/shipping-returns" class="bp-footer__link">Shipping</a>
20455                </li><li>
20456                  <a href="https://www.bostonproper.com/pages/size-chart" class="bp-footer__link">Size Chart</a>
20457                </li><li>
20458                  <a href="/pages/proper-insider-rewards" class="bp-footer__link">Proper Insider Rewards</a>
20459                </li><li>
20460                  <a href="/pages/marketplace-faqs" class="bp-footer__link">Brands We Love Marketplace</a>
20461                </li><li>
20462                  <a href="https://www.bostonproper.com/pages/returns-exchanges" class="bp-footer__link">Returns & Exchanges</a>
20463                </li><li>
20464                  <a href="/pages/charity" class="bp-footer__link">Style Meets Purpose</a>
20465                </li><li>
20466                  <a href="https://www.facebook.com/groups/4044543892348249/" class="bp-footer__link">Join Our Signature Circle</a>
20467                </li></ul></div></nav>
20468
20469    <!-- Newsletter + Social: desktop copy (visible >= 1024px only) -->
20470    <div class="bp-footer__newsletter bp-footer__newsletter--desktop"><p class="bp-footer__newsletter-heading">Join the list</p><p class="bp-footer__newsletter-copy">Sign up for email and SMS and get 20% OFF your order.</p><button
20471        type="button"
20472        class="bp-footer__signup-btn klaviyo_form_trigger_footer"
20473        data-bp-klaviyo-form-id="X8v8qM"
20474      >Sign Up</button><div class="bp-footer__legal"><p>By signing up via email or text, you agree to our <a href="/pages/terms-of-use" title="Terms of Use">Terms</a> & <a href="/pages/privacy-policy" title="Privacy Policy">Privacy</a>.</p></div><div class="bp-footer__social" role="list" aria-label="Social media links"><span role="listitem">
20475            <a
20476              href="https://www.instagram.com/bostonproperofficial/"
20477              class="bp-footer__social-icon"
20478              target="_blank"
20479              rel="noopener noreferrer"
20480              aria-label="Instagram"
20481            ><svg class="bp-footer__social-svg" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
20482
20483
20484<path
20485      fill-rule="evenodd"
20486      d="M13.23 3.492c-.84-.037-1.096-.046-3.23-.046-2.144 0-2.39.01-3.238.055-.776.027-1.195.164-1.487.273a2.43 2.43 0 0 0-.912.593 2.486 2.486 0 0 0-.602.922c-.11.282-.238.702-.274 1.486-.046.84-.046 1.095-.046 3.23 0 2.134.01 2.39.046 3.229.004.51.097 1.016.274 1.495.145.365.319.639.602.913.282.282.538.456.92.602.474.176.974.268 1.479.273.848.046 1.103.046 3.238.046 2.134 0 2.39-.01 3.23-.046.784-.036 1.203-.164 1.486-.273.374-.146.648-.329.921-.602.283-.283.447-.548.602-.922.177-.476.27-.979.274-1.486.037-.84.046-1.095.046-3.23 0-2.134-.01-2.39-.055-3.229-.027-.784-.164-1.204-.274-1.495a2.43 2.43 0 0 0-.593-.913 2.604 2.604 0 0 0-.92-.602c-.284-.11-.703-.237-1.488-.273ZM6.697 2.05c.857-.036 1.131-.045 3.302-.045 1.1-.014 2.202.001 3.302.045.664.014 1.321.14 1.943.374a3.968 3.968 0 0 1 1.414.922c.41.397.728.88.93 1.414.23.622.354 1.279.365 1.942C18 7.56 18 7.824 18 10.005c0 2.17-.01 2.444-.046 3.292-.036.858-.173 1.442-.374 1.943-.2.53-.474.976-.92 1.423a3.896 3.896 0 0 1-1.415.922c-.51.191-1.095.337-1.943.374-.857.036-1.122.045-3.302.045-2.171 0-2.445-.009-3.302-.055-.849-.027-1.432-.164-1.943-.364a4.152 4.152 0 0 1-1.414-.922 4.128 4.128 0 0 1-.93-1.423c-.183-.51-.329-1.085-.365-1.943C2.009 12.45 2 12.167 2 10.004c0-2.161 0-2.435.055-3.302.027-.848.164-1.432.365-1.942a4.44 4.44 0 0 1 .92-1.414 4.18 4.18 0 0 1 1.415-.93c.51-.183 1.094-.33 1.943-.366Zm.427 4.806a4.105 4.105 0 1 1 5.805 5.805 4.105 4.105 0 0 1-5.805-5.805Zm1.882 5.371a2.668 2.668 0 1 0 2.042-4.93 2.668 2.668 0 0 0-2.042 4.93Zm5.922-5.942a.958.958 0 1 1-1.355-1.355.958.958 0 0 1 1.355 1.355Z"
20487      clip-rule="evenodd"
20488    /></svg></a>
20489            </span><span role="listitem">
20490            <a
20491              href="https://www.tiktok.com/@bostonproperofficial"
20492              class="bp-footer__social-icon"
20493              target="_blank"
20494              rel="noopener noreferrer"
20495              aria-label="Tiktok"
20496            ><svg class="bp-footer__social-svg" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
20497
20498
20499<path d="M10.511 1.705h2.74s-.157 3.51 3.795 3.768v2.711s-2.114.129-3.796-1.158l.028 5.606A5.073 5.073 0 1 1 8.213 7.56h.708v2.785a2.298 2.298 0 1 0 1.618 2.205L10.51 1.705Z" /></svg></a>
20500            </span><span role="listitem">
20501            <a
20502              href="https://www.youtube.com/@bostonproper"
20503              class="bp-footer__social-icon"
20504              target="_blank"
20505              rel="noopener noreferrer"
20506              aria-label="Youtube"
20507            ><svg class="bp-footer__social-svg bp-footer__social-svg--youtube" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="13 13 14 14">
20508                    <path d="M26.3926 16.7286C26.2389 16.1458 25.7886 15.6865 25.2175 15.5295C24.1741 15.2383 20.0005 15.2383 20.0005 15.2383C20.0005 15.2383 15.827 15.2383 14.7837 15.5185C14.2235 15.6752 13.7622 16.1459 13.6086 16.7286C13.334 17.7929 13.334 20.0002 13.334 20.0002C13.334 20.0002 13.334 22.2187 13.6086 23.2718C13.7624 23.8545 14.2126 24.3139 14.7838 24.4708C15.8381 24.7621 20.0007 24.7621 20.0007 24.7621C20.0007 24.7621 24.1741 24.7621 25.2175 24.4819C25.7887 24.325 26.2389 23.8657 26.3927 23.283C26.6672 22.2187 26.6672 20.0114 26.6672 20.0114C26.6672 20.0114 26.6783 17.7929 26.3926 16.7286ZM18.6717 22.0394V17.9609L22.1423 20.0002L18.6717 22.0394Z" fill="currentColor"/>
20509                  </svg></a>
20510            </span><span role="listitem">
20511            <a
20512              href="https://www.facebook.com/bostonproper"
20513              class="bp-footer__social-icon"
20514              target="_blank"
20515              rel="noopener noreferrer"
20516              aria-label="Facebook"
20517            ><svg class="bp-footer__social-svg bp-footer__social-svg--facebook" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 6 12">
20518                    <path d="M1.26991 2.53971V3.80952H0V5.71429H1.26991V11.4286H3.80952V5.71429H5.49848L5.71429 3.80952H3.80952V2.69848C3.80952 2.18419 3.86029 1.91114 4.65391 1.91114H5.71429V0H4.01276C1.98095 9.52381e-05 1.26991 0.952381 1.26991 2.53971Z" fill="currentColor"/>
20519                  </svg></a>
20520            </span><span role="listitem">
20521            <a
20522              href="https://www.pinterest.com/bostonproper/"
20523              class="bp-footer__social-icon"
20524              target="_blank"
20525              rel="noopener noreferrer"
20526              aria-label="Pinterest"
20527            ><svg class="bp-footer__social-svg" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
20528
20529
20530<path d="M10 2.01c2.124.01 4.16.855 5.666 2.353a8.087 8.087 0 0 1 1.277 9.68A7.952 7.952 0 0 1 10 18.04a8.164 8.164 0 0 1-2.276-.307c.403-.653.672-1.24.816-1.729l.567-2.2c.134.27.393.5.768.702.384.192.768.297 1.19.297.836 0 1.585-.24 2.248-.72a4.678 4.678 0 0 0 1.537-1.969c.37-.89.554-1.848.537-2.8
2053013 0-1.249-.48-2.315-1.43-3.227a5.061 5.061 0 0 0-3.65-1.374c-.893 0-1.729.154-2.478.461a5.023 5.023 0 0 0-3.236 4.552c0 .72.134 1.355.413 1.902.269.538.672.922 1.22 1.152.096.039.182.039.25 0 .066-.028.114-.096.143-.192l.173-.653c.048-.144.02-.288-.105-.432a2.257 2.257 0 0 1-.548-1.565 3.803 3.803 0 0 1 3.976-3.861c1.047 0 1.863.288 2.44.855.585.576.883 1.315.883 2.228 0 .768-.106 1.479-.317 2.122a3.813 3.813 0 0 1-.893 1.556c-.384.384-.836.576-1.345.576-.413 0-.749-.144-1.018-.451-.259-.307-.345-.672-.25-1.085.147-.514.298-1.026.452-1.537l.173-.701c.057-.25.086-.451.086-.624 0-.346-.096-.634-.269-.855-.192-.22-.451-.336-.797-.336-.432 0-.797.192-1.085.595-.288.394-.442.893-.442 1.499.005.374.063.746.173 1.104l.058.144c-.576 2.478-.913 3.938-1.037 4.36-.116.528-.154 1.153-.125 1.863A8.067 8.067 0 0 1 2 10.03c0-2.208.778-4.11 2.343-5.666A7.721 7.721 0 0 1 10 2.001v.01Z" /></svg></a>
20531            </span></div></div>
20532
20533  </div><!-- /.bp-footer__top -->
20534
20535  <!-- Full-bleed brand wordmark -->
20536  <div class="bp-footer__wordmark" role="img" aria-label="Boston Proper"><svg xmlns="http://www.w3.org/2000/svg" width="3125.373" height="477.863" viewBox="0 0 3125.373 477.863" xmlns:v="https://vecta.io/nano"><defs><clipPath id="A"><path d="M0 358.397h2344.032V0H0z" transform="translate(-1192.84 -358.397)"/></clipPath><clipPath id="B"><path d="M0 358.397h2344.032V0H0z" transform="translate(-1231.018 -147.311)"/></clipPath><clipPath id="C"><path d="M0 358.397h2344.032V0H0z" transform="translate(-324.5 -185.766)"/></clipPath><clipPath id="D"><path d="M0 358.397h2344.032V0H0z" transform="translate(-374.634 -235.749)"/></clipPath><clipPath id="E"><path d="M0 358.397h2344.032V0H0z" transform="translate(-560.78 -113.875)"/></clipPath><clipPath id="F"><path d="M0 358.397h2344.032V0H0z" transform="translate(-179.077 -113.875)"/></clipPath><clipPath id="G"><path d="M0 358.397h2344.032V0H0z" transform="translate(-38.235 -116.862)"/></clipPath><clipPath id="H"><path d="M0 358.397h2344.032V0H0z" transform="translate(-755.738 -140.308)"/></clipPath><clipPath id="I"><path d="M0 358.397h2344.032V0H0z" transform="translate(-1904.567 -113.876)"/></clipPath><clipPath id="J"><path d="M0 358.397h2344.032V0H0z" transform="translate(-2146.066 -116.663)"/></clipPath><clipPath id="K"><path d="M0 358.397h2344.032V0H0z" transform="translate(-2042.293 -247.698)"/></clipPath><clipPath id="L"><path d="M0 358.397h2344.032V0H0z" transform="translate(-1809.258 -211.852)"/></clipPath><clipPath id="M"><path d="M0 358.397h2344.032V0H0z" transform="translate(-2286.082 -175.808)"/></clipPath><clipPath id="N"><path d="M0 358.397h2344.032V0H0z" transform="translate(-1642.062 -247.698)"/></clipPath><clipPath id="O"><path d="M0 358.397h2344.032V0H0z" transform="translate(-1192.84 -358.397)"/></clipPath><clipPath id="P"><path d="M0 358.397h2344.032V0H0z" transform="translate(-1231.018 -147.311)"/></clipPath><clipPath id="Q"><path d="M0 358.397h2344.032V0H0z" transform="translate(-324.5 -185.766)"/></clipPath><clipPath id="R"><path d="M0 358.397h2344.032V0H0z" transform="translate(-374.634 -235.749)"/></clipPath><clipPath id="S"><path d="M0 358.397h2344.032V0H0z" transform="translate(-560.78 -113.875)"/></clipPath><clipPath id="T"><path d="M0 358.397h2344.032V0H0z" transform="translate(-179.077 -113.875)"/></clipPath><clipPath id="U"><path d="M0 358.397h2344.032V0H0z" transform="translate(-38.235 -116.862)"/></clipPath><clipPath id="V"><path d="M0 358.397h2344.032V0H0z" transform="translate(-755.738 -140.308)"/></clipPath><clipPath id="W"><path d="M0 358.397h2344.032V0H0z" transform="translate(-1904.567 -113.876)"/></clipPath><clipPath id="X"><path d="M0 358.397h2344.032V0H0z" transform="translate(-2146.066 -116.663)"/></clipPath><clipPath id="Y"><path d="M0 358.397h2344.032V0H0z" transform="translate(-2042.293 -247.698)"/></clipPath><clipPath id="Z"><path d="M0 358.397h2344.032V0H0z" transform="translate(-1809.258 -211.852)"/></clipPath><clipPath id="a"><path d="M0 358.397h2344.032V0H0z" transform="translate(-2286.082 -175.808)"/></clipPath><clipPath id="b"><path d="M0 358.397h2344.032V0H0z" transform="translate(-1642.062 -247.698)"/></clipPath><path id="c" d="M0 0c.641-.454 1.721-.352 3.069-.428C71.046-4.284 131.83-41.973 168.985-98.563c22.383-34.091 35.214-73.313 37.788-113.93.252-3.977-.131-11.232.692-12.352v-5.956c.077.206-.436-.595-.441-.838l-.229-11.502c-2.614-41.097-15.515-80.404-38.474-115.192l-34.367-.022c14.563 17.472 25.313 36.778 32.868 57.999 7.514 21.208 11.391 43.038 12.422 65.592 1.197 26.189-2.028 51.989-10.102 76.887-16.078 49.577-50.287 91.772-96.564 115.686-54.842 28.34-120.314 26.363-173.426-5.074-54.594-32.313-89.695-90.034-96.401-153.074-3.221-30.282-.402-60.904 8.097-90.08 7.52-24.947 19.282-47.731 36.128-67.923l-34.335-.015c-22.438 34-35.353 72.424-38.319 112.649l-.209 6.75c-.004.13-.511.873-.439.712v20.847c0 2.305.513 5.111.721 7.898 2.961 39.581 15.764 77.783 37.623 111.031C-150.969-42.17-90.567-4.577-22.925-.477c1.561.095 2.604.025 3.568.477z"/><path id="d" d="M0 0c-36.873 3.668-58.007-28.965-60.558-61.979l-6.592-85.296-30.568-.003 6.677 86.898c3.06 35.896 21.866 54.274 51.958 70.374 6.455 3.454 12.433 6.982 17.89 11.876 8.033 7.205 13.487 16.237 15.915 26.831 3.542 15.455 2.452 33.471-5.328 47.51-10.605 19.137-31.194 25.342-51.859 21.56-14.199-2.599-25.74-11.636-31.911-24.655-3.51-7.101-5.214-14.44-6.
20536045-22.492l-16.759-217.906-30.565.025 16.755 217.822c1.543 15.86 8.716 30.125 20.124 41.023 24.807 23.589 64.163 26.807 94.634 13.338 11.696-5.169 21.633-12.709 29.425-22.747C34.946 74.154 31.573 33.961.134 13.982c36.017-3.624 64.039-23.923 72.893-59.584 4.16-18.066 2.991-37.092-3.463-54.549-13.087-35.395-48.719-47.873-83.897-47.129l1.081 13.706c29.353-.102 49.053 18.644 55.519 46.349 3.201 13.712 3.65 27.668 1.338 41.537C39.625-21.806 25.349-2.522 0 0"/><path id="e" d="M0 0l-13.741 5.576c-16.926 6.572-24.295 14.736-24.295 25.688 0 14.737 12.148 25.292 29.871 25.292S17.78 49.8 24.494 40.026v19.119c-9.16 3.784-20.71 5.576-29.671 5.576-29.871 0-48.591-15.135-48.591-39.231 0-16.927 10.754-29.273 31.265-37.438l14.936-5.776c15.732-6.173 23.499-14.139 23.499-26.684 0-16.13-13.144-27.482-31.465-27.482-17.723 0-27.787 8.157-39.629 22.304v-20.312c9.36-6.372 24.295-10.356 38.036-10.356 28.676 0 48.392 17.126 48.392 43.015C31.266-19.915 22.105-8.762 0 0"/><path id="f" d="M0 0c11.749 2.39 24.694 3.386 43.413 3.386v-83.839c0-21.706-.399-33.853-1.195-46.996h21.507c-.996 13.341-1.195 25.29-1.195 46.996V3.386c18.719 0 31.464-.995 43.214-3.386v11.949H0z"/><path id="g" d="M0 0c-30.269 0-50.98 25.889-50.98 64.124S-30.269 128.445 0 128.445c30.07 0 50.781-26.087 50.781-64.321S30.07 0 0 0m0 136.611c-41.023 0-71.292-30.668-71.292-72.487S-41.023-8.363 0-8.363s71.093 30.668 71.093 72.487S41.023 136.611 0 136.611"/><path id="h" d="M0 0c-30.269 0-50.98 25.889-50.98 64.124S-30.269 128.446 0 128.446c30.071 0 50.781-26.088 50.781-64.322S30.071 0 0 0m0 136.611c-41.023 0-71.292-30.668-71.292-72.487S-41.023-8.363 0-8.363s71.093 30.668 71.093 72.487S41.023 136.611 0 136.611"/><path id="i" d="M0 0h-18.321v122.671H0c16.927 0 27.481-9.359 27.481-24.892C27.481 81.25 15.732 69.7-.2 69.7l-13.797-.001 6.913-8.563h8.279c19.117 0 31.265-10.952 31.265-29.871C32.46 11.949 20.511 0 0 0zm14.935 65.916C35.048 69.7 46.599 82.445 46.599 98.973c0 20.114-17.326 31.863-45.803 31.863h-39.031c.796-12.347 1.194-24.295 1.194-47.196V38.434c0-22.901-.398-34.848-1.194-46.997H.598c31.862 0 51.776 15.533 51.776 39.63 0 19.914-12.745 32.459-37.439 34.849"/><path id="j" d="M0 0l-87.712 107.39h-24.254l15.334-18.774V-32.008h12.347V73.499L1.889-32.008h10.457V107.39H0z"/><path id="k" d="M0 0c-30.269 0-50.98 25.888-50.98 64.123S-30.269 128.445 0 128.445c30.07 0 50.781-26.087 50.781-64.321S30.07 0 0 0m0 136.61c-41.023 0-71.292-30.668-71.292-72.487S-41.023-8.364 0-8.364s71.093 30.668 71.093 72.488S41.023 136.61 0 136.61"/><path id="l" d="M0 0v61.335h13.343c15.732 0 26.086-.399 36.641-1.594v11.55c-9.957-1.194-20.711-1.792-36.641-1.792H0v53.371h8.364c20.511 0 33.854-1.196 45.404-3.585v11.75h-74.081c.797-13.343 1.195-25.49 1.195-47.197V38.634c0-21.508-.398-33.854-1.195-46.997h75.276V3.585C43.412 1.195 29.672 0 9.36 0z"/><path id="m" d="M0 0h-35.447c.796-12.347 1.194-24.295 1.194-47.196v-45.205c0-21.906-.398-33.854-1.194-46.997h21.507c-.996 13.541-1.195 25.091-1.195 46.997v84.236h13.94c20.114 0 33.058-11.55 33.058-30.07C31.863-57.75 19.118-69.7-1.394-69.7l-9.255.001 6.43-7.965h3.621c31.066 0 51.778 15.732 51.778 39.628S31.663 0 0 0"/><path id="n" d="M0 0c0 22.702-19.316 35.846-49.387 35.846h-38.434c.797-13.144 1.195-25.49 1.195-46.997v-45.405c0-21.706-.398-33.853-1.195-46.997h21.308c-.996 13.343-1.195 25.291-1.195 46.997v84.237h17.525c18.32 0 30.667-10.953 30.667-27.681 0-17.922-12.545-29.473-30.667-29.473h-14.594l59.798-74.079-.001.001.001-.002h23.698l-57.95 67.509C-15.931-34.053 0-19.913 0 0"/><path id="o" d="M0 0c23.3 1.991 39.231 16.131 39.231 36.044 0 22.702-19.317 35.846-49.387 35.846h-38.435c.797-13.144 1.195-25.491 1.195-46.997v-45.405c0-21.706-.397-33.852-1.194-46.996h21.308c-.996 13.342-1.195 25.29-1.195 46.996v84.237h17.525c18.32 0 30.667-10.953 30.667-27.681 0-17.922-12.546-29.473-30.667-29.473h-14.594l59.798-74.078h-.001l.001-.001H57.95z"/><path id="p" d="M0 0h-35.447c.796-12.347 1.194-24.295 1.194-47.196v-45.205c0-21.906-.398-33.853-1.194-46.997h21.507c-.996 13.541-1.195 25.091-1.195 46.997v84.236h13.94c20.113 0 33.057-11.55 33.057-30.07C31.862-57.75 19.118-69.7-1.394-69.7l-9.255.001 6.43-7.966h3.621c31.066 0 51.777 15.732 51.777 39.629S31.663 0 0 0"/></defs><g fill="currentColor"><use href="#c" transform="matrix(1.333333 0 0 -1.333333 1590.454 -.000267)" clip-path="url(#A)"/><use href="#d" transform="matrix(1.333333 0 0 -1.333333 1641.3571 281.44787)" clip-path="url(#B)"/><use href="#e" transform="matrix(1.333333 0 0 -1.333333 432.66653 230.17507)" clip-path="url(#C)"/><use href="#f" transform="matrix(1.333333 0 0 -1.333333 499.51187 163.53053)" clip-path="url(#D)"/><use href="#g" transform="matrix(1.333333 0 0 -1.333333 747.70707 326.02893)" clip-path="url(#E)"/><use href="#h" transform="matrix(1.333333 0 0 -1.333333 238.77 326.02893)" clip-path="url(#F)"/><use href="#i" transform="matrix(1.333333 0 0 -1.333333 50.9804 322.04613)" clip-path="url(#G)"/><use href="#j" transform="matrix(1.333333 0 0 -1.333333 1007.6507 290.7852)" clip-path="url(#H)"/><use href="#k" transform="matrix(1.333333 0 0 -1.333333 2539.4224 326.02827)" clip-path="url(#I)"/><use href="#l" transform="matrix(1.333333 0 0 -1.333333 2861.4209 322.31187)" clip-path="url(#J)"/><use href="#m" transform="matrix(1.333333 0 0 -1.333333 2723.0571 147.59867)" clip-path="url(#K)"/><use href="#n" transform="matrix(1.333333 0 0 -1.333333 2412.3441 195.39293)" clip-path="url(#L)"/><use href="#o" transform="matrix(1.333333 0 0 -1.333333 3048.1087 243.45173)" clip-path="url(#M)"/><use href="#p" transform="matrix(1.333333 0 0 -1.333333 2189.416 147.59867)" clip-path="url(#N)"/><use href="#c" transform="matrix(1.333333 0 0 -1.333333 1590.454 -.000267)" clip-path="url(#O)"/><use href="#d" transform="matrix(1.333333 0 0 -1.333333 1641.3571 281.44787)" clip-path="url(#P)"/><use href="#e" transform="matrix(1.333333 0 0 -1.333333 432.66653 230.17507)" clip-path="url(#Q)"/><use href="#f" transform="matrix(1.333333 0 0 -1.333333 499.51187 163.53053)" clip-path="url(#R)"/><use href="#g" transform="matrix(1.333333 0 0 -1.333333 747.70707 326.02893)" clip-path="url(#S)"/><use href="#h" transform="matrix(1.333333 0 0 -1.333333 238.77 326.02893)" clip-path="url(#T)"/><use href="#i" transform="matrix(1.333333 0 0 -1.333333 50.9804 322.04613)" clip-path="url(#U)"/><use href="#j" transform="matrix(1.333333 0 0 -1.333333 1007.6507 290.7852)" clip-path="url(#V
20536)"/><use href="#k" transform="matrix(1.333333 0 0 -1.333333 2539.4224 326.02827)" clip-path="url(#W)"/><use href="#l" transform="matrix(1.333333 0 0 -1.333333 2861.4209 322.31187)" clip-path="url(#X)"/><use href="#m" transform="matrix(1.333333 0 0 -1.333333 2723.0571 147.59867)" clip-path="url(#Y)"/><use href="#n" transform="matrix(1.333333 0 0 -1.333333 2412.3441 195.39293)" clip-path="url(#Z)"/><use href="#o" transform="matrix(1.333333 0 0 -1.333333 3048.1087 243.45173)" clip-path="url(#a)"/><use href="#p" transform="matrix(1.333333 0 0 -1.333333 2189.416 147.59867)" clip-path="url(#b)"/></g></svg></div>
20537
20538  <!-- Policy bar: copyright left, links right -->
20539  <div class="bp-footer__policy-bar"><span class="bp-footer__copyright">© 2026 Boston Proper.</span><div class="bp-footer__policy-links"><a href="/pages/check-gift-card-balance" class="bp-footer__policy-link">Check Gift Card Balance</a><a href="/pages/privacy-policy" class="bp-footer__policy-link">Privacy Policy</a>
20540      <a href="/pages/shipping-returns" class="bp-footer__policy-link">Shipping Policy</a>
20541      <a href="/pages/terms-of-use" class="bp-footer__policy-link">Terms of Service</a><a href="/pages/site-map" class="bp-footer__policy-link">Site Map</a></div>
20542  </div>
20543
20544
20545</bp-footer>
20546
20547
20548
20549
20550
20551
20552</div>
20553<!-- END sections: footer-group -->
20554    </footer>
20555
20556    
20557
20558<script
20559  src="//www.bostonproper.com/cdn/shop/t/1521/assets/dialog.js?v=150888536568694194021790713714"
20560  type="module"
20561></script>
20561
20562
20563<script
20564  src="//www.bostonproper.com/cdn/shop/t/1521/assets/predictive-search.js?v=174099676085626643091790713714"
20565  type="module"
20566  fetchpriority="low"
20567></script>
20567
20568
20569<dialog-component
20570  id="search-modal"
20571  class="search-modal"
20572  
20573>
20574  <dialog
20575    ref="dialog"
20576    on:click="/closeDialogOnClickOutside"
20577    on:keydown="/closeDialogOnEscapePress"
20578    class="search-modal__content dialog-modal"
20579    scroll-lock
20580    aria-labelledby="search-modal-heading"
20581  >
20582    <h2
20583      id="search-modal-heading"
20584      class="visually-hidden"
20585    >
20586      Search
20587    </h2>
20588    <predictive-search-component
20589      class="predictive-search color-scheme-1"
20590      style="--product-corner-radius: 0px; --card-corner-radius: 4px;"
20591      data-section-id="predictive-search"
20592      data-testid="search-component--modal"
20593      role="search"
20594      aria-label="Search"
20595    >
20596      <form
20597        action="/search"
20598        method="get"
20599        role="search"
20600        class="predictive-search-form"
20601        ref="form"
20602        on:keydown="/onSearchKeyDown"
20603      >
20604        <div
20605          class="predictive-search-form__header"
20606        >
20607          <div class="predictive-search-form__header-inner">
20608            <label
20609              for="cmdk-input"
20610              class="visually-hidden"
20611            >Search</label>
20612            <input
20613              class="search-input"
20614              id="cmdk-input"
20615              type="search"
20616              name="q"
20617              role="combobox"
20618              aria-expanded="false"
20619              aria-owns="predictive-search-results"
20620              aria-controls="predictive-search-results"
20621              aria-haspopup="listbox"
20622              aria-autocomplete="list"
20623              autocomplete="off"
20624              placeholder="Search"
20625              ref="searchInput"
20626              on:input="/search"
20627              on:keydown="/onSearchKeyDown"
20628            >
20629            <input
20630              name="options[prefix]"
20631              type="hidden"
20632              value="last"
20633            >
20634            <span class="svg-wrapper predictive-search__icon">
20635              <svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
20636<path d="M30.6967 19.7055C30.7183 23.8405 27.932 27.3926 24.0949 28.7508C17.6703 31.1232 10.0267 26.8687 10 19.7055C10.0272 12.5414 17.6703 8.28779 24.0953 10.6602C27.932 12.0184 30.7187 15.5704 30.6967 19.7055ZM28.5408 19.7055C28.5477 16.9739 27.3344 14.2088 25.1509 12.5164C22.4003 10.326 18.2959 10.3256 15.5454 12.5164C13.3619 14.2088 12.1486 16.9735 12.1555 19.7055C12.1486 22.437 13.3619 25.2022 15.5454 26.8946C18.2959 29.085 22.4003 29.0854 25.1509 26.8946C27.3344 25.2022 28.5477 22.4374 28.5408 19.7055Z" fill="currentColor"/>
20637<path d="M33.1718 33.9998C31.5945 32.7679 30.2255 31.2984 28.9126 29.7966C28.4814 29.2934 28.0606 28.7816 27.6699 28.2439L28.9794 27.1216C29.4511 27.5898 29.8927 28.084 30.3238 28.5872C31.3971 29.854 32.4207 31.1661 33.3132 32.5696C33.4917 32.8528 33.6659 33.1396 33.8263 33.4388L33.1714 34.0002L33.1718 33.9998Z" fill="currentColor"/>
20638</svg>
20639
20640            </span>
20641            <button
20642              type="button"
20643              class="button-unstyled predictive-search__reset-button"
20644              ref="resetButton"
20645              hidden
20646              on:click="/resetSearch"
20647            >
20648              Clear
20649            </button>
20650          </div>
20651          <button
20652            type="button"
20653            class="button predictive-search__close-modal-button"
20654            aria-label="Close dialog"
20655            on:click="dialog-component/closeDialog"
20656            ref="closeModalButton"
20657          >
20658            <span class="svg-wrapper">
20659              <svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
20660  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
20661  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
20662</svg>
20663
20664            </span>
20665          </button>
20666        </div>
20667
20668        <div class="predictive-search-form__content-wrapper">
20669          <div
20670            class="predictive-search-form__content"
20671            ref="predictiveSearchResults"
20672            on:click="/handleModalClick"
20673          >
20674
20675<div
20676  id="predictive-search-results"
20677  class="predictive-search-dropdown"
20678  role="listbox"
20679  aria-expanded="true"
20680  style="--color-shadow: rgb(var(--color-foreground-rgb) / 0.1);"
20681>
20682  
20683    <div class="predictive-search-results__inner">
20684      
20685      
20686        
20687        
20688        
20689          <div
20690  id="predictive-search-products"
20691  class="predictive-search-results__products"
20692  
20693    data-testid="search-component-default--modal"
20694  
20695>
20696  
20697    <h4 class="predictive-search-results__title">
20698      Products
20699    </h4>
20700    <ul
20701      class="predictive-search-results__list predictive-search-results__wrapper-products list-unstyled"
20702    >
20703      
20704      
20705        <li
20706          class="predictive-search-results__card predictive-search-results__card--product"
20707          ref="resultsItems[]"
20708        >
20709          <product-card class="bp-card-host">
20710  <article
20711    class="bp-card"
20712    data-product-id="15399681392806"
20713    data-product-url="/products/leopard-print-skirt-brown-multi"
20714    data-bp-card-secondary-hover="true"
20715    data-bp-card-qv-dest="drawer"
20716    data-bp-card-qv-vis-d="hover"
20717    data-bp-card-qv-vis-m="shown"
20718    data-bp-card-qb-style="button"
20719    data-bp-track-product='{    "id":          15399681392806,    "title":       "Leopard Print Skirt Brown Multi",    "vendor":      "Bagatelle",    "handle":      "leopard-print-skirt-brown-multi",    "url":         "\/products\/leopard-print-skirt-brown-multi",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO3390_SET.jpg?v=1791009176\u0026width=720",    "category":    "Skirts",    "product_type":null,    "selected_variant": {      "id":               56779671077030,      "sku":              "2DO3390800",      "price":            110.0,      "compare_at_price": 110.0,      "option1":          "Brown Multi",      "option2":          "L",      "product_id":       15399681392806,      "available":          true,      "inventory_quantity": 51    }  }'
20720  >
20721    <div class="bp-card__media">
20722      <a class="bp-card__media-link" href="/products/leopard-print-skirt-brown-multi" aria-label="Leopard Print Skirt Brown Multi" ref="productCardLink"><img
20723            class="bp-card__image bp-card__image--primary"
20724            src="//www.bostonproper.com/cdn/shop/files/2DO3390_SET.jpg?v=1791009176&width=720"
20725            srcset="//www.bostonproper.com/cdn/shop/files/2DO3390_SET.jpg?v=1791009176&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DO3390_SET.jpg?v=1791009176&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DO3390_SET.jpg?v=1791009176&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DO3390_SET.jpg?v=1791009176&width=1080 1080w"
20726            sizes="(min-width: 1024px) 25vw, 50vw"
20727            width="1639"
20728            height="2048"
20729            alt="Leopard Print Skirt Brown Multi"
20730            loading="lazy"
20731            data-bp-card-image-primary
20732          ><img
20733            class="bp-card__image bp-card__image--secondary"
20734            src="//www.bostonproper.com/cdn/shop/files/2_c2593330-685e-4f0d-affc-d3a27bbd70d9.jpg?v=1791009175&width=720"
20735            srcset="//www.bostonproper.com/cdn/shop/files/2_c2593330-685e-4f0d-affc-d3a27bbd70d9.jpg?v=1791009175&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_c2593330-685e-4f0d-affc-d3a27bbd70d9.jpg?v=1791009175&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_c2593330-685e-4f0d-affc-d3a27bbd70d9.jpg?v=1791009175&width=720 720w"
20736            sizes="(min-width: 1024px) 25vw, 50vw"
20737            width="1639"
20738            height="2048"
20739            alt=""
20740            loading="lazy"
20741            aria-hidden="true"
20742            data-bp-card-image-secondary
20743          ></a><div class="bp-card__badges" data-bp-card-badges></div><button
20744          type="button"
20745          class="bp-card__quick"
20746          aria-label="Quick add Leopard Print Skirt Brown Multi"
20747          data-product-id="15399681392806"
20748          data-bp-card-qv-trigger
20749        >
20750          <svg viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
20751            <path d="M4.18929 5.74434H16.5343H16.6292L16.6729 5.74549C16.9007 5.75099 17.1328 5.87803 17.2448 6.08089C17.3145 6.20157 17.3382 6.30372 17.3547 6.43048C17.6354 9.18806 17.9008 11.996 18.3051 14.7356C18.3771 15.2467 18.4466 15.758 18.5137 16.2697C18.5163 16.2917 18.5195 16.336 18.5207 16.3582C18.5378 16.6193 18.4156 16.9263 18.1508 17.0687C17.9651 17.1752 17.7807 17.1763 17.5845 17.1755C16.1978 17.1755 4.69428 17.1755 3.34023 17.1755C3.20422 17.1726 3.01496 17.1862 2.86505 17.1451C2.45036 17.0406 2.25213 16.656 2.31666 16.2445C2.41071 15.5271 2.58579 14.2489 2.68621 13.5185C2.95476 11.5399 3.15849 9.46674 3.35962 7.47459C3.37582 7.3571 3.44296 6.63739 3.45714 6.52887L3.46698 6.43424L3.46814 6.42237C3.46814 6.41948 3.46901 6.4134 3.47045 6.40559C3.5156 6.02417 3.79254 5.74
20751028 4.18929 5.74434ZM4.18929 6.6125C4.2136 6.6125 4.24804 6.59601 4.27872 6.57343C4.30302 6.55491 4.3201 6.53089 4.32704 6.51845C4.33457 6.50601 4.33486 6.50138 4.33399 6.50427C4.33341 6.50803 4.33225 6.51353 4.33138 6.51758C4.33138 6.51758 4.33081 6.51932 4.33052 6.52424L4.32936 6.5361L4.31923 6.63044C4.132 8.4151 3.9054 10.3181 3.74624 12.1016C3.63685 13.4481 3.56103 15.0256 3.46727 16.3753L3.46582 16.3915V16.3961C3.46582 16.3961 3.46611 16.3973 3.4664 16.3915C3.4664 16.3872 3.4664 16.375 3.46351 16.3588C3.45396 16.2908 3.41721 16.2161 3.3602 16.1507C3.29306 16.0798 3.20422 16.0246 3.12319 16.0162C3.11856 16.0162 3.13361 16.0173 3.15647 16.0176C4.67199 16.0182 16.0117 16.0176 17.5848 16.0176H17.6719C17.6823 16.017 17.6916 16.0168 17.6962 16.0165C17.7014 16.0162 17.7034 16.0159 17.6991 16.0162C17.5752 16.0286 17.4268 16.1591 17.3857 16.2795C17.3576 16.3556 17.3617 16.3788 17.362 16.3941C17.362 16.3921 17.362 16.393 17.362 16.3886L17.3605 16.3724C17.254 14.8543 17.1872 13.3292 17.0509 11.8148C16.8906 10.0895 16.6752 8.23163 16.4883 6.50456C16.495 6.52019 16.5161 6.55433 16.5468 6.57575C16.5714 6.59485 16.5989 6.60585 16.6145 6.60961L16.6243 6.61192H16.6284C16.6284 6.61192 16.6298 6.61279 16.6304 6.61279C16.6318 6.61279 16.6336 6.61279 16.633 6.61279C16.6324 6.61279 16.635 6.61279 16.6292 6.61279C16.5783 6.61221 16.4 6.61337 16.3445 6.61279H4.18929V6.6125Z"/>
20752            <path d="M6.08301 8.78064C6.1788 7.5189 6.20658 6.21405 6.58539 4.98907C7.15432 3.11007 8.4421 2.11631 10.414 2.12673C13.8001 2.13338 14.5031 4.87997 14.6721 7.71395C14.6964 8.07453 14.7158 8.43453 14.745 8.78035L13.5874 8.77485C13.6172 8.46057 13.6575 8.02649 13.6754 7.71858C13.801 5.83351 13.5976 3.34129 11.3988 2.81605C10.7575 2.6676 10.0702 2.6676 9.42892 2.81605C7.61503 3.24811 7.15143 5.0374 7.12683 6.6872C7.11121 7.36929 7.17545 8.09132 7.24056 8.77485L6.08301 8.78035V8.78064Z"/>
20753          </svg>
20754        </button><div class="bp-card__quick-add">
20755
20756<quick-add-component
20757  class="quick-add color-scheme-1 "
20758  ref="quickAdd"
20759  data-product-title="Leopard Print Skirt Brown Multi"
20760  data-quick-add-button="choose"
20761  data-product-options-count="2"
20762>
20763  <product-form-component
20764    data-section-id="bp-card"
20765    data-product-id="15399681392806"
20766    on:submit="/handleSubmit"
20767    class="quick-add__product-form-component"
20768  >
20769    <div
20770      class="visually-hidden"
20771      aria-live="assertive"
20772      role="status"
20773      aria-atomic="true"
20774      ref="liveRegion"
20775    ></div><form method="post" action="/cart/add" id="QuickAdd-ProductForm-15399681392806-" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" novalidate="novalidate" data-type="add-to-cart-form"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /><input
20776        type="hidden"
20777        name="id"
20778        ref="variantId"
20779        value="56779671077030"
20780        
20781      >
20782      <input
20783        type="hidden"
20784        name="quantity"
20785        value="1"
20786      >
20787      
20788      <add-to-cart-component
20789  ref="addToCartButtonContainer"
20790  data-product-variant-media="//www.bostonproper.com/cdn/shop/files/2DO3390_SET.jpg?v=1791009176&width=100"
20791  data-add-to-cart-animation="true"
20792>
20793  <button
20794    
20795    type="submit"
20796    name="add"
20797    ref="addToCartButton"
20798    on:click="/handleClick"
20799    class="button button quick-add__button quick-add__button--add add-to-cart-button"
20800    
20801    
20802  >
20803    <span
20804      class="add-to-cart-text"
20805    >
20806      
20807        <span
20808          aria-hidden="true"
20809          class="svg-wrapper add-to-cart-icon"
20810        ><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="var(--icon-stroke-width)" d="M16.608 9.421V6.906H3.392v8.016c0 .567.224 1.112.624 1.513.4.402.941.627 1.506.627H8.63M8.818 3h2.333c.618 0 1.212.247 1.649.686a2.35 2.35 0 0 1 .683 1.658v1.562H6.486V5.344c0-.622.246-1.218.683-1.658A2.33 2.33 0 0 1 8.82 3"/><path stroke="currentColor" stroke-linecap="round" stroke-width="var(--icon-stroke-width)" d="M14.608 12.563v5m2.5-2.5h-5"/></svg>
20811</span>
20812      
20813      <span class="add-to-cart-text__content is-visually-hidden-mobile">
20814        <span>
20815          <span>Add</span>
20816        </span>
20817      </span>
20818    </span>
20819    
20820    <span class="add-to-cart__added">
20821      <span class="svg-wrapper add-to-cart__added-icon"><svg aria-hidden="true" class="checkmark-burst" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
20822  <g class="check">
20823    <circle class="ring" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
20824    <path class="tick" d="M9 12.75L11.25 15L15 9.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
20825  </g>
20826  <g class="burst">
20827    <g style="--index: 0;">
20828      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
20829    </g>
20830    <g style="--index: 1;">
20831      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
20832    </g>
20833    <g style="--index: 2;">
20834      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
20835    </g>
20836    <g style="--index: 3;">
20837      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
20838    </g>
20839    <g style="--index: 4;">
20840      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
20841    </g>
20842    <g style="--index: 5;">
20843      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
20844    </g>
20845    <g style="--index: 6;">
20846      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
20847    </g>
20848    <g style="--index: 7;">
20849      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
20850    </g>
20851  </g>
20852</svg>
20853</span>
20854    </span>
20855  </button>
20856</add-to-cart-component>
20857
20858
20859      <button
20860        class="button quick-add__button quick-add__button--choose add-to-cart-button"
20861        
20862        type="button"
20863        name="add"
20864        on:click="quick-add-component/handleClick"
20865      >
20866        <span
20867          class="add-to-cart-text"
20868        >
20869          
20870          <span
20871            aria-hidden="true"
20872            class="svg-wrapper add-to-cart-icon"
20873          ><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="var(--icon-stroke-width)" d="M16.608 9.421V6.906H3.392v8.016c0 .567.224 1.112.624 1.513.4.402.941.627 1.506.627H8.63M8.818 3h2.333c.618 0 1.212.247 1.649.686a2.35 2.35 0 0 1 .683 1.658v1.562H6.486V5.344c0-.622.246-1.218.683-1.658A2.33 2.33 0 0 1 8.82 3"/><path stroke="currentColor" stroke-linecap="round" stroke-width="var(--icon-stroke-width)" d="M14.608 12.563v5m2.5-2.5h-5"/></svg>
20874</span>
20875          <span class="add-to-cart-text__content is-visually-hidden-mobile">
20876            <span>
20877              
20878              <span>
20879                Choose
20880              </span>
20881            </span>
20882          </span>
20883        </span>
20884      </button><input type="hidden" name="product-id" value="15399681392806" /></form></product-form-component>
20885</quick-add-component>
20886
20887
20888
20889</div></div>
20890
20891    <div class="bp-card__body"><h3 class="bp-card__title">
20892        <a href="/products/leopard-print-skirt-brown-multi">Leopard Print Skirt</a>
20893      </h3>
20894
20895      <div class="bp-card__price-row"><span class="bp-card__price">$110</span>
20896        <s class="bp-card__compare" hidden></s></div></div>
20897  </article>
20898</product-card>
20899
20900        </li>
20901      
20902        <li
20903          class="predictive-search-results__card predictive-search-results__card--product"
20904          ref="resultsItems[]"
20905        >
20906          <product-card class="bp-card-host">
20907  <article
20908    class="bp-card"
20909    data-product-id="15399681360038"
20910    data-product-url="/products/metallic-zebra-printed-dress-tan-multi"
20911    data-bp-card-secondary-hover="true"
20912    data-bp-card-qv-dest="drawer"
20913    data-bp-card-qv-vis-d="hover"
20914    data-bp-card-qv-vis-m="shown"
20915    data-bp-card-qb-style="button"
20916    data-bp-track-product='{    "id":          15399681360038,    "title":       "Metallic Zebra Printed Dress Tan Multi",    "vendor":      "Bagatelle",    "handle":      "metallic-zebra-printed-dress-tan-multi",    "url":         "\/products\/metallic-zebra-printed-dress-tan-multi",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO0590_
20916SET.jpg?v=1791009160\u0026width=720",    "category":    "Dresses",    "product_type":null,    "selected_variant": {      "id":               56779670782118,      "sku":              "2DO0590006",      "price":            180.0,      "compare_at_price": 180.0,      "option1":          "Tan Multi",      "option2":          "6",      "product_id":       15399681360038,      "available":          true,      "inventory_quantity": 50    }  }'
20917  >
20918    <div class="bp-card__media">
20919      <a class="bp-card__media-link" href="/products/metallic-zebra-printed-dress-tan-multi" aria-label="Metallic Zebra Printed Dress Tan Multi" ref="productCardLink"><img
20920            class="bp-card__image bp-card__image--primary"
20921            src="//www.bostonproper.com/cdn/shop/files/2DO0590_SET.jpg?v=1791009160&width=720"
20922            srcset="//www.bostonproper.com/cdn/shop/files/2DO0590_SET.jpg?v=1791009160&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DO0590_SET.jpg?v=1791009160&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DO0590_SET.jpg?v=1791009160&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DO0590_SET.jpg?v=1791009160&width=1080 1080w"
20923            sizes="(min-width: 1024px) 25vw, 50vw"
20924            width="1639"
20925            height="2048"
20926            alt="Metallic Zebra Printed Dress Tan Multi"
20927            loading="lazy"
20928            data-bp-card-image-primary
20929          ><img
20930            class="bp-card__image bp-card__image--secondary"
20931            src="//www.bostonproper.com/cdn/shop/files/2_0161cf9a-a917-4e26-98d6-d48db12f058a.jpg?v=1791009160&width=720"
20932            srcset="//www.bostonproper.com/cdn/shop/files/2_0161cf9a-a917-4e26-98d6-d48db12f058a.jpg?v=1791009160&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_0161cf9a-a917-4e26-98d6-d48db12f058a.jpg?v=1791009160&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_0161cf9a-a917-4e26-98d6-d48db12f058a.jpg?v=1791009160&width=720 720w"
20933            sizes="(min-width: 1024px) 25vw, 50vw"
20934            width="1639"
20935            height="2048"
20936            alt=""
20937            loading="lazy"
20938            aria-hidden="true"
20939            data-bp-card-image-secondary
20940          ></a><div class="bp-card__badges" data-bp-card-badges></div><button
20941          type="button"
20942          class="bp-card__quick"
20943          aria-label="Quick add Metallic Zebra Printed Dress Tan Multi"
20944          data-product-id="15399681360038"
20945          data-bp-card-qv-trigger
20946        >
20947          <svg viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
20948            <path d="M4.18929 5.74434H16.5343H16.6292L16.6729 5.74549C16.9007 5.75099 17.1328 5.87803 17.2448 6.08089C17.3145 6.20157 17.3382 6.30372 17.3547 6.43048C17.6354 9.18806 17.9008 11.996 18.3051 14.7356C18.3771 15.2467 18.4466 15.758 18.5137 16.2697C18.5163 16.2917 18.5195 16.336 18.5207 16.3582C18.5378 16.6193 18.4156 16.9263 18.1508 17.0687C17.9651 17.1752 17.7807 17.1763 17.5845 17.1755C16.1978 17.1755 4.69428 17.1755 3.34023 17.1755C3.20422 17.1726 3.01496 17.1862 2.86505 17.1451C2.45036 17.0406 2.25213 16.656 2.31666 16.2445C2.41071 15.5271 2.58579 14.2489 2.68621 13.5185C2.95476 11.5399 3.15849 9.46674 3.35962 7.47459C3.37582 7.3571 3.44296 6.63739 3.45714 6.52887L3.46698 6.43424L3.46814 6.42237C3.46814 6.41948 3.46901 6.4134 3.47045 6.40559C3.5156 6.02417 3.79254 5.74028 4.18929 5.74434ZM4.18929 6.6125C4.2136 6.6125 4.24804 6.59601 4.27872 6.57343C4.30302 6.55491 4.3201 6.53089 4.32704 6.51845C4.33457 6.50601 4.33486 6.50138 4.33399 6.50427C4.33341 6.50803 4.33225 6.51353 4.33138 6.51758C4.33138 6.51758 4.33081 6.51932 4.33052 6.52424L4.32936 6.5361L4.31923 6.63044C4.132 8.4151 3.9054 10.3181 3.74624 12.1016C3.63685 13.4481 3.56103 15.0256 3.46727 16.3753L3.46582 16.3915V16.3961C3.46582 16.3961 3.46611 16.3973 3.4664 16.3915C3.4664 16.3872 3.4664 16.375 3.46351 16.3588C3.45396 16.2908 3.41721 16.2161 3.3602 16.1507C3.29306 16.0798 3.20422 16.0246 3.12319 16.0162C3.11856 16.0162 3.13361 16.0173 3.15647 16.0176C4.67199 16.0182 16.0117 16.0176 17.5848 16.0176H17.6719C17.6823 16.017 17.6916 16.0168 17.6962 16.0165C17.7014 16.0162 17.7034 16.0159 17.6991 16.0162C17.5752 16.0286 17.4268 16.1591 17.3857 16.2795C17.3576 16.3556 17.3617 16.3788 17.362 16.3941C17.362 16.3921 17.362 16.393 17.362 16.3886L17.3605 16.3724C17.254 14.8543 17.1872 13.3292 17.0509 11.8148C16.8906 10.0895 16.6752 8.23163 16.4883 6.50456C16.495 6.52019 16.5161 6.55433 16.5468 6.57575C16.5714 6.59485 16.5989 6.60585 16.6145 6.60961L16.6243 6.61192H16.6284C16.6284 6.61192 16.6298 6.61279 16.6304 6.61279C16.6318 6.61279 16.6336 6.61279 16.633 6.61279C16.6324 6.61279 16.635 6.61279 16.6292 6.61279C16.5783 6.61221 16.4 6.61337 16.3445 6.61279H4.18929V6.6125Z"/>
20949            <path d="M6.08301 8.78064C6.1788 7.5189 6.20658 6.21405 6.58539 4.98907C7.15432 3.11007 8.4421 2.11631 10.414 2.12673C13.8001 2.13338 14.5031 4.87997 14.6721 7.71395C14.6964 8.07453 14.7158 8.43453 14.745 8.78035L13.5874 8.77485C13.6172 8.46057 13.6575 8.02649 13.6754 7.71858C13.801 5.83351 13.5976 3.34129 11.3988 2.81605C10.7575 2.6676 10.0702 2.6676 9.42892 2.81605C7.61503 3.24811 7.15143 5.0374 7.12683 6.6872C7.11121 7.36929 7.17545 8.09132 7.24056 8.77485L6.08301 8.78035V8.78064Z"/>
20950          </svg>
20951        </button><div class="bp-card__quick-add">
20952
20953<quick-add-component
20954  class="quick-add color-scheme-1 "
20955  ref="quickAdd"
20956  data-product-title="Metallic Zebra Printed Dress Tan Multi"
20957  data-quick-add-button="choose"
20958  data-product-options-count="2"
20959>
20960  <product-form-component
20961    data-section-id="bp-card"
20962    data-product-id="15399681360038"
20963    on:submit="/handleSubmit"
20964    class="quick-add__product-form-component"
20965  >
20966    <div
20967      class="visually-hidden"
20968      aria-live="assertive"
20969      role="status"
20970      aria-atomic="true"
20971      ref="liveRegion"
20972    ></div><form method="post" action="/cart/add" id="QuickAdd-ProductForm-15399681360038-" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" novalidate="novalidate" data-type="add-to-cart-form"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /><input
20973        type="hidden"
20974        name="id"
20975        ref="variantId"
20976        value="56779670782118"
20977        
20978      >
20979      <input
20980        type="hidden"
20981        name="quantity"
20982        value="1"
20983      >
20984      
20985      <add-to-cart-component
20986  ref="addToCartButtonContainer"
20987  data-product-variant-media="//www.bostonproper.com/cdn/shop/files/2DO0590_SET.jpg?v=1791009160&width=100"
20988  data-add-to-cart-animation="true"
20989>
20990  <button
20991    
20992    type="submit"
20993    name="add"
20994    ref="addToCartButton"
20995    on:click="/handleClick"
20996    class="button button quick-add__button quick-add__button--add add-to-cart-button"
20997    
20998    
20999  >
21000    <span
21001      class="add-to-cart-text"
21002    >
21003      
21004        <span
21005          aria-hidden="true"
21006          class="svg-wrapper add-to-cart-icon"
21007        ><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="var(--icon-stroke-width)" d="M16.608 9.421V6.906H3.392v8.016c0 .567.224 1.112.624 1.513.4.402.941.627 1.506.627H8.63M8.818 3h2.333c.618 0 1.212.247 1.649.686a2.35 2.35 0 0 1 .683 1.658v1.562H6.486V5.344c0-.622.246-1.218.683-1.658A2.33 2.33 0 0 1 8.82 3"/><path stroke="currentColor" stroke-linecap="round" stroke-width="var(--icon-stroke-width)" d="M14.608 12.563v5m2.5-2.5h-5"/></svg>
21008</span>
21009      
21010      <span class="add-to-cart-text__content is-visually-hidden-mobile">
21011        <span>
21012          <span>Add</span>
21013        </span>
21014      </span>
21015    </span>
21016    
21017    <span class="add-to-cart__added">
21018      <span class="svg-wrapper add-to-cart__added-icon"><svg aria-hidden="true" class="checkmark-burst" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
21019  <g class="check">
21020    <circle class="ring" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
21021    <path class="tick" d="M9 12.75L11.25 15L15 9.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
21022  </g>
21023  <g class="burst">
21024    <g style="--index: 0;">
21025      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21026    </g>
21027    <g style="--index: 1;">
21028      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21029    </g>
21030    <g style="--index: 2;">
21031      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21032    </g>
21033    <g style="--index: 3;">
21034      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21035    </g>
21036    <g style="--index: 4;">
21037      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21038    </g>
21039    <g style="--index: 5;">
21040      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21041    </g>
21042    <g style="--index: 6;">
21043      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21044    </g>
21045    <g style="--index: 7;">
21046      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21047    </g>
21048  </g>
21049</svg>
21050</span>
21051    </span>
21052  </button>
21053</add-to-cart-component>
21054
21055
21056      <button
21057        class="button quick-add__button quick-add__button--choose add-to-cart-button"
21058        
21059        type="button"
21060        name="add"
21061        on:click="quick-add-component/handleClick"
21062      >
21063        <span
21064          class="add-to-cart-text"
21065        >
21066          
21067          <span
21068            aria-hidden="true"
21069            class="svg-wrapper add-to-cart-icon"
21070          ><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="var(--icon-stroke-width)" d="M16.608 9.421V6.906H3.392v8.016c0 .567.224 1.112.624 1.513.4.402.941.627 1.506.627H8.63M8.818 3h2.333c.618 0 1.212.247 1.649.686a2.35 2.35 0 0 1 .683 1.658v1.562H6.486V5.344c0-.622.246-1.218.683-1.658A2.33 2.33 0 0 1 8.82 3"/><path stroke="currentColor" stroke-linecap="round" stroke-width="var(--icon-stroke-width)" d="M14.608 12.563v5m2.5-2.5h-5"/></svg>
21071</span>
21072          <span class="add-to-cart-text__content is-visually-hidden-mobile">
21073            <span>
21074              
21075              <span>
21076                Choose
21077              </span>
21078            </span>
21079          </span>
21080        </span>
21081      </button><input type="hidden" name="product-id" value="15399681360038" /></form></product-form-component>
21082</quick-add-component>
21083
21084
21085
21086</div></div>
21087
21088    <div class="bp-card__body"><h3 class="bp-card__title">
21089        <a href="/products/metallic-zebra-printed-dress-tan-multi">Metallic Zebra Printed Dress</a>
21090      </h3>
21091
21092      <div class="bp-card__price-row"><span class="bp-card__price">$180</span>
21093        <s class="bp-card__compare" hidden></s></div></div>
21094  </article>
21095</product-card>
21096
21097        </li>
21098      
21099        <li
21100          class="predictive-search-results__card predictive-search-results__card--product"
21101          ref="resultsItems[]"
21102        >
21103          <product-card class="bp-card-host">
21104  <article
21105    class="bp-card"
21106    data-product-id="15399680114854"
21107    data-product-url="/products/sam-edelman-fur-lace-up-bootie-tan"
21108    data-bp-card-secondary-hover="true"
21109    data-bp-card-qv-dest="drawer"
21110    data-bp-card-qv-vis-d="hover"
21111    data-bp-card-qv-vis-m="shown"
21112    data-bp-card-qb-style="button"
21113    data-bp-track-product='{    "id":          15399680114854,    "title":       "Sam Edelman Fur Lace Up Bootie Tan",    "vendor":      "Sam Edelman",    "handle":      "sam-edelman-fur-lace-up-bootie-tan",    "url":         "\/products\/sam-edelman-fur-lace-up-bootie-tan",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO5680_SET.jpg?v=1791009185\u0026width=720",    "category":    "Shoes",    "product_type":null,    "selected_variant": {      "id":               56779666161830,      "sku":              "2DO5680060",      "price":            180.0,      "compare_at_price": 180.0,      "option1":          "Tan",      "option2":          "6.0",      "product_id":       15399680114854,      "available":          true,      "inventory_quantity": 13    }  }'
21114  >
21115    <div class="bp-card__media">
21116      <a class="bp-card__media-link" href="/products/sam-edelman-fur-lace-up-bootie-tan" aria-label="Sam Edelman Fur Lace Up Bootie Tan" ref="productCardLink"><img
21117            class="bp-card__image bp-card__image--primary"
21118            src="//www.bostonproper.com/cdn/shop/files/2DO5680_SET.jpg?v=1791009185&width=720"
21119            srcset="//www.bostonproper.com/cdn/shop/files/2DO5680_SET.jpg?v=1791009185&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DO5680_SET.jpg?v=1791009185&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DO5680_SET.jpg?v=1791009185&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DO5680_SET.jpg?v=1791009185&width=1080 1080w"
21120            sizes="(min-width: 1024px) 25vw, 50vw"
21121            width="1639"
21122            height="2048"
21123            alt="Sam Edelman Fur Lace Up Bootie Tan"
21124            loading="lazy"
21125            data-bp-card-image-primary
21126          ><img
21127            class="bp-card__image bp-card__image--secondary"
21128            src="//www.bostonproper.com/cdn/shop/files/2_811cc34e-278e-4bea-a759-24085c37ff4f.jpg?v=1791009185&width=720"
21129            srcset="//www.bostonproper.com/cdn/shop/files/2_811cc34e-278e-4bea-a759-24085c37ff4f.jpg?v=1791009185&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_811cc34e-278e-4bea-a759-24085c37ff4f.jpg?v=1791009185&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_811cc34e-278e-4bea-a759-24085c37ff4f.jpg?v=1791009185&width=720 720w"
21130            sizes="(min-width: 1024px) 25vw, 50vw"
21131            width="1639"
21132            height="2048"
21133            alt=""
21134            loading="lazy"
21135            aria-hidden="true"
21136            data-bp-card-image-secondary
21137          ></a><div class="bp-card__badges" data-bp-card-badges></div><button
21138          type="button"
21139          class="bp-card__quick"
21140          aria-label="Quick add Sam Edelman Fur Lace Up Bootie Tan"
21141          data-product-id="15399680114854"
21142          data-bp-card-qv-trigger
21143        >
21144          <svg viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
21145            <path d="M4.18929 5.74434H16.5343H16.6292L16.6729 5.74549C16.9007 5.75099 17.1328 5.87803 17.2448 6.08089C17.3145 6.20157 17.3382 6.30372 17.3547 6.43048C17.6354 9.18806 17.9008 11.996 18.3051 14.7356C18.3771 15.2467 18.4466 15.758 18.5137 16.2697C18.5163 16.2917 18.5195 16.336 18.5207 16.3582C18.5378 16.6193 18.4156 16.9263 18.1508 17.0687C17.9651 17.1752 17.7807 17.1763 17.5845 17.1755C16.1978 17.1755 4.69428 17.1755 3.34023 17.1755C3.20422 17.1726 3.01496 17.1862 2.86505 17.1451C2.45036 17.0406 2.25213 16.656 2.31666 16.2445C2.41071 15.5271 2.58579 14.2489 2.68621 13.5185C2.95476 11.5399 3.15849 9.46674 3.35962 7.47459C3.37582 7.3571 3.44296 6.63739 3.45714 6.52887L3.46698 6.43424L3.46814 6.42237C3.46814 6.41948 3.46901 6.4134 3.47045 6.40559C3.5156 6.02417 3.79254 5.74
21145028 4.18929 5.74434ZM4.18929 6.6125C4.2136 6.6125 4.24804 6.59601 4.27872 6.57343C4.30302 6.55491 4.3201 6.53089 4.32704 6.51845C4.33457 6.50601 4.33486 6.50138 4.33399 6.50427C4.33341 6.50803 4.33225 6.51353 4.33138 6.51758C4.33138 6.51758 4.33081 6.51932 4.33052 6.52424L4.32936 6.5361L4.31923 6.63044C4.132 8.4151 3.9054 10.3181 3.74624 12.1016C3.63685 13.4481 3.56103 15.0256 3.46727 16.3753L3.46582 16.3915V16.3961C3.46582 16.3961 3.46611 16.3973 3.4664 16.3915C3.4664 16.3872 3.4664 16.375 3.46351 16.3588C3.45396 16.2908 3.41721 16.2161 3.3602 16.1507C3.29306 16.0798 3.20422 16.0246 3.12319 16.0162C3.11856 16.0162 3.13361 16.0173 3.15647 16.0176C4.67199 16.0182 16.0117 16.0176 17.5848 16.0176H17.6719C17.6823 16.017 17.6916 16.0168 17.6962 16.0165C17.7014 16.0162 17.7034 16.0159 17.6991 16.0162C17.5752 16.0286 17.4268 16.1591 17.3857 16.2795C17.3576 16.3556 17.3617 16.3788 17.362 16.3941C17.362 16.3921 17.362 16.393 17.362 16.3886L17.3605 16.3724C17.254 14.8543 17.1872 13.3292 17.0509 11.8148C16.8906 10.0895 16.6752 8.23163 16.4883 6.50456C16.495 6.52019 16.5161 6.55433 16.5468 6.57575C16.5714 6.59485 16.5989 6.60585 16.6145 6.60961L16.6243 6.61192H16.6284C16.6284 6.61192 16.6298 6.61279 16.6304 6.61279C16.6318 6.61279 16.6336 6.61279 16.633 6.61279C16.6324 6.61279 16.635 6.61279 16.6292 6.61279C16.5783 6.61221 16.4 6.61337 16.3445 6.61279H4.18929V6.6125Z"/>
21146            <path d="M6.08301 8.78064C6.1788 7.5189 6.20658 6.21405 6.58539 4.98907C7.15432 3.11007 8.4421 2.11631 10.414 2.12673C13.8001 2.13338 14.5031 4.87997 14.6721 7.71395C14.6964 8.07453 14.7158 8.43453 14.745 8.78035L13.5874 8.77485C13.6172 8.46057 13.6575 8.02649 13.6754 7.71858C13.801 5.83351 13.5976 3.34129 11.3988 2.81605C10.7575 2.6676 10.0702 2.6676 9.42892 2.81605C7.61503 3.24811 7.15143 5.0374 7.12683 6.6872C7.11121 7.36929 7.17545 8.09132 7.24056 8.77485L6.08301 8.78035V8.78064Z"/>
21147          </svg>
21148        </button><div class="bp-card__quick-add">
21149
21150<quick-add-component
21151  class="quick-add color-scheme-1 "
21152  ref="quickAdd"
21153  data-product-title="Sam Edelman Fur Lace Up Bootie Tan"
21154  data-quick-add-button="choose"
21155  data-product-options-count="2"
21156>
21157  <product-form-component
21158    data-section-id="bp-card"
21159    data-product-id="15399680114854"
21160    on:submit="/handleSubmit"
21161    class="quick-add__product-form-component"
21162  >
21163    <div
21164      class="visually-hidden"
21165      aria-live="assertive"
21166      role="status"
21167      aria-atomic="true"
21168      ref="liveRegion"
21169    ></div><form method="post" action="/cart/add" id="QuickAdd-ProductForm-15399680114854-" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" novalidate="novalidate" data-type="add-to-cart-form"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /><input
21170        type="hidden"
21171        name="id"
21172        ref="variantId"
21173        value="56779666161830"
21174        
21175      >
21176      <input
21177        type="hidden"
21178        name="quantity"
21179        value="1"
21180      >
21181      
21182      <add-to-cart-component
21183  ref="addToCartButtonContainer"
21184  data-product-variant-media="//www.bostonproper.com/cdn/shop/files/2DO5680_SET.jpg?v=1791009185&width=100"
21185  data-add-to-cart-animation="true"
21186>
21187  <button
21188    
21189    type="submit"
21190    name="add"
21191    ref="addToCartButton"
21192    on:click="/handleClick"
21193    class="button button quick-add__button quick-add__button--add add-to-cart-button"
21194    
21195    
21196  >
21197    <span
21198      class="add-to-cart-text"
21199    >
21200      
21201        <span
21202          aria-hidden="true"
21203          class="svg-wrapper add-to-cart-icon"
21204        ><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="var(--icon-stroke-width)" d="M16.608 9.421V6.906H3.392v8.016c0 .567.224 1.112.624 1.513.4.402.941.627 1.506.627H8.63M8.818 3h2.333c.618 0 1.212.247 1.649.686a2.35 2.35 0 0 1 .683 1.658v1.562H6.486V5.344c0-.622.246-1.218.683-1.658A2.33 2.33 0 0 1 8.82 3"/><path stroke="currentColor" stroke-linecap="round" stroke-width="var(--icon-stroke-width)" d="M14.608 12.563v5m2.5-2.5h-5"/></svg>
21205</span>
21206      
21207      <span class="add-to-cart-text__content is-visually-hidden-mobile">
21208        <span>
21209          <span>Add</span>
21210        </span>
21211      </span>
21212    </span>
21213    
21214    <span class="add-to-cart__added">
21215      <span class="svg-wrapper add-to-cart__added-icon"><svg aria-hidden="true" class="checkmark-burst" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
21216  <g class="check">
21217    <circle class="ring" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
21218    <path class="tick" d="M9 12.75L11.25 15L15 9.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
21219  </g>
21220  <g class="burst">
21221    <g style="--index: 0;">
21222      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21223    </g>
21224    <g style="--index: 1;">
21225      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21226    </g>
21227    <g style="--index: 2;">
21228      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21229    </g>
21230    <g style="--index: 3;">
21231      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21232    </g>
21233    <g style="--index: 4;">
21234      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21235    </g>
21236    <g style="--index: 5;">
21237      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21238    </g>
21239    <g style="--index: 6;">
21240      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21241    </g>
21242    <g style="--index: 7;">
21243      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21244    </g>
21245  </g>
21246</svg>
21247</span>
21248    </span>
21249  </button>
21250</add-to-cart-component>
21251
21252
21253      <button
21254        class="button quick-add__button quick-add__button--choose add-to-cart-button"
21255        
21256        type="button"
21257        name="add"
21258        on:click="quick-add-component/handleClick"
21259      >
21260        <span
21261          class="add-to-cart-text"
21262        >
21263          
21264          <span
21265            aria-hidden="true"
21266            class="svg-wrapper add-to-cart-icon"
21267          ><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="var(--icon-stroke-width)" d="M16.608 9.421V6.906H3.392v8.016c0 .567.224 1.112.624 1.513.4.402.941.627 1.506.627H8.63M8.818 3h2.333c.618 0 1.212.247 1.649.686a2.35 2.35 0 0 1 .683 1.658v1.562H6.486V5.344c0-.622.246-1.218.683-1.658A2.33 2.33 0 0 1 8.82 3"/><path stroke="currentColor" stroke-linecap="round" stroke-width="var(--icon-stroke-width)" d="M14.608 12.563v5m2.5-2.5h-5"/></svg>
21268</span>
21269          <span class="add-to-cart-text__content is-visually-hidden-mobile">
21270            <span>
21271              
21272              <span>
21273                Choose
21274              </span>
21275            </span>
21276          </span>
21277        </span>
21278      </button><input type="hidden" name="product-id" value="15399680114854" /></form></product-form-component>
21279</quick-add-component>
21280
21281
21282
21283</div></div>
21284
21285    <div class="bp-card__body"><h3 class="bp-card__title">
21286        <a href="/products/sam-edelman-fur-lace-up-bootie-tan">Sam Edelman Fur Lace Up Bootie</a>
21287      </h3>
21288
21289      <div class="bp-card__price-row"><span class="bp-card__price">$180</span>
21290        <s class="bp-card__compare" hidden></s></div></div>
21291  </article>
21292</product-card>
21293
21294        </li>
21295      
21296        <li
21297          class="predictive-search-results__card predictive-search-results__card--product"
21298          ref="resultsItems[]"
21299        >
21300          <product-card class="bp-card-host">
21301  <article
21302    class="bp-card"
21303    data-product-id="15399680082086"
21304    data-product-url="/products/ultimate-velvet-double-breasted-shaped-blazer-black"
21305    data-bp-card-secondary-hover="true"
21306    data-bp-card-qv-dest="drawer"
21307    data-bp-card-qv-vis-d="hover"
21308    data-bp-card-qv-vis-m="shown"
21309    data-bp-card-qb-style="button"
21310    data-bp-track-product='{    "id":          15399680082086,    "title":       "Ultimate Velvet Double Breasted Shaped Blazer Black",    "vendor":      "Boston Proper",    "handle":      "ultimate-velvet-double-breasted-shaped-blazer-black",    "url":         "\/products\/ultimate-velvet-double-breasted-shaped-blazer-black",    "image":       "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DP1920_SET.jpg?v=1791009211\u0026width=720",    "category":    "Jackets",    "product_type":null,    "selected_variant": {      "id":               56779665801382,      "sku":              "2DP1920002",      "price":            150.0,      "compare_at_price": 150.0,      "option1":          "Black",      "option2":          "2",      "product_id":       15399680082086,      "available":          true,      "inventory_quantity": 21    }  }'
21311  >
21312    <div class="bp-card__media">
21313      <a class="bp-card__media-link" href="/products/ultimate-velvet-double-breasted-shaped-blazer-black" aria-label="Ultimate Velvet Double Breasted Shaped Blazer Black" ref="productCardLink"><img
21314            class="bp-card__image bp-card__image--primary"
21315            src="//www.bostonproper.com/cdn/shop/files/2DP1920_SET.jpg?v=1791009211&width=720"
21316            srcset="//www.bostonproper.com/cdn/shop/files/2DP1920_SET.jpg?v=1791009211&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DP1920_SET.jpg?v=1791009211&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DP1920_SET.jpg?v=1791009211&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DP1920_SET.jpg?v=1791009211&width=1080 1080w"
21317            sizes="(min-width: 1024px) 25vw, 50vw"
21318            width="1639"
21319            height="2048"
21320            alt="Ultimate Velvet Double Breasted Shaped Blazer Black"
21321            loading="lazy"
21322            data-bp-card-image-primary
21323          ><img
21324            class="bp-card__image bp-card__image--secondary"
21325            src="//www.bostonproper.com/cdn/shop/files/2_1560b9bf-904f-46e5-b2c8-2e27b8946935.jpg?v=1791009211&width=720"
21326            srcset="//www.bostonproper.com/cdn/shop/files/2_1560b9bf-904f-46e5-b2c8-2e27b8946935.jpg?v=1791009211&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_1560b9bf-904f-46e5-b2c8-2e27b8946935.jpg?v=1791009211&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_1560b9bf-904f-46e5-b2c8-2e27b8946935.jpg?v=1791009211&width=720 720w"
21327            sizes="(min-width: 1024px) 25vw, 50vw"
21328            width="1639"
21329            height="2048"
21330            alt=""
21331            loading="lazy"
21332            aria-hidden="true"
21333            data-bp-card-image-secondary
21334          ></a><div class="bp-card__badges" data-bp-card-badges></div><button
21335          type="button"
21336          class="bp-card__quick"
21337          aria-label="Quick add Ultimate Velvet Double Breasted Shaped Blazer Black"
21338          data-product-id="15399680082086"
21339          data-bp-card-qv-trigger
21340        >
21341          <svg viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
21342            <path d="M4.18929 5.74434H16.5343H16.6292L16.6729 5.74549C16.9007 5.75099 17.1328 5.87803 17.2448 6.08089C17.3145 6.20157 17.3382 6.30372 17.3547 6.43048C17.6354 9.18806 17.9008 11.996 18.3051 14.7356C18.3771 15.2467 18.4466 15.758 18.5137 16.2697C18.5163 16.2917 18.5195 16.336 18.5207 16.3582C18.5378 16.6193 18.4156 16.9263 18.1508 17.0687C17.9651 17.1752 17.7807 17.1763 17.5845 17.1755C16.1978 17.1755 4.69428 17.1755 3.34023 17.1755C3.20422 17.1726 3.01496 17.1862 2.86505 17.1451C2.45036 17.0406 2.25213 16.656 2.31666 16.2445C2.41071 15.5271 2.58579 14.2489 2.68621 13.5185C2.95476 11.5399 3.15849 9.46674 3.35962 7.47459C3.37582 7.3571 3.44296 6.63739 3.45714 6.52887L3.46698 6.43424L3.46814 6.42237C3.46814 6.41948 3.46901 6.4134 3.47045 6.40559C3.5156 6.02417 3.79254 5.74
21342028 4.18929 5.74434ZM4.18929 6.6125C4.2136 6.6125 4.24804 6.59601 4.27872 6.57343C4.30302 6.55491 4.3201 6.53089 4.32704 6.51845C4.33457 6.50601 4.33486 6.50138 4.33399 6.50427C4.33341 6.50803 4.33225 6.51353 4.33138 6.51758C4.33138 6.51758 4.33081 6.51932 4.33052 6.52424L4.32936 6.5361L4.31923 6.63044C4.132 8.4151 3.9054 10.3181 3.74624 12.1016C3.63685 13.4481 3.56103 15.0256 3.46727 16.3753L3.46582 16.3915V16.3961C3.46582 16.3961 3.46611 16.3973 3.4664 16.3915C3.4664 16.3872 3.4664 16.375 3.46351 16.3588C3.45396 16.2908 3.41721 16.2161 3.3602 16.1507C3.29306 16.0798 3.20422 16.0246 3.12319 16.0162C3.11856 16.0162 3.13361 16.0173 3.15647 16.0176C4.67199 16.0182 16.0117 16.0176 17.5848 16.0176H17.6719C17.6823 16.017 17.6916 16.0168 17.6962 16.0165C17.7014 16.0162 17.7034 16.0159 17.6991 16.0162C17.5752 16.0286 17.4268 16.1591 17.3857 16.2795C17.3576 16.3556 17.3617 16.3788 17.362 16.3941C17.362 16.3921 17.362 16.393 17.362 16.3886L17.3605 16.3724C17.254 14.8543 17.1872 13.3292 17.0509 11.8148C16.8906 10.0895 16.6752 8.23163 16.4883 6.50456C16.495 6.52019 16.5161 6.55433 16.5468 6.57575C16.5714 6.59485 16.5989 6.60585 16.6145 6.60961L16.6243 6.61192H16.6284C16.6284 6.61192 16.6298 6.61279 16.6304 6.61279C16.6318 6.61279 16.6336 6.61279 16.633 6.61279C16.6324 6.61279 16.635 6.61279 16.6292 6.61279C16.5783 6.61221 16.4 6.61337 16.3445 6.61279H4.18929V6.6125Z"/>
21343            <path d="M6.08301 8.78064C6.1788 7.5189 6.20658 6.21405 6.58539 4.98907C7.15432 3.11007 8.4421 2.11631 10.414 2.12673C13.8001 2.13338 14.5031 4.87997 14.6721 7.71395C14.6964 8.07453 14.7158 8.43453 14.745 8.78035L13.5874 8.77485C13.6172 8.46057 13.6575 8.02649 13.6754 7.71858C13.801 5.83351 13.5976 3.34129 11.3988 2.81605C10.7575 2.6676 10.0702 2.6676 9.42892 2.81605C7.61503 3.24811 7.15143 5.0374 7.12683 6.6872C7.11121 7.36929 7.17545 8.09132 7.24056 8.77485L6.08301 8.78035V8.78064Z"/>
21344          </svg>
21345        </button><div class="bp-card__quick-add">
21346
21347<quick-add-component
21348  class="quick-add color-scheme-1 "
21349  ref="quickAdd"
21350  data-product-title="Ultimate Velvet Double Breasted Shaped Blazer Black"
21351  data-quick-add-button="choose"
21352  data-product-options-count="2"
21353>
21354  <product-form-component
21355    data-section-id="bp-card"
21356    data-product-id="15399680082086"
21357    on:submit="/handleSubmit"
21358    class="quick-add__product-form-component"
21359  >
21360    <div
21361      class="visually-hidden"
21362      aria-live="assertive"
21363      role="status"
21364      aria-atomic="true"
21365      ref="liveRegion"
21366    ></div><form method="post" action="/cart/add" id="QuickAdd-ProductForm-15399680082086-" accept-charset="UTF-8" class="shopify-product-form" enctype="multipart/form-data" novalidate="novalidate" data-type="add-to-cart-form"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="✓" /><input
21367        type="hidden"
21368        name="id"
21369        ref="variantId"
21370        value="56779665801382"
21371        
21372      >
21373      <input
21374        type="hidden"
21375        name="quantity"
21376        value="1"
21377      >
21378      
21379      <add-to-cart-component
21380  ref="addToCartButtonContainer"
21381  data-product-variant-media="//www.bostonproper.com/cdn/shop/files/2DP1920_SET.jpg?v=1791009211&width=100"
21382  data-add-to-cart-animation="true"
21383>
21384  <button
21385    
21386    type="submit"
21387    name="add"
21388    ref="addToCartButton"
21389    on:click="/handleClick"
21390    class="button button quick-add__button quick-add__button--add add-to-cart-button"
21391    
21392    
21393  >
21394    <span
21395      class="add-to-cart-text"
21396    >
21397      
21398        <span
21399          aria-hidden="true"
21400          class="svg-wrapper add-to-cart-icon"
21401        ><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="var(--icon-stroke-width)" d="M16.608 9.421V6.906H3.392v8.016c0 .567.224 1.112.624 1.513.4.402.941.627 1.506.627H8.63M8.818 3h2.333c.618 0 1.212.247 1.649.686a2.35 2.35 0 0 1 .683 1.658v1.562H6.486V5.344c0-.622.246-1.218.683-1.658A2.33 2.33 0 0 1 8.82 3"/><path stroke="currentColor" stroke-linecap="round" stroke-width="var(--icon-stroke-width)" d="M14.608 12.563v5m2.5-2.5h-5"/></svg>
21402</span>
21403      
21404      <span class="add-to-cart-text__content is-visually-hidden-mobile">
21405        <span>
21406          <span>Add</span>
21407        </span>
21408      </span>
21409    </span>
21410    
21411    <span class="add-to-cart__added">
21412      <span class="svg-wrapper add-to-cart__added-icon"><svg aria-hidden="true" class="checkmark-burst" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
21413  <g class="check">
21414    <circle class="ring" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
21415    <path class="tick" d="M9 12.75L11.25 15L15 9.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
21416  </g>
21417  <g class="burst">
21418    <g style="--index: 0;">
21419      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21420    </g>
21421    <g style="--index: 1;">
21422      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21423    </g>
21424    <g style="--index: 2;">
21425      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21426    </g>
21427    <g style="--index: 3;">
21428      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21429    </g>
21430    <g style="--index: 4;">
21431      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21432    </g>
21433    <g style="--index: 5;">
21434      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21435    </g>
21436    <g style="--index: 6;">
21437      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21438    </g>
21439    <g style="--index: 7;">
21440      <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/>
21441    </g>
21442  </g>
21443</svg>
21444</span>
21445    </span>
21446  </button>
21447</add-to-cart-component>
21448
21449
21450      <button
21451        class="button quick-add__button quick-add__button--choose add-to-cart-button"
21452        
21453        type="button"
21454        name="add"
21455        on:click="quick-add-component/handleClick"
21456      >
21457        <span
21458          class="add-to-cart-text"
21459        >
21460          
21461          <span
21462            aria-hidden="true"
21463            class="svg-wrapper add-to-cart-icon"
21464          ><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="var(--icon-stroke-width)" d="M16.608 9.421V6.906H3.392v8.016c0 .567.224 1.112.624 1.513.4.402.941.627 1.506.627H8.63M8.818 3h2.333c.618 0 1.212.247 1.649.686a2.35 2.35 0 0 1 .683 1.658v1.562H6.486V5.344c0-.622.246-1.218.683-1.658A2.33 2.33 0 0 1 8.82 3"/><path stroke="currentColor" stroke-linecap="round" stroke-width="var(--icon-stroke-width)" d="M14.608 12.563v5m2.5-2.5h-5"/></svg>
21465</span>
21466          <span class="add-to-cart-text__content is-visually-hidden-mobile">
21467            <span>
21468              
21469              <span>
21470                Choose
21471              </span>
21472            </span>
21473          </span>
21474        </span>
21475      </button><input type="hidden" name="product-id" value="15399680082086" /></form></product-form-component>
21476</quick-add-component>
21477
21478
21479
21480</div></div>
21481
21482    <div class="bp-card__body"><h3 class="bp-card__title">
21483        <a href="/products/ultimate-velvet-double-breasted-shaped-blazer-black">Ultimate Velvet Double Breasted Shaped Blazer</a>
21484      </h3>
21485
21486      <div class="bp-card__price-row"><span class="bp-card__price">$150</span>
21487        <s class="bp-card__compare" hidden></s></div></div>
21488  </article>
21489</product-card>
21490
21491        </li>
21492      
21493    </ul>
21494  
21495</div>
21496
21497        
21498      
21499    </div>
21500  
21501</div>
21502</div>
21503
21504          <div class="predictive-search-form__footer">
21505            <button
21506              class="button predictive-search__search-button"
21507              ref="viewAllButton"
21508            >
21509              View all
21510            </button>
21511          </div>
21512        </div>
21513      </form>
21514    </predictive-search-component>
21515  </dialog>
21516</dialog-component>
21517
21518
21519
21520<bp-search-drawer
21521  class="bp-sd"
21522  aria-hidden="true"
21523  inert
21524  data-search-url="/search"
21525  data-br-enabled="1"
21526>
21527  <div class="bp-sd__panel">
21528    <form class="bp-sd__form" action="/search" method="get">
21529      <input type="hidden" name="options[prefix]" value="last">
21530
21531      <div class="bp-sd__header">
21532        <span class="bp-sd__icon svg-wrapper"><svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
21533<path d="M30.6967 19.7055C30.7183 23.8405 27.932 27.3926 24.0949 28.7508C17.6703 31.1232 10.0267 26.8687 10 19.7055C10.0272 12.5414 17.6703 8.28779 24.0953 10.6602C27.932 12.0184 30.7187 15.5704 30.6967 19.7055ZM28.5408 19.7055C28.5477 16.9739 27.3344 14.2088 25.1509 12.5164C22.4003 10.326 18.2959 10.3256 15.5454 12.5164C13.3619 14.2088 12.1486 16.9735 12.1555 19.7055C12.1486 22.437 13.3619 25.2022 15.5454 26.8946C18.2959 29.085 22.4003 29.0854 25.1509 26.8946C27.3344 25.2022 28.5477 22.4374 28.5408 19.7055Z" fill="currentColor"/>
21534<path d="M33.1718 33.9998C31.5945 32.7679 30.2255 31.2984 28.9126 29.7966C28.4814 29.2934 28.0606 28.7816 27.6699 28.2439L28.9794 27.1216C29.4511 27.5898 29.8927 28.084 30.3238 28.5872C31.3971 29.854 32.4207 31.1661 33.3132 32.5696C33.4917 32.8528 33.6659 33.1396 33.8263 33.4388L33.1714 34.0002L33.1718 33.9998Z" fill="currentColor"/>
21535</svg>
21536</span>
21537        <input
21538          type="search"
21539          name="q"
21540          id="bp-sd-input"
21541          class="bp-sd__input"
21542          placeholder="Search"
21543          autocomplete="off"
21544          aria-label="Search"
21545          role="combobox"
21546          aria-expanded="false"
21547          aria-controls="bp-sp-products"
21548          aria-autocomplete="list"
21549        >
21550        <button type="button" class="bp-sd__clear" hidden>Clear</button>
21551      </div><p class="visually-hidden" role="status" aria-live="polite" data-bp-search-status></p><div class="bp-sp">
21552  <div class="bp-sp__body">
21553
21554    <aside class="bp-sp__sidebar" data-br-sidebar>
21555      <div class="bp-sp__group">
21556        <h3 class="bp-sp__group-title">Suggestions</h3><ul class="bp-sp__links" role="list">
21557          <li><a class="bp-sp__link" href="/search?q=dresses" data-bp-search="dresses">dresses</a></li>
21558          <li><a class="bp-sp__link" href="/search?q=swimwear" data-bp-search="swimwear">swimwear</a></li>
21559          <li><a class="bp-sp__link" href="/search?q=tops" data-bp-search="tops">tops</a></li>
21560          <li><a class="bp-sp__link" href="/search?q=summer+dresses" data-bp-search="summer dresses">summer dresses</a></li>
21561        </ul>
21562      </div>
21563
21564      <div class="bp-sp__group">
21565        <h3 class="bp-sp__group-title">Category</h3>
21566        <ul class="bp-sp__links" role="list">
21567          <li><a class="bp-sp__link" href="/collections/dresses">Dresses</a></li>
21568          <li><a class="bp-sp__link" href="/collections/swimwear">Swimwear</a></li>
21569          <li><a class="bp-sp__link" href="/collections/tops">Tops</a></li>
21570          <li><a class="bp-sp__link" href="/collections/sale">Sale</a></li>
21571          <li><a class="bp-sp__link" href="/collections/new-arrivals">New Arrivals</a></li>
21572        </ul>
21573      </div>
21574    </aside>
21575
21576    <div class="bp-sp__products" id="bp-sp-products" data-br-products data-bp-track-list-name="Search Results" hidden></div>
21577
21578  </div>
21579</div>
21580</form>
21581  </div>
21582</bp-search-drawer>
21583
21584
21585
21586
21587
21588
21589    
21590      <div id="shopify-section-bp-quick-drawer" class="shopify-section">
21591
21592
21593
21594
21595<script
21596  src="//www.bostonproper.com/cdn/shop/t/1521/assets/gift-card-recipient-form.js?v=129634859299628245901790713714"
21597  type="module"
21598  fetchpriority="low"
21599></script>
21599
21600
21601<quick-add-dialog id="quick-add-dialog">
21602  <dialog
21603    class="quick-add-modal bp-qd dialog-modal color-scheme-1"
21604    ref="dialog"
21605    scroll-lock
21606    aria-label="Quick view"
21607  >
21608    <button
21609      ref="closeButton"
21610      on:click="/closeDialog"
21611      class="button button-unstyled close-button quick-add-modal__close bp-qd__close"
21612      aria-label="Close dialog"
21613    ><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
21614  <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
21615  <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/>
21616</svg>
21617</button>
21618
21619    <div class="bp-qd__layout">
21620      <aside class="bp-qd__media-slot" data-bp-qd-media-slot></aside>
21621
21622      <div class="bp-qd__main">
21623        <div
21624          id="quick-add-modal-content"
21625          class="quick-add-modal__content bp-qd__body"
21626        ></div>
21627
21628        <footer class="bp-qd__cta-slot" data-bp-qd-cta-slot><p class="bp-qd__pay-in-4" data-bp-qd-pay-in-4>
21629            Pay in full or in 4 interest-free installments with
21630            <img class="bp-qd__shop-pay-mark" src="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-shop-pay-logo.svg?v=68994295948588378181790713714" alt="Shop Pay" width="42" height="10" loading="lazy" style="width:auto;height:12px;">
21631          </p>
21632        </footer>
21633      </div>
21634    </div>
21635  </dialog>
21636</quick-add-dialog>
21637
21638
21639
21640
21641
21642
21643</div>
21644    
21645
21646
21647<script>
21648(function () {
21649  var SERVER_COLOR = "With Love BP";
21650  // Product scopes: main PDP + quick-add / quick-view drawer, so a title's
21651  // colour comes from ITS OWN product's label, not another on the page.
21652  var SCOPE_SEL = '.product-details, .product-information, #quick-add-modal-content, .quick-add-modal, .quick-add-modal__content, .bp-qd__body, dialog[open]';
21653  function colorFor(el) {
21654    var scope = el.closest(SCOPE_SEL) || document;
21655    // Use the SELECTED colour, not the label text — bp-color-siblings mutates
21656    // [data-bp-active-color] on swatch HOVER (preview), which would make us
21657    // strip the wrong colour and flash the full title back. The active swatch
21658    // only changes on real selection / in-place swap, so it's stable.
21659    var active = scope.querySelector(
21660      '.bp-colors__item.is-active[data-bp-color-name], .bp-colors__item--active[data-bp-color-name], .bp-colors__item[aria-current][data-bp-color-name]'
21661    );
21662    var sel = active && active.getAttribute('data-bp-color-name');
21663    if (sel && sel.trim()) return sel.trim();
21664    return SERVER_COLOR || '';
21665  }
21666  function strip(title, color) {
21667    if (!title || !color) return title;
21668    var c = String(color).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
21669    var re = new RegExp('\\s*[-\\u2013\\u2014]?\\s*' + c + '\\s*$', 'i');
21670    var out = String(title).replace(re, '').trim();
21671    return out || title;
21672  }
21673  function titleEls() {
21674    var sels = [
21675      '.product-information h1',
21676      '.product-details h1',
21677      '[id^="ProductInformation"] h1',
21678      '.view-product-title a',
21679      '[ref="productTitleLink"] [role="heading"]',
21680      // Quick-add / quick-view drawer main title. The drawer's controller
21681      // (sections/bp-quick-drawer.liquid wrapTitleLink) wraps the morphed
21682      // <h1> text-block in an <a href="{pdp}">, so the colour lives in
21683      // "<h1 data-bp-qd-placed><a>Everyday Hoop Gold</a></h1>". apply() skips
21684      // container elements (the h1 now has an <a> child), so target the inner
21685      // <a> leaf directly. Also match the pre-wrap <h1> (text leaf, before the
21686      // controller runs) and the un-relocated node still in #quick-add-modal-
21687      // content, so whichever timing wins gets stripped.
21688      '.bp-qd__body h1 a',
21689      '.bp-qd__body h1',
21690      '#quick-add-modal-content h1 a',
21691      '#quick-add-modal-content h1'
21692    ];
21693    var seen = [], out = [];
21694    sels.forEach(function (s) {
21695      document.querySelectorAll(s).forEach(function (el) {
21696        if (seen.indexOf(el) < 0) { seen.push(el); out.push(el); }
21697      });
21698    });
21699    return out;
21700  }
21701  function apply() {
21702    titleEls().forEach(function (t) {
21703      if (t.children && t.children.length > 0) return; // text-only leaves
21704      var color = colorFor(t);
21705      if (!color) return;
21706      if (t.getAttribute('data-bp-full-title') == null) {
21707        t.setAttribute('data-bp-full-title', (t.textContent || '').trim());
21708      }
21709      var full = t.getAttribute('data-bp-full-title') || (t.textContent || '').trim();
21710      var clean = strip(full, color);
21711      if (clean && clean !== (t.textContent || '').trim()) t.textContent = clean;
21712    });
21713  }
21714  // Reveal the PDP title once we've had a pass at stripping it. bp-fonts.liquid
21715  // hides '.product-information h1 / .product-details h1' until this attribute
21716  // is set, so the full "…Colour" title never paints before it's cleaned.
21717  // Always reveal (even if there was no colour to strip) so a plain title is
21718  // never left hidden; the CSS also has a 1.2s fail-safe reveal.
21719  function revealTitles() {
21720    document
21721      .querySelectorAll('.product-information h1, .product-details h1')
21722      .forEach(function (h) { h.setAttribute('data-bp-title-ready', ''); });
21723  }
21724  function boot() {
21725    apply();
21726    revealTitles();
21727    var tries = 0;
21728    var iv = setInterval(function () { apply(); if (++tries > 24) clearInterval(iv); }, 300);
21729    if (document.body) {
21730      var obs = new MutationObserver(function () { apply(); });
21731      obs.observe(document.body, { childList: true, subtree: true, characterData: true });
21732      setTimeout(function () { obs.disconnect(); }, 10000);
21733    }
21734  }
21735  if (document.readyState !== 'loading') boot();
21736  else document.addEventListener('DOMContentLoaded', boot);
21737  // In-place colour swap / quick-view open re-render titles + labels.
21738  document.addEventListener('bp:pdp:swapped', boot);
21739  document.addEventListener('click', function (e) {
21740    if (e.target.closest && (e.target.closest('[data-bp-swatch]') || e.target.closest('[data-bp-card-qv-trigger]') || e.target.closest('.quick-add__button')))
21741      setTimeout(boot, 120);
21742  }, true);
21743})();
21744</script>
21744
21745
21746
21747    <dialog
21748    class="bp-size-chart"
21749    id="bp-size-chart-drawer"
21750    data-bp-size-chart-drawer
21751    aria-labelledby="bp-size-chart-title"
21752  >
21753    <div class="bp-size-chart__inner">
21754      <header class="bp-size-chart__head">
21755        <h2 id="bp-size-chart-title" class="bp-size-chart__title">Size Chart</h2>
21756        <button
21757          type="button"
21758          class="bp-size-chart__close"
21759          data-bp-size-chart-close
21760          aria-label="Close size chart"
21761        >
21762          <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
21763            <line x1="18" y1="6" x2="6" y2="18"/>
21764            <line x1="6" y1="6" x2="18" y2="18"/>
21765          </svg>
21766        </button>
21767      </header>
21768
21769      <div class="bp-size-chart__tabs" role="tablist" aria-label="Size guide tabs">
21770        <button
21771          type="button"
21772          class="bp-size-chart__tab is-active"
21773          role="tab"
21774          aria-selected="true"
21775          aria-controls="bp-size-chart-pane-chart"
21776          data-bp-size-chart-tab="chart"
21777        >Size Chart</button>
21778        <button
21779          type="button"
21780          class="bp-size-chart__tab"
21781          role="tab"
21782          aria-selected="false"
21783          aria-controls="bp-size-chart-pane-htm"
21784          data-bp-size-chart-tab="htm"
21785        >How to Measure</button>
21786      </div>
21787
21788      <div class="bp-size-chart__body">
21789        <section
21790          id="bp-size-chart-pane-chart"
21791          class="bp-size-chart__pane is-active"
21792          role="tabpanel"
21793          data-bp-size-chart-pane="chart"
21794        ><div style="margin: 10px 0 10px;" class="flex-measuring-text size-measuring-section modal-sizechart">
21795<p>We take the guesswork out of choosing the right size. If you are unsure of exactly which size to order, there are a few steps you can follow to help ensure the best fit.</p>
21796<ul>
21797<li>When selecting your size, it is important to note our Boston Proper sizes may differ in the sizes you wear from other brands. Use our size ranges to help determine which sizing will work best for you based on the numeric equivalents provided here and on product pages. Specifically: XXS(0), XS(2-4), S(6-8), M(10-12), L(14-16), XL(18).</li>
21798<li>We also note when an item may run small/big or if you are between sizes, with direction to order a smaller or larger size.</li>
21799<li>We offer <strong>True Fit</strong> to assist with size selection by using your measurements, shape, and what you wear in other brands to find the right Boston Proper size for you. Simply click on <u>What's My Size?</u> next to the True Fit icon below the select size options on any product page or visit the <a href="https://www.bostonproper.com/pages/true-fit" title="True Fit">True Fit</a> page.</li>
21800</ul>
21801<p>And just in case you need a different size, exchanges are always free.</p>
21802<p>For additional sizing information, please reference the charts below or contact our Customer Care team with any questions you may have.</p>
21803</div>
21804<div style="margin-top: 10px;" class="customerservice--sizecharts">
21805<div class="modal-sizechart customerservice--sizecharts">
21806<div class="flex-chart">
21807<h3>Measurements</h3>
21808<table class="table table-bordered table-size-chart">
21809<thead>
21810<tr>
21811<th colspan="2">US SIZE</th>
21812<th>BUST</th>
21813<th>WAIST</th>
21814<th>HIPS</th>
21815</tr>
21816</thead>
21817<tbody>
21818<tr>
21819<td class="sizechart-col1">XXS</td>
21820<td class="sizechart-colX">0</td>
21821<td class="sizechart-colX">32.5"</td>
21822<td class="sizechart-colX">26"</td>
21823<td class="sizechart-colX">35.5"</td>
21824</tr>
21825<tr>
21826<td class="sizechart-col1">XS</td>
21827<td class="sizechart-colX">2</td>
21828<td class="sizechart-colX">33.5"</td>
21829<td class="sizechart-colX">27"</td>
21830<td class="sizechart-colX">36.5"</td>
21831</tr>
21832<tr>
21833<td class="sizechart-col1">XS</td>
21834<td class="sizechart-colX">4</td>
21835<td class="sizechart-colX">34.5"</td>
21836<td class="sizechart-colX">28"</td>
21837<td class="sizechart-colX">37.5"</td>
21838</tr>
21839<tr>
21840<td class="sizechart-col1">S</td>
21841<td class="sizechart-colX">6</td>
21842<td class="sizechart-colX">35.5"</td>
21843<td class="sizechart-colX">29"</td>
21844<td class="sizechart-colX">38.5"</td>
21845</tr>
21846<tr>
21847<td class="sizechart-col1">S</td>
21848<td class="sizechart-colX">8</td>
21849<td class="sizechart-colX">36.5"</td>
21850<td class="sizechart-colX">30"</td>
21851<td class="sizechart-colX">39.5"</td>
21852</tr>
21853<tr>
21854<td class="sizechart-col1">M</td>
21855<td class="sizechart-colX">10</td>
21856<td class="sizechart-colX">37.5"</td>
21857<td class="sizechart-colX">31"</td>
21858<td class="sizechart-colX">40.5"</td>
21859</tr>
21860<tr>
21861<td class="sizechart-col1">M</td>
21862<td class="sizechart-colX">12</td>
21863<td class="sizechart-colX">39"</td>
21864<td class="sizechart-colX">32.5"</td>
21865<td class="sizechart-colX">42"</td>
21866</tr>
21867<tr>
21868<td class="sizechart-col1">L</td>
21869<td class="sizechart-colX">14</td>
21870<td class="sizechart-colX">40.5"</td>
21871<td class="sizechart-colX">34"</td>
21872<td class="sizechart-colX">43.5"</td>
21873</tr>
21874<tr>
21875<td class="sizechart-col1">L</td>
21876<td class="sizechart-colX">16</td>
21877<td class="sizechart-colX">42"</td>
21878<td class="sizechart-colX">35.5"</td>
21879<td class="sizechart-colX">45"</td>
21880</tr>
21881<tr>
21882<td class="sizechart-col1">XL</td>
21883<td class="sizechart-colX">18</td>
21884<td class="sizechart-colX">44"</td>
21885<td class="sizechart-colX">37.5"</td>
21886<td class="sizechart-colX">47"</td>
21887</tr>
21888</tbody>
21889</table>
21890</div>
21891<div class="flex-chart">
21892<h3>Dress &amp; Skirt Lengths</h3>
21893<table class="table table-bordered table-size-chart">
21894<thead>
21895<tr>
21896<th>DESCRIPTION</th>
21897<th>DRESS</th>
21898<th>SKIRT</th>
21899</tr>
21900</thead>
21901<tbody>
21902<tr>
21903<td class="sizechart-colX">Mid thigh</td>
21904<td class="sizechart-colX">35"</td>
21905<td class="sizechart-colX">18"</td>
21906</tr>
21907<tr>
21908<td class="sizechart-colX">Above the knee</td>
21909<td class="sizechart-colX">37"</td>
21910<td class="sizechart-colX">20"</td>
21911</tr>
21912<tr>
21913<td class="sizechart-colX">At the knee</td>
21914<td class="sizechart-colX">38" -39"</td>
21915<td class="sizechart-colX">22"</td>
21916</tr>
21917<tr>
21918<td class="sizechart-colX">Below the knee</td>
21919<td class="sizechart-colX">40" - 41"</td>
21920<td class="sizechart-colX">23" - 24"</td>
21921</tr>
21922<tr>
21923<td class="sizechart-colX">Midi</td>
21924<td class="sizechart-colX">44" - 45"</td>
21925<td class="sizechart-colX">28"</td>
21926</tr>
21927<tr>
21928<td class="sizechart-colX">Ankle</td>
21929<td class="sizechart-colX">54" - 55"</td>
21930<td class="sizechart-colX">38"</td>
21931</tr>
21932<tr>
21933<td class="sizechart-colX">Maxi</td>
21934<td class="sizechart-colX">57" - 58"</td>
21935<td class="sizechart-colX">40"</td>
21936</tr>
21937</tbody>
21938</table>
21939</div>
21940</div>
21941<div class="modal-measuring" style="display: none;">
21942<div>
21943<div style="margin-top: 0px;" class="flex-measuring-text">
21944<h4>Measuring For The Perfect Size</h4>
21945<p class="flex-measuring-text-center">Wearing appropriate undergarments, place the measuring tape comfortably around the bust, waist and hips. To determine the most accurate measurements, ensure that the tape is placed evenly around and parallel to the floor.</p>
21946</div>
21947<div class="flex-measuring">
21948<div class="customerservice--sizecharts-model"><img src="https://media.bostonproper.com/i/bostonproper/silhouette_v2-01"></div>
21949<div>
21950<ul>
21951<li>
21952<strong>Bust:</strong> Measure around the fullest part of the bust, arms relaxed at your side.</li>
21953<li>
21954<strong>Waist:</strong> Measure around waist smallest point with tape slightly loosened for c
21954omfort.</li>
21955<li>
21956<strong>Hips:</strong> With feet together, measure around the fullest part of hip and rear, usually 7" - 9" below the waist.</li>
21957<li>
21958<strong>Inseam:</strong> Measure a similar style of pants that fit well. Measure from the crotch seam to the hem.</li>
21959<li>
21960<strong>Length:</strong> Lengths are measured at the front, starting from where the shoulder meets the neck.</li>
21961</ul>
21962</div>
21963</div>
21964</div>
21965</div>
21966</div>
21967<div>
21968<div>
21969<p>For additional information, please click on full sizing details below or contact the Customer Care team with any questions you may have.</p>
21970</div>
21971<div class="richtext-cta-container richtext-cta-container--small">
21972<div class="richtext-cta-container">
21973<a class="button button--secondary richtext-cta__button" href="/pages/size-chart" style="margin-right: 20px;"><em class="blog-title"><b>FULL SIZING DETAILS</b></em></a> <a class="button button--secondary richtext-cta__button" href="/pages/contact-us"><em class="blog-title"><b>CONTACT CUSTOMER CARE</b></em></a>
21974</div>
21975</div>
21976</div>
21977</section>
21978
21979        <section
21980          id="bp-size-chart-pane-htm"
21981          class="bp-size-chart__pane bp-size-chart__pane--htm"
21982          role="tabpanel"
21983          data-bp-size-chart-pane="htm"
21984          hidden
21985        ><figure class="bp-size-chart__measure-fig">
21986              <img class="bp-size-chart__measure-img"
21987                   src="//www.bostonproper.com/cdn/shop/t/1521/assets/bp-size-chart-measure.png?v=70142022341375340491790713714"
21988                   alt="Measurement diagram showing bust, waist, hips, and inseam points on a model">
21989            </figure><h3>Measuring for the Perfect Size</h3>
21990<p>Wearing a bra and panties, place the measuring tape comfortably around the bust, waist and hips. To determine the most accurate measurements, ensure that the tape is placed evenly around and parallel to the floor.</p>
21991<ul>
21992<li>
21993<strong>Bust:</strong> Measure around the fullest part of the bust, arms relaxed at your side.</li>
21994<li>
21995<strong>Waist:</strong> Measure around waist smallest point with tape slightly loosened for comfort.</li>
21996<li>
21997<strong>Hips:</strong> With feet together, measure around the fullest part of hip and rear, usually 7" - 9" below the waist.</li>
21998<li>
21999<strong>Inseam:</strong> Measure a similar style of pants that fit well. Measure from the crotch seam to the hem.</li>
22000<li>
22001<strong>Length:</strong> Lengths are measured at the front, starting from where the shoulder meets the neck.</li>
22002</ul>
22003<p><a class="btn" href="/pages/size-chart">Full Sizing Details</a></p>
22004<p><a class="btn" href="/pages/contact-us">Contact Customer Care</a></p>
22005</section>
22006      </div>
22007    </div>
22008  </dialog>
22009
22010    
22010<script>
22011      (function () {
22012        const dialog = document.getElementById('bp-size-chart-drawer');
22013        if (!dialog) return;
22014
22015        const openDialog = () => {
22016          try {
22017            if (typeof dialog.showModal === 'function') dialog.showModal();
22018            else dialog.setAttribute('open', '');
22019          } catch (_) {
22020            dialog.setAttribute('open', '');
22021          }
22022          document.body.classList.add('bp-size-chart-open');
22023        };
22024        const closeDialog = () => {
22025          try { if (typeof dialog.close === 'function') dialog.close(); else dialog.removeAttribute('open'); }
22026          catch (_) { dialog.removeAttribute('open'); }
22027          document.body.classList.remove('bp-size-chart-open');
22028        };
22029
22030        document.addEventListener('click', (e) => {
22031          const t = e.target.closest('[data-bp-size-chart-open]');
22032          if (!t) return;
22033          e.preventDefault();
22034          openDialog();
22035        });
22036
22037        dialog.addEventListener('click', (e) => {
22038          if (e.target.closest('[data-bp-size-chart-close]')) { closeDialog(); return; }
22039          const tab = e.target.closest('[data-bp-size-chart-tab]');
22040          if (tab) {
22041            const key = tab.getAttribute('data-bp-size-chart-tab');
22042            dialog.querySelectorAll('[data-bp-size-chart-tab]').forEach((t) => {
22043              const active = t === tab;
22044              t.classList.toggle('is-active', active);
22045              t.setAttribute('aria-selected', active ? 'true' : 'false');
22046            });
22047            dialog.querySelectorAll('[data-bp-size-chart-pane]').forEach((p) => {
22048              const match = p.getAttribute('data-bp-size-chart-pane') === key;
22049              p.classList.toggle('is-active', match);
22050              if (match) p.removeAttribute('hidden');
22051              else p.setAttribute('hidden', '');
22052            });
22053            return;
22054          }
22055          if (e.target === dialog) closeDialog();
22056        });
22057        dialog.addEventListener('close', () => {
22058          document.body.classList.remove('bp-size-chart-open');
22059        });
22060      })();
22061    </script>
22061
22062
22063    <style>
22064      dialog.bp-size-chart {
22065        margin: 0;
22066        padding: 0;
22067        border: 0;
22068        max-width: none;
22069        max-height: none;
22070        width: min(640px, 100vw);
22071        height: 100dvh;
22072        inset: 0 0 0 auto;
22073        background: var(--bp-color-cta-text, #FDFFFA);
22074        color: var(--bp-color-text, #171609);
22075        box-shadow: -16px 0 48px rgba(0, 0, 0, 0.12);
22076        overflow: hidden;
22077        transform: translateX(100%);
22078        transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
22079      }
22080      dialog.bp-size-chart[open] { transform: translateX(0); }
22081      dialog.bp-size-chart::backdrop {
22082        background: rgba(0, 0, 0, 0.32);
22083        animation: bp-size-chart-fade 0.28s ease forwards;
22084      }
22085      @keyframes bp-size-chart-fade { from { opacity: 0; } to { opacity: 1; } }
22086      body.bp-size-chart-open { overflow: hidden; }
22087
22088      .bp-size-chart__inner {
22089        display: flex;
22090        flex-direction: column;
22091        height: 100%;
22092        width: 100%;
22093      }
22094      .bp-size-chart__head {
22095        flex: 0 0 auto;
22096        display: flex;
22097        align-items: center;
22098        justify-content: space-between;
22099        gap: 16px;
22100        padding: 20px 24px;
22101        border-bottom: 1px solid rgba(23, 22, 9, 0.08);
22102      }
22103      @media (max-width: 767px) {
22104        .bp-size-chart__head { padding: 18px 20px; }
22105        .bp-size-chart__title { font-size: 22px; }
22106      }
22107      .bp-size-chart__title {
22108        margin: 0;
22109        color: inherit;
22110        font-family: var(--bp-font-display);
22111        font-size: 28px;
22112        font-weight: 300;
22113        line-height: 120%;
22114        letter-spacing: -0.56px;
22115      }
22116      .bp-size-chart__close {
22117        background: transparent;
22118        border: 0;
22119        padding: 8px;
22120        cursor: pointer;
22121        color: inherit;
22122        line-height: 0;
22123        border-radius: 50%;
22124      }
22125      .bp-size-chart__close:hover { background: rgba(23, 22, 9, 0.06); }
22126
22127      .bp-size-chart__tabs {
22128        flex: 0 0 auto;
22129        display: flex;
22130        gap: 0;
22131        padding: 0;
22132        border-bottom: 1px solid rgba(23, 22, 9, 0.08);
22133      }
22134      .bp-size-chart__tab {
22135        flex: 1 1 0;
22136        background: transparent;
22137        border: 0;
22138        padding: 12px 8px 14px;
22139        cursor: pointer;
22140        font-family: var(--bp-font-body);
22141        font-size: 14px;
22142        font-weight: 500;
22143        line-height: 145%;
22144        letter-spacing: -0.14px;
22145        color: var(--bp-color-body-copy, #74736B);
22146        text-align: center;
22147        position: relative;
22148        transition: color 0.15s ease;
22149      }
22150      .bp-size-chart__tab.is-active {
22151        color: var(--bp-color-text, #171609);
22152        font-weight: 700;
22153      }
22154      .bp-size-chart__tab.is-active::after {
22155        content: '';
22156        position: absolute;
22157        left: 0;
22158        right: 0;
22159        bottom: -1px;
22160        height: 1.5px;
22161        background: var(--bp-color-text, #171609);
22162      }
22163      .bp-size-chart__tab:hover:not(.is-active) { color: var(--bp-color-text, #171609); }
22164
22165      .bp-size-chart__pane[hidden] { display: none; }
22166
22167      .bp-size-chart__body {
22168        flex: 1 1 0;
22169        min-height: 0;
22170        padding: 24px;
22171        overflow-y: auto;
22172        overflow-x: hidden;
22173        font-family: var(--bp-font-body);
22174        font-size: 14px;
22175        line-height: 145%;
22176        letter-spacing: -0.14px;
22177        color: var(--bp-color-text, #171609);
22178        box-sizing: border-box;
22179      }
22180      .bp-size-chart__body *,
22181      .bp-size-chart__body *::before,
22182      .bp-size-chart__body *::after {
22183        box-sizing: border-box;
22184        max-width: 100%;
22185      }
22186      .bp-size-chart__body img { height: auto; }
22187      @media (max-width: 767px) {
22188        .bp-size-chart__body { padding: 20px; }
22189      }
22190
22191      /* Subheaders inside resolved page content. Body-font / 660 /
22192         uppercase per Figma — admins can mark these up as h2/h3/h4
22193         in the Shopify page editor and the drawer styles them
22194         consistently. */
22195      .bp-size-chart__body h2,
22196      .bp-size-chart__body h3,
22197      .bp-size-chart__body h4 {
22198        margin: 24px 0 12px;
22199        font-family: var(--bp-font-body);
22200        font-size: 13px;
22201        font-weight: 700;
22202        line-height: 145%;
22203        letter-spacing: 0.06em;
22204        text-transform: uppercase;
22205        color: var(--bp-color-text, #171609);
22206      }
22207      .bp-size-chart__body > section > :first-child { margin-top: 0; }
22208
22209      .bp-size-chart__body p { margin: 0 0 12px; }
22210      .bp-size-chart__body ul,
22211      .bp-size-chart__body ol {
22212        margin: 8px 0 16px;
22213        padding-left: 20px;
22214      }
22215      .bp-size-chart__body li {
22216        margin: 0 0 8px;
22217        padding-left: 4px;
22218      }
22219      .bp-size-chart__body li::marker { color: var(--bp-color-text, #171609); }
22220
22221      /* Tables — !important on width so a page that ships table with
22222         inline width attribute (or wrapped in <center>) still fills
22223         the drawer. center-aligned cells match the Figma. */
22224      .bp-size-chart__body table {
22225        width: 100% !important;
22226        max-width: 100% !important;
22227        min-width: 0 !important;
22228        border-collapse: collapse;
22229        margin: 12px 0 24px;
22230        font-family: var(--bp-font-body);
22231        display: table !important;
22232      }
22233      .bp-size-chart__body th,
22234      .bp-size-chart__body td {
22235        padding: 12px 14px;
22236        text-align: center;
22237        border-bottom: 1px solid rgba(23, 22, 9, 0.08);
22238        font-size: 14px;
22239        line-height: 145%;
22240        letter-spacing: -0.14px;
22241        color: var(--bp-color-text, #171609);
22242      }
22243      .bp-size-chart__body th {
22244        font-weight: 700;
22245        text-transform: uppercase;
22246        letter-spacing: 0.06em;
22247        font-size: 12px;
22248        background: var(--bp-color-bg-cream, #F7F6EA);
22249        border-bottom: 1px solid rgba(23, 22, 9, 0.12);
22250      }
22251
22252      /* How-to-Measure pane — figure floats left, list flows beside.
22253         Stacks on mobile. */
22254      .bp-size-chart__pane--htm .bp-size-chart__measure-fig {
22255        margin: 0 20px 16px 0;
22256        float: left;
22257        shape-outside: margin-box;
22258        width: 42%;
22259        max-width: 220px;
22260      }
22261      .bp-size-chart__pane--htm .bp-size-chart__measure-img {
22262        display: block;
22263        width: 100%;
22264        height: auto;
22265      }
22266      .bp-size-chart__pane--htm > :first-child:not(figure) { margin-top: 0; }
22267      @media (max-width: 599px) {
22268        .bp-size-chart__pane--htm .bp-size-chart__measure-fig {
22269          float: none;
22270          width: 100%;
22271          max-width: 280px;
22272          margin: 12px auto 16px;
22273        }
22274      }
22275
22276      /* Tame the Shopify-Page admin "FULL SIZING DETAILS" + "CONTACT
22277         CUSTOMER CARE" anchors — Figma renders them as outlined
22278         buttons (white bg, dark border, dark text), full-width,
22279         stacked, hover flips to filled dark. */
22280      .bp-size-chart__body a.btn,
22281      .bp-size-chart__body a.button,
22282      .bp-size-chart__body a[class*="button"],
22283      .bp-size-chart__body a[href*="full-sizing"],
22284      .bp-size-chart__body a[href*="customer-care"],
22285      .bp-size-chart__body a[href*="customer-service"],
22286      .bp-size-chart__body button {
22287        display: flex !important;
22288        align-items: center !important;
22289        justify-content: center !important;
22290        width: 100% !important;
22291        max-width: 100% !important;
22292        min-height: 48px !important;
22293        padding: 12px 18px !important;
22294        margin: 10px 0 0 !important;
22295        font-family: var(--bp-font-body) !important;
22296        font-size: 14px !important;
22297        font-weight: 500 !important;
22298        letter-spacing: -0.14px !important;
22299        line-height: 145% !important;
22300        text-transform: none !important;
22301        font-style: normal !important;
22302        border-radius: 0 !important;
22303        background: transparent !important;
22304        color: var(--bp-color-text, #171609) !important;
22305        border: 1px solid var(--bp-color-text, #171609) !important;
22306        text-decoration: none !important;
22307        white-space: normal !important;
22308        transition: background-color 0.15s ease, color 0.15s ease;
22309      }
22310      .bp-size-chart__body a.btn:hover,
22311      .bp-size-chart__body a.button:hover,
22312      .bp-size-chart__body a[class*="button"]:hover,
22313      .bp-size-chart__body a[href*="full-sizing"]:hover,
22314      .bp-size-chart__body a[href*="customer-care"]:hover,
22315      .bp-size-chart__body a[href*="customer-service"]:hover,
22316      .bp-size-chart__body button:hover {
22317        background: var(--bp-color-text, #171609) !important;
22318        color: var(--bp-color-cta-text, #FDFFFA) !important;
22319      }
22320
22321      @media (prefers-reduced-motion: reduce) {
22322        dialog.bp-size-chart { transition: none; }
22323      }
22324    </style>
22325
22326    <dialog
22327  class="bp-notify"
22328  id="bp-notify-drawer"
22329  data-bp-notify-drawer
22330  data-klaviyo-company="VZrTML"
22331  data-klaviyo-company-dev="WgMT43"
22332  data-klaviyo-list="WFEsDC"
22333  data-klaviyo-list-dev="VDxyUk"
22334  aria-labelledby="bp-notify-title"
22335>
22336  <form class="bp-notify__inner" data-bp-notify-form>
22337    <button
22338      type="button"
22339      class="bp-notify__close"
22340      data-bp-notify-close
22341      aria-label="Close"
22342    >
22343      <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
22344        <line x1="18" y1="6" x2="6" y2="18"/>
22345        <line x1="6" y1="6" x2="18" y2="18"/>
22346      </svg>
22347    </button><div class="bp-notify__body" data-bp-notify-state="form">
22348      <h2 id="bp-notify-title" class="bp-notify__title">Join the Waitlist</h2>
22349      <p class="bp-notify__copy">Be first in line if your size makes a comeback.</p>
22350
22351      <label class="bp-notify__field">
22352        <span class="bp-notify__label">Email address</span>
22353        <input
22354          type="email"
22355          required
22356          autocomplete="email"
22357          data-bp-notify-email
22358          id="bp-notify-email"
22359          aria-describedby="bp-notify-error"
22360        >
22361      </label>
22362
22363      <label class="bp-notify__opt">
22364        <input type="checkbox" data-bp-notify-optin>
22365        <span>Add me to your email list.</span>
22366      </label>
22367
22368      <button type="submit" class="bp-notify__submit" data-bp-notify-submit>
22369        Notify me when it's back
22370      </button>
22371
22372      <p class="bp-notify__legal">
22373        By joining the waitlist, you accept our
22374        <a href="/policies/terms-of-service">Terms</a>
22375        &amp;
22376        <a href="/policies/privacy-policy">Privacy policy</a>.
22377      </p>
22378
22379      <p class="bp-notify__error" id="bp-notify-error" data-bp-notify-error role="alert" hidden></p>
22380    </div><div class="bp-notify__body bp-notify__body--success" data-bp-notify-state="success" role="status" hidden>
22381      <h3 class="bp-notify__success-title">You're on the List</h3>
22382      <p class="bp-notify__success-copy">We'll let you know if your size comes back.<br>Until then, there's so much more to discover.</p>
22383      <button type="button" class="bp-notify__submit bp-notify__submit--success" data-bp-notify-close>Keep Shopping</button>
22384    </div>
22385  </form>
22386</dialog>
22387
22388<script>
22389  (function () {
22390    const LOG = '[bp-notify]';
22391    const dialog = document.getElementById('bp-notify-drawer');
22392    if (!dialog) return;
22393
22394    const form = dialog.querySelector('[data-bp-notify-form]');
22395    const emailInput = dialog.querySelector('[data-bp-notify-email]');
22396    const optinInput = dialog.querySelector('[data-bp-notify-optin]');
22397    const errorEl = dialog.querySelector('[data-bp-notify-error]');
22398    const submitBtn = dialog.querySelector('[data-bp-notify-submit]');
22399    const formState = dialog.querySelector('[data-bp-notify-state="form"]');
22400    const successState = dialog.querySelector('[data-bp-notify-state="success"]');
22401    // Prod vs dev Klaviyo account is decided by the LIVE browser host, not
22402    // server-side: prod + staging share one Shopify store (identical
22403    // shop.domain), so only the URL the shopper is actually on distinguishes
22404    // them. Mirrors Atlas's isProd (src/v2/scripts/utils.js) — exact host
22405    // allowlist, top-frame host, localhost via "127". staging.bostonproper.com
22406    // is NOT prod, so it uses the dev company (WgMT43) and stops 404-ing.
22407    let bpHost = '';
22408    try { bpHost = window.top.location.host; } catch (_) { bpHost = window.location.host; }
22409    const isProd = bpHost === 'bostonproper.com'
22410      || bpHost === 'www.bostonproper.com'
22411      || bpHost === 'bostonproper.myshopify.com'
22412      || bpHost.includes('127');
22413    const company = isProd ? dialog.dataset.klaviyoCompany : (dialog.dataset.klaviyoCompanyDev || dialog.dataset.klaviyoCompany);
22414    const listId  = isProd ? dialog.dataset.klaviyoList    : (dialog.dataset.klaviyoListDev    || dialog.dataset.klaviyoList);
22415
22416    let currentVariantId = null;
22417
22418    const openDialog = (variantId) => {
22419      currentVariantId = variantId || window.bpCurrentVariantId || null;
22420      console.log(LOG, 'open, variantId=', currentVariantId);
22421      resetState();
22422      try { dialog.showModal(); } catch (_) { dialog.setAttribute('open', ''); }
22423      document.body.classList.add('bp-notify-open');
22424      if (emailInput) setTimeout(() => emailInput.focus(), 60);
22425    };
22426    const closeDialog = () => {
22427      try { dialog.close(); } catch (_) { dialog.removeAttribute('open'); }
22428      document.body.classList.remove('bp-notify-open');
22429    };
22430    const resetState = () => {
22431      if (emailInput) emailInput.value = '';
22432      if (optinInput) optinInput.checked = false;
22433      if (errorEl) { errorEl.hidden = true; errorEl.textContent = ''; }
22434      if (formState) formState.hidden = false;
22435      if (successState) successState.hidden = true;
22436      if (submitBtn) { submitBtn.disabled = false; submitBtn.textContent = 'Notify Me'; }
22437    };
22438
22439    const klaviyoHeaders = {
22440      accept: 'application/vnd.api+json',
22441      revision: '2025-07-15',
22442      'content-type': 'application/vnd.api+json',
22443    };
22444
22445    const submitBackInStock = async (email, variantId) => {
22446      const url = `https://a.klaviyo.com/client/back-in-stock-subscriptions/?company_id=${company}`;
22447      const body = JSON.stringify({
22448        data: {
22449          type: 'back-in-stock-subscription',
22450          attributes: {
22451            channels: ['EMAIL'],
22452            profile: { data: { type: 'profile', attributes: { email } } },
22453          },
22454          relationships: {
22455            variant: { data: { type: 'catalog-variant', id: `$shopify:::$default:::${variantId}` } },
22456          },
22457        },
22458      });
22459      return fetch(url, { method: 'POST', headers: klaviyoHeaders, body });
22460    };
22461    const submitNewsletter = async (email) => {
22462      const url = `https://a.klaviyo.com/client/subscriptions/?company_id=${company}`;
22463      const body = JSON.stringify({
22464        data: {
22465          type: 'subscription',
22466          attributes: {
22467            profile: { data: { type: 'profile', attributes: { email } } },
22468            custom_source: 'Back-in-Stock Waitlist Modal',
22469          },
22470          relationships: {
22471            list: { data: { type: 'list', id: listId } },
22472          },
22473        },
22474      });
22475      return fetch(url, { method: 'POST', headers: klaviyoHeaders, body });
22476    };
22477
22478    // --- delegated open ---
22479    document.addEventListener('click', (e) => {
22480      const t = e.target.closest('[data-bp-notify-open]');
22481      if (!t) return;
22482      e.preventDefault();
22483      const vid = t.getAttribute('data-bp-notify-variant-id');
22484      openDialog(vid);
22485    });
22486
22487    // --- close ---
22488    dialog.addEventListener('click', (e) => {
22489      if (e.target.closest('[data-bp-notify-close]')) { closeDialog(); return; }
22490      if (e.target === dialog) closeDialog();
22491    });
22492    dialog.addEventListener('close', () => document.body.classList.remove('bp-notify-open'));
22493
22494    // --- submit ---
22495    form.addEventListener('submit', async (e) => {
22496      e.preventDefault();
22497      const email = (emailInput.value || '').trim();
22498      if (!email) return;
22499      if (!currentVariantId) {
22500        errorEl.textContent = 'We could not detect which variant to subscribe you to. Please re-select your size and try again.';
22501        errorEl.hidden = false;
22502        return;
22503      }
22504      submitBtn.disabled = true;
22505      submitBtn.textContent = 'Submitting…';
22506      errorEl.hidden = true;
22507      try {
22508        const res = await submitBackInStock(email, currentVariantId);
22509        console.log(LOG, 'BIS response', res.status);
22510        if (res.status === 202 || res.ok) {
22511          if (optinInput && optinInput.checked) {
22512            try { await submitNewsletter(email); } catch (e2) { console.error(LOG, 'newsletter error', e2); }
22513          }
22514          if (formState) formState.hidden = true;
22515          if (successState) successState.hidden = false;
22516        } else {
22517          errorEl.textContent = 'Something went wrong. Please try again.';
22518          errorEl.hidden = false;
22519        }
22520      } catch (err) {
22521        console.error(LOG, 'BIS error', err);
22522        errorEl.textContent = 'Network error. Please try again.';
22523        errorEl.hidden = false;
22524      } finally {
22525        submitBtn.disabled = false;
22526        submitBtn.textContent = "Notify me when it's back";
22527      }
22528    });
22529  })();
22530</script>
22530
22531
22532<style>
22533  /* Figma reference: centered modal (not right-side drawer), cream
22534     background, Signifier serif heading, underline-only input, dark
22535     full-width CTA, small legal copy with inline links. */
22536  dialog.bp-notify {
22537    margin: auto;
22538    padding: 0;
22539    border: 0;
22540    width: min(560px, calc(100vw - 32px));
22541    max-width: 560px;
22542    max-height: calc(100dvh - 32px);
22543    background: var(--bp-color-cta-text, #FDFFFA);
22544    color: var(--bp-color-text, #171609);
22545    box-shadow: 0 24px 64px rgba(0, 0, 0, 0.18);
22546    box-sizing: border-box;
22547    opacity: 0;
22548    transform: scale(0.96);
22549    transition: opacity 0.2s ease, transform 0.2s ease;
22550  }
22551  dialog.bp-notify[open] { opacity: 1; transform: scale(1); }
22552  dialog.bp-notify::backdrop { background: rgba(0, 0, 0, 0.4); }
22553  body.bp-notify-open { overflow: hidden; }
22554
22555  .bp-notify__inner {
22556    position: relative;
22557    padding: 56px 56px 40px;
22558  }
22559  @media (max-width: 749px) {
22560    .bp-notify__inner { padding: 48px 24px 32px; }
22561  }
22562
22563  .bp-notify__close {
22564    position: absolute;
22565    top: 16px;
22566    right: 16px;
22567    background: transparent;
22568    border: 0;
22569    padding: 8px;
22570    cursor: pointer;
22571    color: var(--bp-color-text);
22572    line-height: 0;
22573    border-radius: 50%;
22574    transition: background 0.15s ease;
22575  }
22576  .bp-notify__close:hover { background: rgba(23, 22, 9, 0.06); }
22577
22578  .bp-notify__body {
22579    display: flex;
22580    flex-direction: column;
22581    gap: 16px;
22582    font-family: var(--bp-font-body);
22583    font-size: 14px;
22584    line-height: 145%;
22585    text-align: center;
22586  }
22587  /* `.bp-notify__body { display: flex }` has the same specificity as the UA
22588     `[hidden] { display: none }` rule but is authored later, so it won the
22589     cascade and the success state showed ALONGSIDE the form (both visible at
22590     once — QA 7/21). Re-assert display:none for the hidden state so only the
22591     active state (form, then success after submit) shows. */
22592  .bp-notify__body[hidden] { display: none; }
22593  .bp-notify__body--success { gap: 20px; align-items: center; }
22594
22595  .bp-notify__title {
22596    margin: 0;
22597    font-family: var(--bp-font-display);
22598    font-size: 32px;
22599    font-weight: 300;
22600    line-height: 120%;
22601    letter-spacing: -0.64px;
22602    color: var(--bp-color-text);
22603  }
22604  .bp-notify__copy {
22605    margin: 0 0 8px;
22606    color: var(--bp-color-body-copy, #74736B);
22607    font-size: 14px;
22608    line-height: 145%;
22609  }
22610
22611  /* Underline-only input — matches Figma. */
22612  .bp-notify__field { display: flex; flex-direction: column; gap: 4px; text-align: left; margin-top: 8px; }
22613  .bp-notify__label {
22614    font-size: 14px;
22615    font-weight: 500;
22616    color: var(--bp-color-text);
22617    letter-spacing: -0.14px;
22618  }
22619  .bp-notify__field input[type="email"] {
22620    width: 100%;
22621    box-sizing: border-box;
22622    border: 0;
22623    border-bottom: 1px solid rgba(23, 22, 9, 0.32);
22624    background: transparent;
22625    padding: 8px 0;
22626    font-family: var(--bp-font-body);
22627    font-size: 14px;
22628    color: var(--bp-color-text);
22629    border-radius: 0;
22630  }
22631  .bp-notify__field input[type="email"]:focus {
22632    outline: none;
22633    border-bottom-color: var(--bp-color-text);
22634  }
22635  .bp-notify__field input[type="email"]:focus-visible {
22636    outline: 2px solid var(--bp-color-text);
22637    outline-offset: 2px;
22638  }
22639
22640  .bp-notify__opt {
22641    display: inline-flex;
22642    align-items: center;
22643    gap: 10px;
22644    cursor: pointer;
22645    text-align: left;
22646    margin-top: 4px;
22647    font-size: 14px;
22648  }
22649  .bp-notify__opt input[type="checkbox"] {
22650    width: 18px;
22651    height: 18px;
22652    accent-color: var(--bp-color-text);
22653    flex: 0 0 auto;
22654  }
22655
22656  .bp-notify__submit {
22657    width: 100%;
22658    background: var(--bp-color-text, #171609);
22659    color: var(--bp-color-cta-text, #FDFFFA);
22660    border: 0;
22661    height: 52px;
22662    padding: 0 24px;
22663    font-family: var(--bp-font-body);
22664    font-size: 17px;
22665    font-weight: 500;
22666    line-height: normal;
22667    letter-spacing: -0.17px;
22668    cursor: pointer;
22669    margin-top: 8px;
22670    transition: opacity 0.2s ease;
22671  }
22672  .bp-notify__submit:hover { opacity: 0.85; }
22673  .bp-notify__submit[disabled] { opacity: 0.55; cursor: wait; }
22674
22675  /* Success-state submit is sized to content (not full-width) — the
22676     "Keep Shopping" CTA in the Figma is a centered fit-content
22677     button, not an edge-to-edge primary. */
22678  .bp-notify__submit--success {
22679    width: auto;
22680    padding: 0 32px;
22681    margin-top: 4px;
22682  }
22683
22684  .bp-notify__legal {
22685    margin: 4px 0 0;
22686    font-size: 12px;
22687    color: var(--bp-color-body-copy, #74736B);
22688    line-height: 145%;
22689    letter-spacing: -0.12px;
22690  }
22691  .bp-notify__legal a {
22692    color: var(--bp-color-text);
22693    text-decoration: underline;
22694    text-underline-offset: 2px;
22695  }
22696
22697  .bp-notify__error {
22698    margin: 0;
22699    color: var(--bp-color-promo, #B5341B);
22700    font-size: 13px;
22701  }
22702  .bp-notify__success-title {
22703    margin: 0;
22704    font-family: var(--bp-font-display);
22705    font-size: 32px;
22706    font-weight: 300;
22707    letter-spacing: -0.64px;
22708    line-height: 120%;
22709    color: var(--bp-color-text);
22710  }
22711  .bp-notify__success-copy {
22712    margin: 0;
22713    color: var(--bp-color-body-copy, #74736B);
22714    font-size: 14px;
22715    line-height: 145%;
22716    text-align: center;
22717  }
22718</style>
22719
22720    <div
22721    class="bp-sticky-atc"
22722    data-bp-sticky-atc
22723    aria-hidden="true"
22724    inert
22725  >
22726    <div class="bp-sticky-atc__inner">
22727      <div class="bp-sticky-atc__info">
22728        <span class="bp-sticky-atc__title">Boston Proper Printed Scarf With Love BP</span>
22729        <span class="bp-sticky-atc__price" data-bp-sticky-price>
22730          $50.00
22731        </span>
22732      </div>
22733      <button
22734        type="button"
22735        class="bp-sticky-atc__btn"
22736        data-bp-sticky-add
22737      >
22738        Add to Bag
22739      </button>
22740    </div>
22741  </div>
22742
22743  
22743<script>
22744    (function () {
22745      const bar = document.querySelector('[data-bp-sticky-atc]');
22746      if (!bar) return;
22747
22748      // Scope lookups to the main buy box so recommendation / bundle ATCs on
22749      // the page don't get picked up.
22750      const mainScope = () => document.querySelector('.product-information') || document;
22751      // Find the page's main ATC button to watch for visibility.
22752      const findMainAtc = () => mainScope().querySelector(
22753        'button[name="add"]:not([data-bp-sticky-add]), add-to-cart-component button'
22754      );
22755      // The Notify Me trigger (bp-notify-me-button) replaces the ATC when the
22756      // variant is sold out AND restock-eligible.
22757      const findNotify = () => mainScope().querySelector('[data-bp-notify-trigger]');
22758      const findMainForm = () => document.querySelector('form[action*="/cart/add"]');
22759
22760      // Painted = not display:none / 0-size (bp-notify-me hides the ATC via
22761      // display:none and shows the Notify trigger, and vice-versa).
22762      const isRendered = (el) => {
22763        if (!el) return false;
22764        const r = el.getBoundingClientRect();
22765        return (r.width > 0 || r.height > 0) && el.offsetParent !== null;
22766      };
22767
22768      // The primary CTA currently shown in the buy box. The sticky bar MIRRORS
22769      // it: "Notify me" for a Notify-Me variant (opens the drawer), "Add to Bag"
22770      // for an in-stock one, "Sold Out" for a disabled sold-out button. This is
22771      // why the bar no longer sits pinned with a dead "Sold Out" on Notify-Me
22772      // products — it tracks the actual visible CTA (QA: Alfred).
22773      const findPrimaryCta = () => {
22774        const notify = findNotify();
22775        if (isRendered(notify)) return { el: notify, mode: 'notify' };
22776        const atc = findMainAtc();
22777        if (isRendered(atc)) return { el: atc, mode: atc.disabled ? 'soldout' : 'atc' };
22778        return { el: null, mode: 'none' };
22779      };
22780      let mode = 'atc';
22781
22782      // Publish the bar's rendered height so the desktop rule below can reserve
22783      // exactly that much space at the foot of the page (see the stylesheet).
22784      const setBarHeight = () => {
22785        document.documentElement.style.setProperty(
22786          '--bp-sticky-atc-h', `${Math.round(bar.offsetHeight)}px`
22787        );
22788      };
22789      // a11y (WCAG 4.1.2): while hidden the bar is only translated off-screen, so
22790      // its button stayed keyboard-focusable despite aria-hidden. `inert` removes
22791      // the whole bar from the tab order + a11y tree; showBar() lifts it.
22792      const showBar = () => {
22793        bar.classList.add('is-visible');
22794        bar.setAttribute('aria-hidden', 'false');
22795        bar.removeAttribute('inert');
22796        setBarHeight();
22797        // Desktop-only footer spacing hook (QA 7/23): keep the footer's
22798        // terms/privacy links from hiding under the fixed bar at page bottom.
22799        document.body.classList.add('bp-sticky-atc-open');
22800      };
22801      const hideBar = () => {
22802        bar.classList.remove('is-visible');
22803        bar.setAttribute('aria-hidden', 'true');
22804        bar.setAttribute('inert', '');
22805        document.body.classList.remove('bp-sticky-atc-open');
22806      };
22807
22808      // (Re)attach the visibility observer to the CURRENT main ATC. A colour
22809      // swatch swap replaces the product section, so the button this watched is
22810      // destroyed and the observer would keep firing on the detached node —
22811      // leaving the bar stuck visible (QA: "sticky ATC always shows"). Called
22812      // again on bp:pdp:swapped with the freshly-swapped button.
22813      // Mirror the current primary CTA onto the sticky button (label + mode) so
22814      // it reads "Notify me" (opens the drawer) on a Notify-Me variant, "Add to
22815      // Bag" in stock, "Sold Out" when the buy button is a disabled sold-out.
22816      const refreshButton = () => {
22817        const stickyBtn = bar.querySelector('[data-bp-sticky-add]');
22818        if (!stickyBtn) return;
22819        const cta = findPrimaryCta();
22820        mode = cta.mode;
22821        if (mode === 'notify') {
22822          const lbl = cta.el.querySelector('[data-bp-notify-open] span, [data-bp-notify-open]');
22823          stickyBtn.textContent = (lbl && lbl.textContent.trim()) || "Notify me when it's back";
22824          stickyBtn.disabled = false;
22825        } else if (mode === 'soldout') {
22826          stickyBtn.textContent = 'Sold Out';
22827          stickyBtn.disabled = true;
22828        } else if (mode === 'atc') {
22829          stickyBtn.textContent = 'Add to Bag';
22830          stickyBtn.disabled = false;
22831        }
22832      };
22833
22834      let io = null;
22835      const attachObserver = () => {
22836        if (!('IntersectionObserver' in window)) return;
22837        if (io) { try { io.disconnect(); } catch (_) {} io = null; }
22838        // Observe whichever CTA is currently primary (ATC or Notify Me), so the
22839        // bar hides while it's in view and appears once it scrolls away —
22840        // identical for both (QA: Alfred — the bar no longer pins itself over a
22841        // Notify-Me product).
22842        const cta = findPrimaryCta();
22843        if (!cta.el) { hideBar(); return; }
22844        io = new IntersectionObserver((entries) => {
22845          entries.forEach((entry) => {
22846            // A display:none / 0-size CTA also reports isIntersecting=false; only
22847            // show the bar when the CTA is genuinely RENDERED and scrolled out of
22848            // view, otherwise keep it hidden.
22849            const r = entry.boundingClientRect;
22850            const rendered = !!r && (r.height > 0 || r.width > 0);
22851            if (entry.isIntersecting || !rendered) hideBar();
22852            else showBar();
22853          });
22854        }, { threshold: 0 });
22855        io.observe(cta.el);
22856      };
22857
22858      // Re-read the buy box (which CTA is visible) + re-point the observer.
22859      const sync = () => { refreshButton(); attachObserver(); };
22860      sync();
22861      // bp-notify-me / pre-order settle the buy box asynchronously after load,
22862      // so re-sync then (and shortly after) to catch the final CTA.
22863      if (document.readyState === 'loading') {
22864        document.addEventListener('DOMContentLoaded', sync, { once: true });
22865      }
22866      window.addEventListener('load', () => { sync(); setTimeout(sync, 200); });
22867
22868      // Colour swap → re-point the observer at the new main ATC and refresh the
22869      // bar's title (the price + button label already track variant:update
22870      // below). Without this the bar stays stuck on the old colour + visible.
22871      const titleEl = bar.querySelector('.bp-sticky-atc__title');
22872      document.addEventListener('bp:pdp:swapped', () => {
22873        try {
22874          const t = document.querySelector('.view-product-title, .product-title, .product-information h1');
22875          if (t && titleEl) {
22876            const txt = t.textContent.replace(/\s+/g, ' ').trim();
22877            if (txt) titleEl.textContent = txt;
22878          }
22879        } catch (_) {}
22880        sync();
22881      });
22882
22883      // Click the sticky button → click the main ATC (so Horizon
22884      // handles validation, variant selection, and cart drawer open).
22885      const stickyAdd = bar.querySelector('[data-bp-sticky-add]');
22886      if (stickyAdd) {
22887        stickyAdd.addEventListener('click', (e) => {
22888          e.preventDefault();
22889
22890          // Notify Me variant: open the back-in-stock drawer via the buy-box
22891          // trigger, mirroring the main Notify Me button.
22892          if (mode === 'notify') {
22893            const notify = findNotify();
22894            const open = notify && notify.querySelector('[data-bp-notify-open]');
22895            if (open) {
22896              notify.scrollIntoView({ behavior: 'smooth', block: 'center' });
22897              open.click();
22898            }
22899            return;
22900          }
22901          // Disabled sold-out button: nothing to do.
22902          if (mode === 'soldout') return;
22903
22904          const main = findMainAtc();
22905          if (!main) return;
22906
22907          // Respect the page's require-size gate (blocks/bp-require-size.liquid).
22908          // That block flags the main button with `data-bp-size-block` when no
22909          // size is chosen (CSS `pointer-events: none`), and `disabled` /
22910          // `aria-disabled` when the chosen size is out of stock. A synthetic
22911          // `.click()` bypasses `pointer-events: none`, so without this guard the
22912          // sticky bar adds the first-available (smallest) size — the bug in QA
22913          // 7/23. Mirror the page Add to Bag: add nothing, and surface the same
22914          // "Please select a {size}" prompt instead. bp-require-size renders that
22915          // prompt off the required-radio `invalid` event that reportValidity()
22916          // fires (it preventDefault()s the native bubble and shows its own).
22917          const blocked =
22918            main.hasAttribute('data-bp-size-block') ||
22919            main.getAttribute('aria-disabled') === 'true' ||
22920            main.disabled;
22921
22922          main.scrollIntoView({ behavior: 'smooth', block: 'center' });
22923
22924          if (blocked) {
22925            const form = findMainForm();
22926            if (form && typeof form.reportValidity === 'function') form.reportValidity();
22927            return;
22928          }
22929
22930          // Slight delay so scroll settles before the click.
22931          setTimeout(() => main.click(), 120);
22932        });
22933      }
22934
22935      // Track variant changes to keep the price + button label fresh.
22936      // Horizon dispatches `variant:update` (see assets/events.js
22937      // → ThemeEvents.variantUpdate); also keep legacy event names
22938      // listening for forward-compat.
22939      const priceEl = bar.querySelector('[data-bp-sticky-price]');
22940      const onVariant = (e) => {
22941        const v = e?.detail?.resource || e?.detail?.variant || e?.detail;
22942        if (v && priceEl && (v.price || v.priceFormatted)) {
22943          priceEl.textContent = v.priceFormatted || `$${(v.price / 100).toFixed(2)}`;
22944        }
22945        // Re-sync AFTER bp-notify-me / pre-order finish morphing the buy box, so
22946        // the bar mirrors the CURRENT visible CTA (ATC vs Notify Me) and re-points
22947        // its observer instead of watching a stale/hidden button (QA: Alfred).
22948        // The label is derived from the DOM in refreshButton, not v.available.
22949        requestAnimationFrame(sync);
22950        setTimeout(sync, 150);
22951      };
22952      document.addEventListener('variant:update', onVariant);
22953      document.addEventListener('variant:change', onVariant);
22954      document.addEventListener('variantchange', onVariant);
22955    })();
22956  </script>
22956
22957
22958  <style>
22959    /* Defensive: hide Horizon's stock sticky-add-to-cart bar so it
22960       never paints alongside ours. Primary disable is the hardcoded
22961       `{% if false and section.settings.enable_sticky_add_to_cart %}`
22962       in sections/product-information.liquid (the BP override there
22963       prevents the element from rendering at all). This rule is a
22964       belt-and-braces backup for the case where:
22965         - a future template or quick-view modal re-renders Horizon's
22966           bar without the JSON gate,
22967         - Horizon's own section CSS loads after this snippet and
22968           tries to override `display: block`.
22969       `html body` prefix bumps specificity past any naked
22970       `.sticky-add-to-cart__bar` rule; the multiple "off" properties
22971       (display + visibility + position + opacity + transform) make
22972       sure no single one being overridden brings the bar back. */
22973    html body sticky-add-to-cart,
22974    html body .sticky-add-to-cart,
22975    html body .sticky-add-to-cart__bar,
22976    html body .sticky-add-to-cart[data-stuck="true"],
22977    html body .sticky-add-to-cart__bar[data-stuck="true"] {
22978      display: none !important;
22979      visibility: hidden !important;
22980      position: absolute !important;
22981      opacity: 0 !important;
22982      transform: translateY(200vh) !important;
22983      pointer-events: none !important;
22984      z-index: -1 !important;
22985    }
22986
22987    .bp-sticky-atc {
22988      position: fixed;
22989      left: 0; right: 0; bottom: 0;
22990      /* Sit above general page chrome but below dialogs (cart drawer,
22991         quick-add modal — those use top-layer / z-index 9999+). The
22992         previous z-index 60 was being overlapped by Klaviyo embeds and
22993         the chat widget on mobile, hiding the bar. */
22994      z-index: 100;
22995      background: var(--bp-color-cta-text, #FDFFFA);
22996      box-shadow: 0 -2px 16px rgba(0, 0, 0, 0.08);
22997      transform: translateY(100%);
22998      transition: transform 0.24s cubic-bezier(0.4, 0, 0.2, 1);
22999      /* Respect iPhone notch / home-indicator inset so the bar isn't
23000         hidden under the safe area on mobile Safari. */
23001      padding-bottom: env(safe-area-inset-bottom);
23002    }
23003    .bp-sticky-atc.is-visible { transform: translateY(0); }
23004    .bp-sticky-atc__inner {
23005      max-width: 1280px;
23006      margin: 0 auto;
23007      padding: 10px 16px;
23008      display: flex;
23009      align-items: center;
23010      justify-content: space-between;
23011      gap: 16px;
23012    }
23013    .bp-sticky-atc__info {
23014      display: flex;
23015      flex-direction: column;
23016      min-width: 0;
23017    }
23018    .bp-sticky-atc__title {
23019      font-family: var(--bp-font-body);
23020      font-size: 13px;
23021      font-weight: 700;
23022      line-height: 1.3;
23023      color: var(--bp-color-text, #171609);
23024      overflow: hidden;
23025      text-overflow: ellipsis;
23026      white-space: nowrap;
23027    }
23028    .bp-sticky-atc__price {
23029      font-family: var(--bp-font-body);
23030      font-size: 14px;
23031      font-weight: 500;
23032      color: var(--bp-color-text, #171609);
23033    }
23034    .bp-sticky-atc__btn {
23035      background: var(--bp-color-text, #171609);
23036      color: var(--bp-color-cta-text, #FDFFFA);
23037      border: 0;
23038      padding: 12px 20px;
23039      font-family: var(--bp-font-body);
23040      font-size: 13px;
23041      font-weight: 700;
23042      letter-spacing: 0.5px;
23043      text-transform: uppercase;
23044      cursor: pointer;
23045      flex: 0 0 auto;
23046    }
23047    .bp-sticky-atc__btn[disabled] { opacity: 0.55; cursor: not-allowed; }
23048
23049    /* Desktop only (QA 7/23): when the sticky bar is showing, reserve space at
23050       the very bottom of the page so the footer's Privacy / Shipping / Terms
23051       links clear the fixed bar instead of sitting under it. The live footer is
23052       sections/bp-footer-main.liquid, whose last element is .bp-footer__policy-bar
23053       (holds those links); we pad its bottom. The <bp-footer> root paints the
23054       cream background (and clips with overflow: hidden), so the reserved area
23055       fills cream — no bare strip under the bar. Reserved height tracks the
23056       bar's actual height (set in JS as --bp-sticky-atc-h) plus a little gap.
23057       Mobile is unchanged: the bar there sits below the safe-area inset and the
23058       policy bar already clears it. */
23059    @media (min-width: 1024px) {
23060      body.bp-sticky-atc-open .bp-footer__policy-bar {
23061        padding-bottom: calc(var(--bp-sticky-atc-h, 64px) + 16px);
23062      }
23063    }
23064    @media (prefers-reduced-motion: reduce) {
23065      .bp-sticky-atc { transition: none; }
23066    }
23067  </style>
23068    <dialog class="bp-zoom" id="bp-zoom-dialog" aria-label="Zoomed image gallery">
23069    <header class="bp-zoom__head">
23070      <span class="bp-zoom__hint" aria-hidden="true">
23071        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
23072          <circle cx="11" cy="11" r="7"/>
23073          <line x1="11" y1="8" x2="11" y2="14"/>
23074          <line x1="8" y1="11" x2="14" y2="11"/>
23075        </svg>
23076        <span class="bp-zoom__hint-text">Pinch to Zoom</span>
23077      </span>
23078      <button class="bp-zoom__close" type="button" aria-label="Close zoom" data-bp-zoom-close>
23079        <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
23080          <line x1="18" y1="6" x2="6" y2="18"/>
23081          <line x1="6" y1="6" x2="18" y2="18"/>
23082        </svg>
23083      </button>
23084    </header>
23085
23086    <button class="bp-zoom__arrow bp-zoom__arrow--prev" type="button" aria-label="Previous image" data-bp-zoom-prev>
23087      <svg viewBox="0 0 12 22" width="14" height="22" fill="none" aria-hidden="true">
23088        <path d="M11 21L1 11L11 1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
23089      </svg>
23090    </button>
23091    <button class="bp-zoom__arrow bp-zoom__arrow--next" type="button" aria-label="Next image" data-bp-zoom-next>
23092      <svg viewBox="0 0 12 22" width="14" height="22" fill="none" aria-hidden="true">
23093        <path d="M1 21L11 11L1 1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
23094      </svg>
23095    </button><div class="bp-zoom__track" data-bp-zoom-track></div>
23096
23097    <ol class="bp-zoom__dots" data-bp-zoom-dots></ol>
23098  </dialog>
23099
23100  
23100<script>
23101    (function () {
23102      const dialog = document.getElementById('bp-zoom-dialog');
23103      if (!dialog) return;
23104
23105      const track = dialog.querySelector('[data-bp-zoom-track]');
23106      const dotsEl = dialog.querySelector('[data-bp-zoom-dots]');
23107      const prevBtn = dialog.querySelector('[data-bp-zoom-prev]');
23108      const nextBtn = dialog.querySelector('[data-bp-zoom-next]');
23109
23110      /* High-res URL builder. Two CDNs in play: Shopify (?width=N)
23111         and Amplience (?w=N). Replace whichever param exists; fall
23112         back to adding the right one based on host. */
23113      const HIRES = 2000;
23114      const toHires = (src) => {
23115        if (!src) return '';
23116        try {
23117          const u = new URL(src, window.location.href);
23118          if (u.searchParams.has('width')) u.searchParams.set('width', HIRES);
23119          else if (u.searchParams.has('w')) u.searchParams.set('w', HIRES);
23120          else if (u.host.includes('shopify') || u.host.includes('cdn.shopify')) u.searchParams.set('width', HIRES);
23121          else u.searchParams.set('w', HIRES);
23122          return u.toString();
23123        } catch (_) { return src; }
23124      };
23125
23126      /* State per open: which slides exist + per-slide zoom level. */
23127      let slidesData = [];      // [{src, alt}]
23128      let activeIndex = 0;
23129      let zooms = [];           // [{scale, x, y}]
23130      let suppressScrollSync = false;
23131
23132      /* ---------- DOM builders ---------- */
23133      const buildSlide = (data, i) => {
23134        const slide = document.createElement('div');
23135        slide.className = 'bp-zoom__slide';
23136        slide.dataset.index = String(i);
23137        const cage = document.createElement('div');
23138        cage.className = 'bp-zoom__cage';
23139        const img = document.createElement('img');
23140        img.className = 'bp-zoom__img';
23141        img.draggable = false;
23142        img.alt = data.alt || '';
23143        img.src = data.src;
23144        cage.appendChild(img);
23145        slide.appendChild(cage);
23146        return slide;
23147      };
23148      const buildDots = (count) => {
23149        dotsEl.innerHTML = '';
23150        if (count <= 1) return;
23151        for (let i = 0; i < count; i += 1) {
23152          const li = document.createElement('li');
23153          const btn = document.createElement('button');
23154          btn.type = 'button';
23155          btn.className = 'bp-zoom__dot' + (i === 0 ? ' is-active' : '');
23156          btn.setAttribute('aria-label', `Go to image ${i + 1}`);
23157          btn.addEventListener('click', () => goTo(i, { smooth: true }));
23158          li.appendChild(btn);
23159          dotsEl.appendChild(li);
23160        }
23161      };
23162
23163      /* ---------- Slide nav (scrollLeft is the source of truth) ---------- */
23164      const setActive = (i) => {
23165        if (i === activeIndex) return;
23166        if (zooms[activeIndex]) resetSlideZoom(activeIndex);
23167        activeIndex = i;
23168        dotsEl.querySelectorAll('.bp-zoom__dot').forEach((d, idx) => d.classList.toggle('is-active', idx === i));
23169        updateArrows();
23170      };
23171      const goTo = (i, opts) => {
23172        if (i < 0 || i >= slidesData.length) return;
23173        // CRITICAL: release the zoom lock BEFORE scrolling. If the
23174        // current slide is zoomed the dialog carries `.is-zoom-active`
23175        // which sets `overflow-x: hidden` on the track — scroll is
23176        // then a no-op and the arrows appear "broken". Reset zoom on
23177        // the current slide first, which removes the class via
23178        // applyTransform's scale-aware toggle.
23179        if (zooms[activeIndex] && zooms[activeIndex].scale > 1.001) {
23180          resetSlideZoom(activeIndex);
23181        }
23182        const smooth = !!(opts && opts.smooth);
23183        suppressScrollSync = true;
23184        // Use scrollIntoView for smooth — interacts cleanly with
23185        // scroll-snap. Direct scrollLeft assignment for instant — most
23186        // reliable across browsers. Update activeIndex synchronously
23187        // so arrow disabled state + dots flip immediately, then let
23188        // the scroll catch up.
23189        setActive(i);
23190        const slide = slideEl(i);
23191        if (smooth && slide) {
23192          slide.scrollIntoView({ inline: 'start', block: 'nearest', behavior: 'smooth' });
23193        } else {
23194          track.scrollLeft = i * track.clientWidth;
23195        }
23196        setTimeout(() => { suppressScrollSync = false; }, smooth ? 450 : 50);
23197      };
23198      const updateArrows = () => {
23199        prevBtn.disabled = activeIndex === 0;
23200        nextBtn.disabled = activeIndex === slidesData.length - 1;
23201      };
23202
23203      /* Track scroll observer — keeps activeIndex in sync with the
23204         browser-driven swipe/scroll, then updates the dots. */
23205      let scrollRaf = 0;
23206      track.addEventListener('scroll', () => {
23207        if (suppressScrollSync) return;
23208        if (scrollRaf) return;
23209        scrollRaf = requestAnimationFrame(() => {
23210          scrollRaf = 0;
23211          const w = track.clientWidth;
23212          if (!w) return;
23213          const i = Math.round(track.scrollLeft / w);
23214          if (i !== activeIndex) setActive(i);
23215        });
23216      }, { passive: true });
23217
23218      /* ---------- Per-slide zoom + pan (touch + mouse) ----------
23219         Each slide owns a {scale, x, y} transform applied to its
23220         .bp-zoom__cage. Gestures are tracked on the slide itself;
23221         pinch (2-finger) and pan (1-finger / mouse drag) both
23222         update the same state. */
23223      const TAP_SCALE = 2.5;
23224      const MIN = 1;
23225      const MAX = 4;
23226
23227      const slideEl = (i) => track.querySelectorAll('.bp-zoom__slide')[i];
23228      const cageEl = (i) => track.querySelectorAll('.bp-zoom__cage')[i];
23229
23230      const resetSlideZoom = (i) => {
23231        const s = zooms[i];
23232        if (!s) return;
23233        s.scale = 1; s.x = 0; s.y = 0;
23234        applyTransform(i);
23235      };
23236      const applyTransform = (i) => {
23237        const s = zooms[i];
23238        const cage = cageEl(i);
23239        if (!s || !cage) return;
23240        cage.style.transform = `translate3d(${s.x}px, ${s.y}px, 0) scale(${s.scale})`;
23241        const slide = slideEl(i);
23242        if (slide) slide.classList.toggle('is-zoomed', s.scale > 1.001);
23243        // Lock the carousel scroll while the active slide is zoomed
23244        // so a pan gesture doesn't accidentally snap to the next slide.
23245        if (i === activeIndex) {
23246          dialog.classList.toggle('is-zoom-active', s.scale > 1.001);
23247        }
23248      };
23249      const clampPan = (i) => {
23250        const s = zooms[i];
23251        const slide = slideEl(i);
23252        if (!s || !slide) return;
23253        if (s.scale <= 1) { s.x = 0; s.y = 0; return; }
23254        const rect = slide.getBoundingClientRect();
23255        const halfX = (rect.width * (s.scale - 1)) / 2;
23256        const halfY = (rect.height * (s.scale - 1)) / 2;
23257        s.x = Math.max(-halfX, Math.min(halfX, s.x));
23258        s.y = Math.max(-halfY, Math.min(halfY, s.y));
23259      };
23260      const toggleZoomAt = (i, clientX, clientY) => {
23261        const s = zooms[i];
23262        const slide = slideEl(i);
23263        if (!s || !slide) return;
23264        if (s.scale > 1) { resetSlideZoom(i); return; }
23265        const rect = slide.getBoundingClientRect();
23266        const cx = clientX - rect.left - rect.width / 2;
23267        const cy = clientY - rect.top - rect.height / 2;
23268        s.scale = TAP_SCALE;
23269        s.x = -cx * (TAP_SCALE - 1);
23270        s.y = -cy * (TAP_SCALE - 1);
23271        clampPan(i);
23272        applyTransform(i);
23273      };
23274
23275      /* Touch gestures (pinch + pan). Pointer events handle
23276         mouse + single-touch pan; we add a separate touch handler
23277         on the SLIDE for pinch since the Pointer API doesn't
23278         natively give us simultaneous touches. */
23279      const distance = (t1, t2) => Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY);
23280      let pinch = null; // {i, startD, startScale}
23281      track.addEventListener('touchstart', (e) => {
23282        if (e.touches.length !== 2) return;
23283        const i = activeIndex;
23284        pinch = { i, startD: distance(e.touches[0], e.touches[1]), startScale: zooms[i].scale };
23285      }, { passive: true });
23286      track.addEventListener('touchmove', (e) => {
23287        if (!pinch || e.touches.length !== 2) return;
23288        const d = distance(e.touches[0], e.touches[1]);
23289        const s = zooms[pinch.i];
23290        const next = Math.max(MIN, Math.min(MAX, pinch.startScale * (d / pinch.startD)));
23291        s.scale = next;
23292        clampPan(pinch.i);
23293        applyTransform(pinch.i);
23294      }, { passive: true });
23295      track.addEventListener('touchend', () => {
23296        if (!pinch) return;
23297        const i = pinch.i;
23298        const s = zooms[i];
23299        if (s.scale < 1.05) resetSlideZoom(i);
23300        pinch = null;
23301      }, { passive: true });
23302
23303      /* Pointer events handle single-pointer interactions: a clean
23304         tap toggles zoom; a drag pans when already zoomed. Touch
23305         pan is also handled here when only one finger is down (the
23306         pinch handler above takes over when a second finger lands). */
23307      let pointer = null; // {i, startX, startY, lastX, lastY, baseX, baseY, moved}
23308      const onPointerDown = (e) => {
23309        if (e.pointerType === 'touch' && e.isPrimary === false) return;
23310        const slide = e.target.closest('.bp-zoom__slide');
23311        if (!slide) return;
23312        const i = Number(slide.dataset.index);
23313        if (Number.isNaN(i)) return;
23314        const s = zooms[i];
23315        pointer = {
23316          i,
23317          startX: e.clientX, startY: e.clientY,
23318          lastX: e.clientX, lastY: e.clientY,
23319          baseX: s.x, baseY: s.y,
23320          moved: false,
23321          pointerType: e.pointerType
23322        };
23323        // Capture so we keep receiving move/up even if the cursor
23324        // leaves the slide.
23325        try { track.setPointerCapture(e.pointerId); } catch (_) {}
23326      };
23327      const onPointerMove = (e) => {
23328        if (!pointer) return;
23329        const dx = e.clientX - pointer.startX;
23330        const dy = e.clientY - pointer.startY;
23331        if (!pointer.moved && Math.hypot(dx, dy) > 6) pointer.moved = true;
23332        const s = zooms[pointer.i];
23333        if (s.scale > 1) {
23334          // Pan the zoomed cage. Use absolute delta from down so the
23335          // panning feels anchored to the initial grab.
23336          s.x = pointer.baseX + dx;
23337          s.y = pointer.baseY + dy;
23338          clampPan(pointer.i);
23339          applyTransform(pointer.i);
23340          // Prevent browser scroll while panning a zoomed image.
23341          e.preventDefault();
23342        }
23343        pointer.lastX = e.clientX; pointer.lastY = e.clientY;
23344      };
23345      const onPointerUp = (e) => {
23346        if (!pointer) return;
23347        const dx = e.clientX - pointer.startX;
23348        const dy = e.clientY - pointer.startY;
23349        if (!pointer.moved || Math.hypot(dx, dy) < 6) {
23350          // Clean tap → toggle zoom (use the up coordinates so the
23351          // anchor matches where the finger ended).
23352          toggleZoomAt(pointer.i, e.clientX, e.clientY);
23353        }
23354        try { track.releasePointerCapture(e.pointerId); } catch (_) {}
23355        pointer = null;
23356      };
23357      track.addEventListener('pointerdown', onPointerDown);
23358      // pointermove must be non-passive so we can preventDefault
23359      // when panning a zoomed image (otherwise the browser would
23360      // scroll the carousel underneath us).
23361      track.addEventListener('pointermove', onPointerMove, { passive: false });
23362      track.addEventListener('pointerup', onPointerUp);
23363      track.addEventListener('pointercancel', () => { pointer = null; });
23364
23365      /* Mouse wheel pinch (Ctrl/⌘ modifier — same as native
23366         browser zoom convention). */
23367      track.addEventListener('wheel', (e) => {
23368        if (!dialog.open) return;
23369        if (!e.ctrlKey && !e.metaKey) return;
23370        e.preventDefault();
23371        const i = activeIndex;
23372        const s = zooms[i];
23373        const delta = -e.deltaY * 0.01;
23374        s.scale = Math.max(MIN, Math.min(MAX, s.scale + delta));
23375        if (s.scale <= 1) { s.x = 0; s.y = 0; }
23376        clampPan(i);
23377        applyTransform(i);
23378      }, { passive: false });
23379
23380      /* ---------- Open / close ---------- */
23381      const open = (data, startIndex) => {
23382        slidesData = data;
23383        zooms = slidesData.map(() => ({ scale: 1, x: 0, y: 0 }));
23384        track.innerHTML = '';
23385        slidesData.forEach((s, i) => track.appendChild(buildSlide(s, i)));
23386        buildDots(slidesData.length);
23387        activeIndex = Math.max(0, Math.min(startIndex || 0, slidesData.length - 1));
23388        try { dialog.showModal(); } catch (_) { dialog.setAttribute('open', ''); }
23389        document.body.classList.add('bp-zoom-open');
23390        // Jump to the right slide AFTER show (need a layout pass so
23391        // track.clientWidth is real). Two rAFs is enough to get past
23392        // the show-modal layout.
23393        requestAnimationFrame(() => requestAnimationFrame(() => {
23394          goTo(activeIndex, { smooth: false });
23395        }));
23396      };
23397      const close = () => {
23398        try { dialog.close(); } catch (_) { dialog.removeAttribute('open'); }
23399        document.body.classList.remove('bp-zoom-open');
23400        dialog.classList.remove('is-zoom-active');
23401        track.innerHTML = '';
23402        slidesData = []; zooms = [];
23403      };
23404
23405      /* ---------- Wiring ---------- */
23406      prevBtn.addEventListener('click', () => goTo(activeIndex - 1, { smooth: true }));
23407      nextBtn.addEventListener('click', () => goTo(activeIndex + 1, { smooth: true }));
23408      dialog.querySelector('[data-bp-zoom-close]').addEventListener('click', close);
23409      dialog.addEventListener('click', (e) => {
23410        // Clicks that hit the dialog backdrop (not a slide / header /
23411        // arrow / dot) close the modal.
23412        if (e.target === dialog) close();
23413      });
23414      dialog.addEventListener('close', () => {
23415        document.body.classList.remove('bp-zoom-open');
23416        dialog.classList.remove('is-zoom-active');
23417      });
23418      document.addEventListener('keydown', (e) => {
23419        if (!dialog.open) return;
23420        if (e.key === 'Escape') close();
23421        else if (e.key === 'ArrowLeft') goTo(activeIndex - 1, { smooth: true });
23422        else if (e.key === 'ArrowRight') goTo(activeIndex + 1, { smooth: true });
23423      });
23424
23425      /* Delegation: any [data-bp-zoomable] image inside a PDP gallery
23426         opens the modal. Slide list = every zoomable image inside the
23427         clicked image's gallery, in DOM order. */
23428      document.addEventListener('click', (e) => {
23429        const target = e.target.closest('[data-bp-zoomable]');
23430        if (!target) return;
23431        const gallery = target.closest('bp-pdp-gallery, .bp-pdp-gallery, .product-slider-main-images');
23432        if (!gallery) return;
23433        const all = Array.from(gallery.querySelectorAll('img[data-bp-zoomable]'));
23434        if (!all.length) return;
23435        const startIndex = all.indexOf(target);
23436        const data = all.map((img) => ({
23437          src: toHires(img.currentSrc || img.src),
23438          alt: img.alt || ''
23439        }));
23440        open(data, startIndex < 0 ? 0 : startIndex);
23441      });
23442
23443      /* Re-anchor on resize so the active slide stays correctly
23444         scrolled into view (track.clientWidth changes affect
23445         scrollLeft math). */
23446      window.addEventListener('resize', () => {
23447        if (!dialog.open) return;
23448        goTo(activeIndex, { smooth: false });
23449      });
23450    })();
23451  </script>
23451
23452
23453  <style>
23454    /* Modal — full-screen white dialog. Vertical layout: header,
23455       track, dots. The track is a native scroll-snap horizontal
23456       container; slides are absolute-flex-sized children. */
23457    dialog.bp-zoom {
23458      margin: 0;
23459      padding: 0;
23460      border: 0;
23461      max-width: none;
23462      max-height: none;
23463      width: 100vw;
23464      height: 100dvh;
23465      inset: 0;
23466      background: var(--bp-color-bg-page);
23467      color: var(--bp-color-text, #171609);
23468      overflow: hidden;
23469    }
23470    dialog.bp-zoom[open] {
23471      display: flex;
23472      flex-direction: column;
23473    }
23474    dialog.bp-zoom::backdrop { background: rgba(0, 0, 0, 0.5); }
23475    body.bp-zoom-open { overflow: hidden; }
23476
23477    .bp-zoom__head {
23478      flex: 0 0 auto;
23479      display: grid;
23480      grid-template-columns: 1fr auto 1fr;
23481      align-items: center;
23482      padding: 12px 16px;
23483      border-bottom: 1px solid rgba(23, 22, 9, 0.08);
23484      z-index: 2;
23485    }
23486    .bp-zoom__hint {
23487      grid-column: 2;
23488      display: inline-flex;
23489      align-items: center;
23490      gap: 8px;
23491      font-family: var(--bp-font-body);
23492      font-size: 13px;
23493      font-weight: 500;
23494      letter-spacing: 0.5px;
23495      text-transform: uppercase;
23496      color: var(--bp-color-body-copy, #74736B);
23497    }
23498    .bp-zoom__hint svg { display: block; }
23499    @media (hover: hover) and (pointer: fine) {
23500      .bp-zoom__hint-text::before { content: 'Click to Zoom'; }
23501      .bp-zoom__hint-text { font-size: 0; }
23502      .bp-zoom__hint-text::before { font-size: 13px; }
23503    }
23504    .bp-zoom__close {
23505      grid-column: 3;
23506      justify-self: end;
23507      background: transparent;
23508      border: 0;
23509      padding: 6px;
23510      cursor: pointer;
23511      color: inherit;
23512      line-height: 0;
23513    }
23514    .bp-zoom__close:hover { opacity: 0.65; }
23515
23516    /* Native scroll-snap carousel. JS reads/writes track.scrollLeft;
23517       browser does the swipe + inertia. When the active slide is
23518       zoomed, dialog.is-zoom-active disables overflow so panning
23519       doesn't accidentally snap to the next slide. */
23520    .bp-zoom__track {
23521      flex: 1 1 0;
23522      position: relative;
23523      display: flex;
23524      overflow-x: auto;
23525      overflow-y: hidden;
23526      scroll-snap-type: x mandatory;
23527      scroll-behavior: auto;
23528      scrollbar-width: none;
23529      -ms-overflow-style: none;
23530      -webkit-overflow-scrolling: touch;
23531      touch-action: pan-y pinch-zoom;
23532    }
23533    .bp-zoom__track::-webkit-scrollbar { display: none; }
23534    dialog.bp-zoom.is-zoom-active .bp-zoom__track {
23535      overflow-x: hidden;
23536      touch-action: none;
23537    }
23538
23539    .bp-zoom__slide {
23540      flex: 0 0 100%;
23541      height: 100%;
23542      scroll-snap-align: start;
23543      display: flex;
23544      align-items: center;
23545      justify-content: center;
23546      overflow: hidden;
23547      user-select: none;
23548      position: relative;
23549    }
23550    .bp-zoom__cage {
23551      width: 100%;
23552      height: 100%;
23553      display: flex;
23554      align-items: center;
23555      justify-content: center;
23556      transition: transform 0.2s ease-out;
23557      will-change: transform;
23558      cursor: zoom-in;
23559    }
23560    /* When zoomed: pause the transition so pan feels 1:1, and flip
23561       the cursor to a grab cue. Disabling the transition prevents
23562       lag while dragging — the JS applies transform inline. */
23563    .bp-zoom__slide.is-zoomed .bp-zoom__cage {
23564      transition: none;
23565      cursor: grab;
23566    }
23567    .bp-zoom__slide.is-zoomed .bp-zoom__cage:active { cursor: grabbing; }
23568    .bp-zoom__img {
23569      max-width: 100%;
23570      max-height: 100%;
23571      width: auto;
23572      height: auto;
23573      object-fit: contain;
23574      pointer-events: none;
23575    }
23576
23577    /* Arrows */
23578    .bp-zoom__arrow {
23579      position: absolute;
23580      top: 50%;
23581      transform: translateY(-50%);
23582      width: 48px;
23583      height: 48px;
23584      display: inline-flex;
23585      align-items: center;
23586      justify-content: center;
23587      background: var(--bp-color-bg-page);
23588      border: 1px solid rgba(23, 22, 9, 0.12);
23589      cursor: pointer;
23590      z-index: 3;
23591      color: var(--bp-color-text, #171609);
23592      transition: background-color 0.15s ease, opacity 0.15s ease;
23593    }
23594    .bp-zoom__arrow:hover { background: var(--bp-color-bg-page); }
23595    .bp-zoom__arrow:disabled { opacity: 0.3; cursor: default; }
23596    .bp-zoom__arrow--prev { left: 16px; }
23597    .bp-zoom__arrow--next { right: 16px; }
23598    @media (max-width: 749px) {
23599      .bp-zoom__arrow { display: none; }
23600    }
23601
23602    /* Dots */
23603    .bp-zoom__dots {
23604      flex: 0 0 auto;
23605      list-style: none;
23606      margin: 0;
23607      padding: 12px 16px;
23608      display: flex;
23609      gap: 8px;
23610      justify-content: center;
23611      align-items: center;
23612      border-top: 1px solid rgba(23, 22, 9, 0.08);
23613    }
23614    .bp-zoom__dot {
23615      width: 8px;
23616      height: 8px;
23617      border-radius: 50%;
23618      border: 1px solid var(--bp-color-text, #171609);
23619      background: transparent;
23620      padding: 0;
23621      cursor: pointer;
23622      transition: background-color 0.15s ease;
23623    }
23624    .bp-zoom__dot.is-active { background: var(--bp-color-text, #171609); }
23625  </style>
23626<script>
23627  (function () {
23628    'use strict';
23629    if (window.__bpCartCtlWired) return;
23630    window.__bpCartCtlWired = true;
23631
23632    const AMPLIENCE_BASE =
23633      (window.shop && window.shop.themeSettings && window.shop.themeSettings.amplience_cdn_base_url) ||
23634      "https:\/\/media.bostonproper.com";
23635    const STYLITICS_USERNAME = 'bostonproper';
23636    const MAX_CARDS = 8;
23637    const ENDPOINT = 'https://widget-api.stylitics.com/api/outfits';
23638    const BP_CTL_BAG_SVG = '<svg viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M4.18929 5.74434H16.5343H16.6292L16.6729 5.74549C16.9007 5.75099 17.1328 5.87803 17.2448 6.08089C17.3145 6.20157 17.3382 6.30372 17.3547 6.43048C17.6354 9.18806 17.9008 11.996 18.3051 14.7356C18.3771 15.2467 18.4466 15.758 18.5137 16.2697C18.5163 16.2917 18.5195 16.336 18.5207 16.3582C18.5378 16.6193 18.4156 16.9263 18.1508 17.0687C17.9651 17.1752 17.7807 17.1763 17.5845 17.1755C16.1978 17.1755 4.69428 17.1755 3.34023 17.1755C3.20422 17.1726 3.01496 17.1862 2.86505 17.1451C2.45036 17.0406 2.25213 16.656 2.31666 16.2445C2.41071 15.5271 2.58579 14.2489 2.68621 13.5185C2.95476 11.5399 3.15849 9.46674 3.35962 7.47459C3.37582 7.3571 3.44296 6.63739 3.45714 6.52887L3.46698 6.43424L3.46814 6.42237C3.46814 6.41948 3.46901 6.4134 3.47045 6.40559C3.5156 6.02417 3.79254 5.74028 4.18929 5.74434ZM4.18929 6.6125C4.2136 6.6125 4.24804 6.59601 4.27872 6.57343C4.30302 6.55491 4.3201 6.53089 4.32704 6.51845C4.33457 6.50601 4.33486 6.50138 4.33399 6.50427C4.33341 6.50803 4.33225 6.51353 4.33138 6.51758C4.33138 6.51758 4.33081 6.51932 4.33052 6.52424L4.32936 6.5361L4.31923 6.63044C4.132 8.4151 3.9054 10.3181 3.74624 12.1016C3.63685 13.4481 3.56103 15.0256 3.46727 16.3753L3.46582 16.3915V16.3961C3.46582 16.3961 3.46611 16.3973 3.4664 16.3915C3.4664 16.3872 3.4664 16.375 3.46351 16.3588C3.45396 16.2908 3.41721 16.2161 3.3602 16.1507C3.29306 16.0798 3.20422 16.0246 3.12319 16.0162C3.11856 16.0162 3.13361 16.0173 3.15647 16.0176C4.67199 16.0182 16.0117 16.0176 17.5848 16.0176H17.6719C17.6823 16.017 17.6916 16.0168 17.6962 16.0165C17.7014 16.0162 17.7034 16.0159 17.6991 16.0162C17.5752 16.0286 17.4268 16.1591 17.3857 16.2795C17.3576 16.3556 17.3617 16.3788 17.362 16.3941C17.362 16.3921 17.362 16.393 17.362 16.3886L17.3605 16.3724C17.254 14.8543 17.1872 13.3292 17.0509 11.8148C16.8906 10.0895 16.6752 8.23163 16.4883 6.50456C16.495 6.52019 16.5161 6.55433 16.5468 6.57575C16.5714 6.59485 16.5989 6.60585 16.6145 6.60961L16.6243 6.61192H16.6284C16.6284 6.61192 16.6298 6.61279 16.6304 6.61279C16.6318 6.61279 16.6336 6.61279 16.633 6.61279C16.6324 6.61279 16.635 6.61279 16.6292 6.61279C16.5783 6.61221 16.4 6.61337 16.3445 6.61279H4.18929V6.6125Z"/><path d="M6.08301 8.78064C6.1788 7.5189 6.20658 6.21405 6.58539 4.98907C7.15432 3.11007 8.4421 2.11631 10.414 2.12673C13.8001 2.13338 14.5031 4.87997 14.6721 7.71395C14.6964 8.07453 14.7158 8.43453 14.745 8.78035L13.5874 8.77485C13.6172 8.46057 13.6575 8.02649 13.6754 7.71858C13.801 5.83351 13.5976 3.34129 11.3988 2.81605C10.7575 2.6676 10.0702 2.6676 9.42892 2.81605C7.61503 3.24811 7.15143 5.0374 7.12683 6.6872C7.11121 7.36929 7.17545 8.09132 7.24056 8.77485L6.08301 8.78035V8.78064Z"/></svg>';
23639
23640    // ----- Helpers -----
23641    function inferPrefix(rootEl) {
23642      const root = rootEl.closest('[data-bp-ctl]');
23643      if (!root) return 'bp-cart-drawer';
23644      const match = Array.from(root.classList).find((c) => /__ctl$/.test(c));
23645      return match ? match.replace(/__ctl$/, '') : 'bp-cart-drawer';
23646    }
23647
23648    function escape(s) {
23649      return String(s || '').replace(/[&<>"']/g, (c) => ({
23650        '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;'
23651      }[c]));
23652    }
23653
23654    // Scroll-progress indicator — same thin-bar-with-thumb pattern as
23655    // bp-product-carousel's BpProductCarousel.updateArrows(). Wired once
23656    // per track (idempotent) and re-measured any time the track's content
23657    // changes, since a fresh render can change scrollWidth.
23658    function wireIndicator(track) {
23659      const root = track.closest('[data-bp-ctl]');
23660      const indicator = root && root.querySelector('[data-bp-ctl-indicator]');
23661      if (!indicator) return null;
23662      if (!track.__bpIndicatorUpdate) {
23663        const update = () => {
23664          const { scrollLeft, scrollWidth, clientWidth } = track;
23665          if (scrollWidth <= clientWidth + 1) {
23666            indicator.style.display = 'none';
23667            return;
23668          }
23669          indicator.style.display = '';
23670          const thumbW = (clientWidth / scrollWidth) * 100;
23671          const overflow = scrollWidth - clientWidth;
23672          const thumbX = overflow > 0 ? scrollLeft / overflow : 0;
23673          indicator.style.setProperty('--bp-ctl-thumb-w', thumbW + '%');
23674          indicator.style.setProperty('--bp-ctl-thumb-x', thumbX);
23675        };
23676        track.__bpIndicatorUpdate = update;
23677        track.addEventListener('scroll', update, { passive: true });
23678        window.addEventListener('resize', update);
23679      }
23680      return track.__bpIndicatorUpdate;
23681    }
23682
23683    // Stylitics serves prices as currency-formatted strings.
23684    // "$25.00" → "$25" (drop the .00) so it lines up with the rest of
23685    // the BP cart typography.
23686    function formatPrice(s) {
23687      if (!s) return '';
23688      return String(s).replace('.00', '');
23689    }
23690
23691    function itemImage(item) {
23692      // Atlas's pickItemImage: Shopify Collective items use their raw
23693      // image_url (no Amplience asset); everyone else uses the
23694      // {amplience}/i/bostonproper/{remote_id}_2 SET shot.
23695      const isCollective = item && item.other_client_item_ids && item.other_client_item_ids.shopify_collective;
23696      const remoteId = item && item.remote_id;
23697      if (isCollective || !remoteId) return (item && item.image_url) || '';
23698      return `${AMPLIENCE_BASE}/i/bostonproper/${remoteId}_2?fmt=auto&w=484`;
23699    }
23700
23701    function itemUrl(item) {
23702      const raw = (item && item.affiliate_link) || '';
23703      // Keep navigation on the local storefront — strip the host.
23704      return raw.replace(/^https?:\/\/(?:www\.)?bostonproper\.com/, '');
23705    }
23706
23707    // Product handle parsed from affiliate_link, e.g. "iris-ring-set".
23708    // Belt-and-suspenders against the remote_id/bp_style in-cart check
23709    // below: those assume Stylitics echoes the queried item_number back
23710    // as remote_id for the anchor, which doesn't hold for every product
23711    // (Stylitics' catalog id doesn't always match the ERP-synced bp_style
23712    // metafield). A live edge case: "Iris Ring Set" recommended itself
23713    // back because its Stylitics remote_id != its bp_style. The handle
23714    // is what the customer actually sees, so it's a more reliable match
23715    // regardless of whatever id scheme Stylitics uses internally.
23716    function itemHandle(item) {
23717      const raw = (item && item.affiliate_link) || '';
23718      const match = raw.match(/\/products\/([^/?#]+)/);
23719      return match ? match[1] : '';
23720    }
23721
23722    function isPopular(item) {
23723      // Stylitics doesn't carry product tags; BP convention surfaces
23724      // popularity via the `meta` map on collective items. We can flag
23725      // anchor items here later if Stylitics adds a signal; for now,
23726      // render no badge by default.
23727      return !!(item && item.bp_popular);
23728    }
23729
23730    function buildCard(item, prefix) {
23731      const title = item.name || '';
23732      const url = itemUrl(item);
23733      const img = itemImage(item);
23734      const price = formatPrice(item.price_localized);
23735      const sale = item.sale_price_localized && item.sale_price_localized !== item.price_localized
23736        ? formatPrice(item.sale_price_localized)
23737        : null;
23738
23739      const badge = isPopular(item) ? `<span class="${prefix}__ctl-badge">Popular</span>` : '';
23740      const priceHtml = sale
23741        ? `<span class="${prefix}__ctl-sale">${escape(sale)}</span>
23742           <span class="${prefix}__ctl-compare">${escape(price)}</span>`
23743        : escape(price);
23744
23745      return `
23746        <li class="${prefix}__ctl-card ctl__item" data-bp-ctl-item data-remote-id="${escape(item.remote_id || '')}">
23747          <a class="${prefix}__ctl-link" href="${escape(url || '#')}">
23748            ${badge}
23749            <div class="${prefix}__ctl-image ctl-media-container">
23750              <img src="${escape(img)}" alt="${escape(title)}" loading="lazy" width="240" height="300">
23751              <button type="button" class="ctl-bag-icon" data-bp-ctl-bag data-url="${url}" data-bp-remote-id="${escape(String(item.remote_id == null ? '' : item.remote_id))}" aria-label="Quick add ${escape(item.name)}">${BP_CTL_BAG_SVG}</button>
23752            </div>
23753            <div class="${prefix}__ctl-body">
23754              <p class="${prefix}__ctl-name">${escape(title)}</p>
23755              <p class="${prefix}__ctl-price">${priceHtml}</p>
23756            </div>
23757          </a>
23758        </li>`;
23759    }
23760
23761    async function fetchOutfits(style) {
23762      const url = `${ENDPOINT}?username=${encodeURIComponent(STYLITICS_USERNAME)}&item_number=${encodeURIComponent(style)}`;
23763      try {
23764        const res = await fetch(url, { cache: 'force-cache' });
23765        if (!res.ok) return [];
23766        const data = await res.json();
23767        return Array.isArray(data) ? data : [];
23768      } catch (err) {
23769        console.warn('[bp-cart-ctl] Stylitics fetch failed', err);
23770        return [];
23771      }
23772    }
23773
23774    // Every bp_style currently in the bag, from the server-rendered cart
23775    // lines. bp-cart-line-item.liquid stamps data-bp-style on each line
23776    // and the drawer re-renders lines from section HTML (not from
23777    // /cart.js, which carries no metafields), so this stays accurate
23778    // after add/remove without an extra round-trip.
23779    function cartStyles() {
23780      const out = new Set();
23781      document.querySelectorAll('[data-bp-cart-line][data-bp-style]').forEach((line) => {
23782        const s = (line.getAttribute('data-bp-style') || '').trim();
23783        if (s) out.add(String(s));
23784      });
23785      return out;
23786    }
23787
23788    // Every product handle currently in the bag. See itemHandle() above —
23789    // this is the fallback exclusion for when remote_id/bp_style doesn't
23790    // match (Stylitics catalog id drift), since the handle is a direct,
23791    // customer-visible identity check.
23792    function cartHandles() {
23793      const out = new Set();
23794      document.querySelectorAll('[data-bp-cart-line][data-product-handle]').forEach((line) => {
23795        const h = (line.getAttribute('data-product-handle') || '').trim();
23796        if (h) out.add(h);
23797      });
23798      return out;
23799    }
23800
23801    // Collect a flat de-duped item list from up to N outfits, dropping
23802    // anything already in the bag.
23803    //
23804    // This used to drop only the anchor style, which is why adding an
23805    // item could still see it recommended back: the anchor is just the
23806    // most-recently-added line, so as soon as a different line became the
23807    // anchor, the earlier item was fair game again — and any outfit
23808    // legitimately containing it would recommend a product already in the
23809    // bag. Excluding the whole bag covers the anchor too (it's a cart
23810    // line), but the anchor check is kept for the case where the cart
23811    // DOM isn't rendered yet.
23812    function flattenOutfits(outfits, anchorStyle, max) {
23813      const seen = new Set();
23814      const inCart = cartStyles();
23815      const inCartHandles = cartHandles();
23816      const out = [];
23817      for (let i = 0; i < outfits.length && out.length < max; i += 1) {
23818        const items = (outfits[i] && outfits[i].items) || [];
23819        for (let j = 0; j < items.length && out.length < max; j += 1) {
23820          const item = items[j];
23821          if (!item) continue;
23822          const rid = item.remote_id ? String(item.remote_id) : '';
23823          if (rid && String(anchorStyle) === rid) continue;
23824          if (rid && inCart.has(rid)) continue;
23825          const handle = itemHandle(item);
23826          if (handle && inCartHandles.has(handle)) continue;
23827          const key = item.remote_id || item.name;
23828          if (!key || seen.has(key)) continue;
23829          seen.add(key);
23830          out.push(item);
23831        }
23832      }
23833      return out;
23834    }
23835
23836    // Read the anchor from the most-recently-added cart line in the DOM.
23837    // Falls back to /cart.js + a product fetch only if no DOM line carries
23838    // a data-bp-style (e.g. all anchors are products without a bp_style
23839    // metafield).
23840    function resolveAnchorStyle() {
23841      const lines = Array.from(document.querySelectorAll('[data-bp-cart-line][data-bp-style]'));
23842      // Pick the LAST one in source order — that's the most-recently-added
23843      // because Liquid renders cart.items in add order (oldest first).
23844      for (let i = lines.length - 1; i >= 0; i -= 1) {
23845        const style = lines[i].getAttribute('data-bp-style');
23846        if (style && style.trim()) return style.trim();
23847      }
23848      return null;
23849    }
23850
23851    let lastKey = null;
23852    let lastItems = null;
23853
23854    // Single-flight guard. Several listeners (DOMContentLoaded, cart:update,
23855    // bp:cart-drawer:opened, ...) can fire within milliseconds of each other
23856    // — most visibly on first page load, when a quick drawer-open races
23857    // DOMContentLoaded's own sync(). Without this, both calls would see the
23858    // same "not cached yet" state and each kick off an independent
23859    // fetchOutfits() call; whichever resolves last wins and overwrites the
23860    // other's render, which is why the CTL could flash in then disappear.
23861    // While a run is in flight, later calls just flag `pending` instead of
23862    // racing a second fetch; once the in-flight run finishes, one clean
23863    // follow-up run picks up whatever the final state actually is.
23864    let inFlight = null;
23865    let pending = false;
23866
23867    function sync() {
23868      if (inFlight) {
23869        pending = true;
23870        return inFlight;
23871      }
23872      inFlight = runSync().finally(() => {
23873        inFlight = null;
23874        if (pending) {
23875          pending = false;
23876          sync();
23877        }
23878      });
23879      return inFlight;
23880    }
23881
23882    async function runSync() {
23883      const tracks = Array.from(document.querySelectorAll('[data-bp-ctl-track]'));
23884      if (!tracks.length) return;
23885      const sections = tracks.map((t) => t.closest('[data-bp-ctl]')).filter(Boolean);
23886
23887      const anchorStyle = resolveAnchorStyle();
23888      if (!anchorStyle) {
23889        sections.forEach((sec) => sec.setAttribute('hidden', ''));
23890        lastKey = null;
23891        return;
23892      }
23893
23894      // Cache on the anchor AND the bag contents (styles + handles — a
23895      // product missing bp_style would only show up in the handle set, so
23896      // both are needed to bust the cache correctly). Keying on the anchor
23897      // alone went stale now that the whole bag is excluded: removing a
23898      // non-anchor item leaves the anchor unchanged, so the removed
23899      // product would stay filtered out of its own recommendations.
23900      // fetchOutfits is force-cache'd, so re-running this is cheap.
23901      const cacheKey = anchorStyle
23902        + '|' + Array.from(cartStyles()).sort().join(',')
23903        + '|' + Array.from(cartHandles()).sort().join(',');
23904      let items = lastItems;
23905      if (cacheKey !== lastKey) {
23906        const outfits = await fetchOutfits(anchorStyle);
23907        items = flattenOutfits(outfits, anchorStyle, MAX_CARDS);
23908        lastKey = cacheKey;
23909        lastItems = items;
23910      }
23911
23912      if (!items || !items.length) {
23913        sections.forEach((sec) => sec.setAttribute('hidden', ''));
23914        return;
23915      }
23916
23917      tracks.forEach((track) => {
23918        const prefix = inferPrefix(track);
23919        track.innerHTML = items.map((item) => buildCard(item, prefix)).join('');
23920        try { track.scrollTo({ left: 0, behavior: 'auto' }); } catch (_) {}
23921        const update = wireIndicator(track);
23922        if (update) requestAnimationFrame(update);
23923      });
23924      sections.forEach((sec) => sec.removeAttribute('hidden'));
23925
23926      document.dispatchEvent(new CustomEvent('bp:ctl:updated'));
23927    }// `cart:updated` (with the 'd') is BP-internal — fired by the cart
23928    // drawer's bpCartChange() after qty/remove mutations.
23929    document.addEventListener('cart:updated', () => sync());
23930    // `cart:update` (no 'd') is Horizon's stock event — fired on PDP
23931    // add-to-cart, quick-add, and product-card adds. The drawer reacts
23932    // to it but doesn't translate to `cart:updated`, so the CTL needs
23933    // to listen for both. Without this the CTL stays empty after any
23934    // cross-page add (the most common path into the drawer).
23935    document.addEventListener('cart:update', () => sync());
23936    // `product:added` is the alternative add-to-cart signal some Horizon
23937    // surfaces dispatch — listen too so we cover every cart-grow path.
23938    document.addEventListener('product:added', () => sync());
23939    // The cart drawer dispatches this when its dialog becomes visible
23940    // (see snippets/bp-cart-drawer.liquid → open()). Re-sync here so
23941    // the CTL populates the first time the user opens the drawer,
23942    // even when the cart was already populated server-side and no
23943    // cart mutation event has fired since the snippet's initial run.
23944    document.addEventListener('bp:cart-drawer:opened', () => sync());
23945    // Fired by the drawer once the re-fetched cart lines are actually in
23946    // the DOM. The cart-* events above fire as soon as the cart API
23947    // returns, which is BEFORE the lines carrying data-bp-style are
23948    // replaced — so a sync on those alone reads the pre-mutation bag and
23949    // recommends back the item that was just added. This is the signal
23950    // the in-bag exclusion depends on.
23951    document.addEventListener('bp:cart-lines:rendered', () => sync());
23952
23953    // Wire bag buttons — delegated so it survives track.innerHTML re-renders.
23954  // preventDefault + stopPropagation blocks the parent <a> from navigating.
23955  document.addEventListener('click', (e) => {
23956    const bag = e.target.closest && e.target.closest('[data-bp-ctl-bag]');
23957    if (!bag) return;
23958    e.preventDefault();
23959    e.stopPropagation();
23960    const url = bag.getAttribute('data-url');
23961    const remoteId = bag.getAttribute('data-bp-remote-id') || '';
23962    openQuickAdd(url, remoteId);
23963  });
23964
23965  function openQuickAdd(productUrl, remoteId) {
23966    if (!productUrl) return;
23967    // Set the Stylitics widget-add context so bp-how-to-wear-it can
23968    // attribute the follow-up /cart/add as a 'widget' engagement.
23969    const handle = (String(productUrl).match(/\/products\/([^/?#]+)/) || [])[1] || '';
23970    if (handle) {
23971      window.__bpStyliticsWidgetAdd = {
23972        style: String(remoteId || handle),
23973        handle,
23974        until: Date.now() + 90000,
23975      };
23976    }
23977    let host = window.__bpCartCtlQaHost;
23978    if (!host) {
23979      host = document.createElement('div');
23980      host.style.cssText = 'position:absolute;left:-9999px;top:0;width:1px;height:1px;overflow:hidden;';
23981      document.body.appendChild(host);
23982      window.__bpCartCtlQaHost = host;
23983    }
23984    host.innerHTML =
23985      '<product-card>' +
23986      '<a class="product-card__link" ref="productCardLink" href="' + productUrl + '"></a>' +
23987      '<quick-add-component ref="quickAdd">' +
23988      '<button type="button" class="button quick-add__button quick-add__button--choose add-to-cart-button" ' +
23989      'on:click="quick-add-component/handleClick"></button>' +
23990      '</quick-add-component>' +
23991      '</product-card>';
23992    const choose = host.querySelector('.quick-add__button--choose');
23993    if (typeof window.bpTrackCartQuickview === 'function') window.bpTrackCartQuickview(productUrl);
23994    requestAnimationFrame(() => {
23995      try {
23996        if (typeof window.bpOpenProductDrawer === 'function' && choose) window.bpOpenProductDrawer(choose);
23997        else if (choose) choose.click();
23998        else window.location.href = productUrl;
23999      } catch (err) {
24000        console.warn('[bp-cart-ctl] quick-add open failed, navigating', err);
24001        window.location.href = productUrl;
24002      }
24003    });
24004  }
24005  })();
24006</script>
24006
24007
24008<style data-shopify>
24009  .ctl-media-container {
24010    position: relative;
24011  }
24012
24013  .ctl-bag-icon {
24014    position: absolute;
24015    bottom: 12px;
24016    right: 12px;
24017    z-index: 2;
24018    width: 36px;
24019    height: 36px;
24020    padding: 0;
24021    border: 1px solid rgba(23, 22, 9, 0.15);
24022    border-radius: 0;
24023    background: var(--bp-color-bg-page);
24024    color: var(--bp-color-text, #171609);
24025    display: inline-flex;
24026    align-items: center;
24027    justify-content: center;
24028    cursor: pointer;
24029    opacity: 0;
24030    transform: translateY(4px);
24031    transition: opacity 0.2s ease, transform 0.2s ease, background-color 0.2s ease;
24032  }
24033
24034  .ctl-bag-icon:hover {
24035    background: var(--bp-color-text, #171609);
24036    color: #fff;
24037  }
24038  .ctl-bag-icon svg {
24039    width: 20px;
24040    height: 20px;
24041    display: block;
24042  }
24043  .ctl__item:hover .ctl-bag-icon,
24044  .ctl-bag-icon:focus-visible {
24045    opacity: 1;
24046    transform: translateY(0);
24047  }
24048</style>
24049
24050<script>
24051(function () {
24052  if (window.bpBundleUpsell) return;
24053
24054  var QA_HOST = null;  // hidden quick-add trigger host
24055  var REMOVED_KEY = 'removedUpsells';
24056  var SURFACE_SELECTOR = 'bp-cart-drawer, bp-cart-page';
24057
24058  // Candidate upsell products emitted on a cart line by bp-cart-line-item.liquid.
24059  function readLineCandidates(line) {
24060    var el = line.querySelector('[data-bp-line-upsell]');
24061    if (!el) return [];
24062    try { return JSON.parse((el.textContent || '').trim() || '[]'); }
24063    catch (e) { return []; }
24064  }
24065
24066  function getRemoved() {
24067    try { return JSON.parse(sessionStorage.getItem(REMOVED_KEY) || '[]'); }
24068    catch (e) { return []; }
24069  }
24070  function addRemoved(id) {
24071    var removed = getRemoved();
24072    if (id && removed.indexOf(String(id)) === -1) {
24073      removed.push(String(id));
24074      try { sessionStorage.setItem(REMOVED_KEY, JSON.stringify(removed)); } catch (e) { /* noop */ }
24075    }
24076  }
24077  function escapeHtml(str) {
24078    return String(str == null ? '' : str).replace(/[&<>"']/g, function (c) {
24079      return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c];
24080    });
24081  }
24082
24083  function buildCard(u) {
24084    var card = document.createElement('li');
24085    card.className = 'bp-cart-upsell';
24086    card.setAttribute('data-bp-cart-upsell', '');
24087    card.setAttribute('data-upsell-id', u.id);
24088    card.setAttribute('data-upsell-url', u.url);
24089
24090    var dv = parseFloat(u.discount_value);
24091    var discountLabel = '';
24092    if (u.discount_type && dv) {
24093      discountLabel = u.discount_type === 'percentage'
24094        ? 'Save ' + Math.round(dv) + '%'
24095        : 'Save $' + Math.round(dv);
24096    }
24097
24098    var media = u.image
24099      ? '<a class="bp-cart-upsell__media" href="' + u.url + '">' +
24100          '<img src="' + u.image + '" alt="" width="120" height="150" loading="lazy">' +
24101        '</a>'
24102      : '';
24103
24104    card.innerHTML =
24105      media +
24106      '<div class="bp-cart-upsell__body">' +
24107        '<p class="bp-cart-upsell__title">' + escapeHtml(u.title) + '</p>' +
24108        '<p class="bp-cart-upsell__prompt">Complete the look' + (discountLabel ? ' and' : '') + '</p>' +
24109        (discountLabel ? '<p class="bp-cart-upsell__discount">' + discountLabel + '</p>' : '') +
24110        '<button type="button" class="bp-cart-upsell__add" data-bp-upsell-add>Add to Bag</button>' +
24111      '</div>' +
24112      '<button type="button" class="bp-cart-upsell__close" data-bp-upsell-remove aria-label="Dismiss">' +
24113        '<svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">' +
24114          '<path d="M12.66 1 1 13" stroke="currentColor" stroke-miterlimit="10"/>' +
24115          '<path d="M1 1l11.66 12" stroke="currentColor" stroke-miterlimit="10"/>' +
24116        '</svg>' +
24117      '</button>';
24118    return card;
24119  }
24120
24121  // Inject ONE "Complete the look" card into `surfaceEl` (a <bp-cart-drawer>
24122  // or <bp-cart-page>): the first cart line that has an eligible candidate —
24123  // available, not already in the cart, not dismissed this session. DOM-driven
24124  // (reads the server-emitted per-line blobs), so it works on cold open/load
24125  // and after a line re-render alike. Clears prior cards first.
24126  function render(surfaceEl) {
24127    if (!surfaceEl) return;
24128    surfaceEl.querySelectorAll('[data-bp-cart-upsell]').forEach(function (el) { el.remove(); });
24129
24130    var bundlesOff = window.shop && window.shop.themeSettings &&
24131                     window.shop.themeSettings.bundlesEnabled === false;
24132    if (bundlesOff) return;
24133
24134    var lines = Array.prototype.slice.call(surfaceEl.querySelectorAll('[data-bp-cart-line]'));
24135    if (!lines.length) return;
24136    var inCart = lines
24137      .map(function (l) { return (l.dataset.productHandle || '').toLowerCase(); })
24138      .filter(Boolean);
24139    var removed = getRemoved();
24140
24141    for (var i = 0; i < lines.length; i++) {
24142      var candidates = readLineCandidates(lines[i]);
24143      if (!candidates.length) continue;
24144      var u = candidates.find(function (p) {
24145        var h = (p.handle || '').toLowerCase();
24146        return h && p.available &&
24147               inCart.indexOf(h) === -1 && removed.indexOf(String(p.id)) === -1;
24148      });
24149      if (u) {
24150        u.url = u.url || ('/products/' + u.handle);
24151        lines[i].parentNode.insertBefore(buildCard(u), lines[i]);
24152        break;
24153      }
24154    }
24155  }
24156
24157  // Render into every cart surface currently in the DOM.
24158  function renderAll() {
24159    document.querySelectorAll(SURFACE_SELECTOR).forEach(function (el) { render(el); });
24160  }
24161
24162  // Open the upsell product in the BP quick-add drawer (same dynamic hidden
24163  // trigger the HTWI section uses — Horizon reads the product URL from the
24164  // product-card's ref="productCardLink"). Preserves LIPs via the fetched form.
24165  function openQuickAdd(productUrl) {
24166    if (!productUrl) return;
24167    if (!QA_HOST) {
24168      QA_HOST = document.createElement('div');
24169      QA_HOST.setAttribute('data-bp-upsell-qa-host', '');
24170      QA_HOST.style.cssText = 'position:absolute;left:-9999px;top:0;width:1px;height:1px;overflow:hidden;';
24171      document.body.appendChild(QA_HOST);
24172    }
24173    QA_HOST.innerHTML =
24174      '<product-card>' +
24175      '<a class="product-card__link" ref="productCardLink" href="' + productUrl + '"></a>' +
24176      '<quick-add-component ref="quickAdd">' +
24177      '<button type="button" class="button quick-add__button quick-add__button--choose add-to-cart-button" ' +
24178      'on:click="quick-add-component/handleClick"></button>' +
24179      '</quick-add-component>' +
24180      '</product-card>';
24181    var choose = QA_HOST.querySelector('.quick-add__button--choose');
24182    // Cart-flyout / cart-page Quickview view_item — this bespoke trigger isn't a
24183    // .bp-card, so bp-track-cards' fireQuickview can't see it; bpTrackCartQuickview
24184    // resolves the Page Type (Cart Flyout Quickview vs Cart Quickview).
24185    if (typeof window.bpTrackCartQuickview === 'function') window.bpTrackCartQuickview(productUrl);
24186    requestAnimationFrame(function () {
24187      try {
24188        if (typeof window.bpOpenProductDrawer === 'function' && choose) window.bpOpenProductDrawer(choose);
24189        else if (choose) choose.click();
24190        else window.location.href = productUrl;
24191      } catch (e) { window.location.href = productUrl; }
24192    });
24193  }
24194
24195  // One delegated listener handles Add-to-Bag + dismiss for cards on any surface.
24196  document.addEventListener('click', function (e) {
24197    var addBtn = e.target.closest && e.target.closest('[data-bp-upsell-add]');
24198    if (addBtn) {
24199      e.preventDefault();
24200      var addCard = addBtn.closest('[data-bp-cart-upsell]');
24201      if (addCard) openQuickAdd(addCard.getAttribute('data-upsell-url'));
24202      return;
24203    }
24204    var rmBtn = e.target.closest && e.target.closest('[data-bp-upsell-remove]');
24205    if (rmBtn) {
24206      e.preventDefault();
24207      var rmCard = rmBtn.closest('[data-bp-cart-upsell]');
24208      if (!rmCard) return;
24209      addRemoved(rmCard.getAttribute('data-upsell-id'));
24210      var surface = rmCard.closest(SURFACE_SELECTOR);
24211      rmCard.remove();
24212      // Surface the next eligible offer on the same surface.
24213      if (surface) render(surface);
24214    }
24215  });
24216
24217  // Self-wiring: render on ready + whenever the cart changes / a drawer opens /
24218  // the line list is re-rendered. All events are dispatched by the cart surfaces.
24219  ['cart:updated', 'bp:cart-drawer:opened', 'bp:cart-lines:rendered'].forEach(function (ev) {
24220    document.addEventListener(ev, function () { renderAll(); });
24221  });
24222  if (document.readyState === 'loading') {
24223    document.addEventListener('DOMContentLoaded', function () { renderAll(); });
24224  } else {
24225    renderAll();
24226  }
24227
24228  window.bpBundleUpsell = {
24229    render: render,
24230    renderAll: renderAll,
24231    openQuickAdd: openQuickAdd,
24232    getRemoved: getRemoved,
24233    addRemoved: addRemoved
24234  };
24235})();
24236</script>
24236
24237
24238
24239
24240<div class="bp-toast" data-bp-toast role="status" aria-live="polite" hidden>
24241  <span class="bp-toast__msg" data-bp-toast-msg></span>
24242  <button type="button" class="bp-toast__action" data-bp-toast-action hidden></button>
24243  <button type="button" class="bp-toast__close" data-bp-toast-close aria-label="Dismiss">
24244    <svg width="14" height="14" viewBox="0 0 20 20" fill="none" aria-hidden="true">
24245      <path d="M5 5l10 10M15 5L5 15" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
24246    </svg>
24247  </button>
24248</div>
24249
24250<style data-shopify>
24251  .bp-toast {
24252    position: fixed;
24253    left: 50%;
24254    bottom: 24px;
24255    transform: translateX(-50%) translateY(8px);
24256    z-index: 9998;
24257    display: flex;
24258    align-items: center;
24259    gap: 16px;
24260    max-width: calc(100vw - 32px);
24261    padding: 14px 16px;
24262    background: var(--bp-color-text, #171609);
24263    color: var(--bp-color-cta-text, #FDFFFA);
24264    font-family: var(--bp-font-body);
24265    font-size: 14px;
24266    font-weight: 500;
24267    line-height: 145%;
24268    letter-spacing: -0.14px;
24269    box-shadow: 0 6px 24px rgb(0 0 0 / 0.18);
24270    opacity: 0;
24271    pointer-events: none;
24272    transition: opacity 0.2s ease, transform 0.2s ease;
24273  }
24274  .bp-toast[hidden] { display: none; }
24275  .bp-toast.is-visible {
24276    opacity: 1;
24277    transform: translateX(-50%) translateY(0);
24278    pointer-events: auto;
24279  }
24280
24281  .bp-toast__msg { flex: 1 1 auto; }
24282
24283  .bp-toast__action {
24284    flex: 0 0 auto;
24285    background: transparent;
24286    border: 0;
24287    padding: 0;
24288    cursor: pointer;
24289    color: inherit;
24290    font: inherit;
24291    text-decoration: underline;
24292    text-underline-offset: 3px;
24293  }
24294  .bp-toast__action[hidden] { display: none; }
24295  .bp-toast__action:hover { opacity: 0.7; }
24296
24297  .bp-toast__close {
24298    flex: 0 0 auto;
24299    background: transparent;
24300    border: 0;
24301    padding: 0;
24302    width: 20px;
24303    height: 20px;
24304    cursor: pointer;
24305    color: inherit;
24306    display: inline-flex;
24307    align-items: center;
24308    justify-content: center;
24309  }
24310  .bp-toast__close:hover { opacity: 0.7; }
24311
24312  @media (prefers-reduced-motion: reduce) {
24313    .bp-toast {
24314      transition: none;
24315      transform: translateX(-50%);
24316    }
24317    .bp-toast.is-visible { transform: translateX(-50%); }
24318  }
24319</style>
24320
24321<script>
24322  (function () {
24323    if (window.bpToast) return; // singleton — safe if rendered twice
24324
24325    const el = document.querySelector('[data-bp-toast]');
24326    if (!el) return;
24327    const msgEl = el.querySelector('[data-bp-toast-msg]');
24328    const actionEl = el.querySelector('[data-bp-toast-action]');
24329    const closeEl = el.querySelector('[data-bp-toast-close]');
24330    let timer = null;
24331
24332    function hide() {
24333      clearTimeout(timer);
24334      el.classList.remove('is-visible');
24335      // Wait out the fade before un-rendering so it doesn't vanish
24336      // abruptly. 200ms matches the transition above.
24337      timer = setTimeout(() => { el.hidden = true; }, 200);
24338    }
24339
24340    function show(message, opts) {
24341      const o = opts || {};
24342      if (!message) return;
24343      clearTimeout(timer);
24344
24345      msgEl.textContent = message;
24346
24347      // Reset the action each time — a previous toast's label/attrs
24348      // must not leak into this one.
24349      actionEl.hidden = true;
24350      actionEl.textContent = '';
24351      [...actionEl.attributes].forEach((a) => {
24352        if (a.name.indexOf('data-') === 0 && a.name !== 'data-bp-toast-action') {
24353          actionEl.removeAttribute(a.name);
24354        }
24355      });
24356
24357      if (o.action) {
24358        actionEl.textContent = o.action;
24359        Object.keys(o.actionAttrs || {}).forEach((k) => actionEl.setAttribute(k, o.actionAttrs[k]));
24360        actionEl.hidden = false;
24361      }
24362
24363      el.hidden = false;
24364      // Force a reflow so the transition runs on a freshly-unhidden
24365      // element instead of being skipped.
24366      void el.offsetWidth;
24367      el.classList.add('is-visible');
24368
24369      const duration = o.duration || 4000;
24370      timer = setTimeout(hide, duration);
24371    }
24372
24373    closeEl.addEventListener('click', hide);
24374    // The action is a one-shot; dismiss after it fires. The click still
24375    // bubbles first, so delegated handlers (e.g. [data-bp-saved-open])
24376    // run normally.
24377    actionEl.addEventListener('click', () => hide());
24378
24379    window.bpToast = show;
24380    window.bpToast.hide = hide;
24381
24382    // ---- Save-for-later confirmations -------------------------------
24383    // `wishlist:item-saved` / `:item-removed` are dispatched by every
24384    // save surface (PDP gallery heart, cart line, saved drawer), so
24385    // wiring here covers them all without touching each one.
24386    //
24387    // "View" carries data-bp-saved-open — bp-saved-for-later-drawer
24388    // opens on a delegated document click for ANY element with that
24389    // attribute, so no extra wiring is needed.
24390    document.addEventListener('wishlist:item-saved', () => {
24391      // Show the toast in-frame too (like the remove toast). Inside the
24392      // Publitas quickview iframe the toast is the VISIBLE surface (the parent
24393      // toast sat BEHIND the Publitas modal — the "background" bug), and its
24394      // "View" click is intercepted by bp-quickview-cart-bridge and relayed to
24395      // the parent, which opens its saved drawer in the top layer above the
24396      // modal (QA 7/27, Dragana — previously the in-frame toast was suppressed
24397      // and the parent's was hidden behind the modal + its View unclickable).
24398      show('Saved for later', {
24399        action: 'View',
24400        actionAttrs: { 'data-bp-saved-open': '' }
24401      });
24402    });
24403
24404    document.addEventListener('wishlist:item-removed', () => {
24405      show('Removed from saved items');
24406    });
24407  })();
24408</script>
24408
24409
24410  <style> .n113 {color: grey;} </style>
24411<div id="shopify-block-AeERjbDhiOTdYM000e__16157100011046449464" class="shopify-block shopify-app-block">
24412
24413  
24414    
24415    
24416
24417
24418
24419  
24420    <link rel="stylesheet" href="https://cdn.shopify.com/extensions/01a0c561-16b0-72bc-8987-550a5e565f0a/narvar-extensions-244/assets/shipping-protection-cart-widget.css">
24421    
24421<script src="https://cdn.shopify.com/extensions/01a0c561-16b0-72bc-8987-550a5e565f0a/narvar-extensions-244/assets/shipping-protection-cart-widget.js" defer></script>
24421
24422  
24423
24424
24425
24426  <style>
24427    div[data-product-handle="narvardeliveryprotection"] {
24428  display: none !important;
24429}
24430
24431button#CartDrawer-Checkout-DP-With {
24432    letter-spacing: .025em;
24433    --tw-text-opacity: 1;
24434    color: rgb(255 255 255 / var(--tw-text-opacity));
24435    --tw-bg-opacity: 1;
24436    background-color: rgb(0 0 0 / var(--tw-bg-opacity));
24437    font-weight: 600;
24438    height: 50px;
24439    font-size:100%;
24440    margin: 0;
24441}
24442button#CartDrawer-Checkout-DP-With:hover {
24443    --tw-bg-opacity: 1;
24444    background-color: rgb(102 102 102 / var(--tw-bg-opacity));
24445}
24446button#CartDrawer-Checkout-DP-Without {
24447    --tw-text-opacity: 1;
24448    --tw-bg-opacity: 1;
24449    --tw-border-opacity: 1;
24450    letter-spacing: .025em;
24451    color: rgb(0 0 0 / var(--tw-text-opacity));
24452    font-weight: 600;
24453    height: 50px;
24454    font-size:100%;
24455    border: 1px solid rgb(0 0 0/var(--tw-border-opacity));
24456    text-transform: capitalize;
24457}
24458  </style>
24459
24460
24461
24462
24463<script>
24464  window.NarvarDPData = {
24465    variant_id: 46514716934310,
24466    metafield:  JSON.stringify({"isRetailerActive":true,"US":{"version":9,"protectionType":"insurance","currency":"USD","minimumPremiumValue":3,"taxAdjustment":15,"l10ns":{"en":{"title":"Shipping Protection","description":"Protect your purchase from loss, damage, and theft with InsureShield.","tnc":"","dpLogoUrl":"https://assets.narvar.com/delivery-protection/ups-insureshield.png","privacyPolicyUrl":"","tosUrl":"","footerText":"By selecting coverage, you acknowledge you have read and agree to the","learnMoreText":"Program Terms and Conditions.","learnMoreUrl":"https://www.insureshield.com/content/terms-and-conditions/Narvar_TermsAndConditions.pdf","zeroPremiumText":"Your purchase includes complimentary coverage paid by Boston Proper for lost, damaged, and stolen packages with InsureShield.","merchantName":"Boston Proper"}},"eligibilityRule":{"shippingCountries":["US"],"maxOrderValue":2000},"premiumRule":{"condition":{"excludedCategories":[],"excludedShippingCountries":[]},"premium":{"type":"percentage","value":3}},"zeroPremiumRule":{"condition":{"customerTags":[""]}},"serviceFee":0,"insuranceType":"upsc"}}),
24467    cart_attributes: "",
24468    settings: {
24469      widget_style: "opt-out-button",
24470      btn_with_class_names: "bp-cart-drawer__btn bp-cart-drawer__btn--primary",
24471      btn_without_class_names: "bp-cart-drawer__btn bp-cart-drawer__btn--secondary",
24472      btn_add_to_cart_class_names: "button, add-to-cart-button",
24473      subtotal_selector: "totals__subtotal-value",
24474      cart_count_bubble_selector: "bp-cart-drawer__bubble",
24475      color_accent: "#2563eb",
24476      always_show_widget: true,
24477      show_price_next_to_checkout_btn: true,
24478      show_domain: "www.bostonproper.com",
24479      shop_name: "Boston Proper",
24480      qty_update_selector: "bp-cart-line__qty-input"
24481    }
24482  };
24483</script>
24483
24484
24485
24486</div><div id="shopify-block-AZkhkQVl0RVZWQVpyZ__13480610564648845780" class="shopify-block shopify-app-block">
24486<script
24487  defer
24488  type="text/javascript"
24489  src="https://szero.narvar.com/packs/js/shop_now.js"></script>
vendor: 1 bytes, line 24489
24489
24490<script>
24491  (function(){
24492    const scriptEl = document.querySelector('script[src="https://szero.narvar.com/packs/js/shop_now.js"]');
24493    if(scriptEl){
24494      scriptEl.addEventListener('load', function(){
24495        const config = {bannerContainer: "body",checkoutButton: "input[name=\"checkout\"],button[name=\"checkout\"],a[href=\"checkout\"],a[href=\"\/checkout\"]",checkoutForm: "form[action=\"cart\"],form[action=\"\/cart\"],form[action=\"checkout\"],form[action=\"\/checkout\"]",alternativePaymentButton: ".shopify-payment-button,shopify-accelerated-checkout,.cart__dynamic-checkout-buttons.additional-checkout-buttons,shopify-accelerated-checkout-cart,shop-pay-wallet-button,shopify-paypal-button,shopify-google-pay-button,shopify-payment-terms,.rebuy-cart__shop-pay-button",bindCheckoutListener: true,
24496          rebuySmartCart: false,
24497          ampCartDrawer: false,
24498        };
24499
24500        nv_shopnow.init(config);
24501
24502        const preview = window.Shopify.designMode;
24503        if(preview){
24504          nv_shopnow.previewBanner();
24505        }
24506      });
24507    }
24508  })();
24509</script>
24509
24510
24511
24512</div><div id="shopify-block-AbGs2R0xnSVR3dGZhd__9271244056961380716" class="shopify-block shopify-app-block">
24512<script src='https://cdn.shopify.com/extensions/01a0f186-e064-7986-a442-4245fc3eb6fb/discount-kit-634/assets/dk_cart_observer.js'></script>
vendor: 1 bytes, line 24512
24512
24513<script type='module' src='https://cdn.shopify.com/extensions/01a0f186-e064-7986-a442-4245fc3eb6fb/discount-kit-634/assets/dk_cart.js'></script>
vendor: 1 bytes, line 24513
24513
24514<script type='module' src='https://cdn.shopify.com/extensions/01a0f186-e064-7986-a442-4245fc3eb6fb/discount-kit-634/assets/dk_gift-selector.js'></script>
24514
24515
24516<!-- BEGIN app snippet: core_script -->
24517
24518
24519
24520
24521
24522
24523
24524
24525<script>
24526  // Initialize DiscountKit namespace
24527  window.discount_kit = window.discount_kit || {};
24528
24529  // Configuration and data
24530  window.discount_kit.config = {
24531    auto_gift: true,
24532    gift_selector_enabled: false,
24533    gift_quickview: false,
24534    gift_quickview_auto_add: false,
24535    gift_quickview_change: false,
24536    gift_quickview_change_label: "Change gifts",
24537    gift_quickview_change_style: "theme",
24538    message: "You've unlocked a free gift! Make your selections now.",
24539    add_to_cart: "Add to cart",
24540    show_on_cart_page: false,
24541    stop_showing_after: 0,
24542    prevent_readd_removed_gifts: true,
24543    refresh_on_cart_change: false,
24544    custom_cart_update_event: "discount_kit:cart_changed",
24545    cart: {"note":null,"attributes":{},"original_total_price":0,"total_price":0,"total_discount":0,"total_weight":0.0,"item_count":0,"items":[],"requires_shipping":false,"currency":"USD","items_subtotal_price":0,"cart_level_discount_applications":[],"checkout_charge_amount":0},
24546    collections: [],
24547    compare_at_prices: [],
24548    conversion_rate: 1.0,
24549    discounts: [{"id": "2395617853606",
24550           "discountType": "GWP",
24551           "discountTitle": "OCTOBERSCARF",
24552           "startsAt": null,
24553           "endsAt": null,
24554           "discountNode": { "config": { "value": {"allowB2b":false,"appliesOncePerCustomer":false,"cartAttribute":null,"currencyCode":null,"customerOperator":"oneOf","customerTags":null,"discountTitle":"OCTOBERSCARF","discountType":"GWP","uuid":"960e25b1-9805-475d-bab9-7aa982339b73","locationIds":null,"locationOperator":"oneOf","marketHandles":null,"marketOperator":"oneOf","matchRule":{"all":true,"type":"product","include":[],"selection":[],"exclude":[],"excludeSale":false,"purchaseType":"both"},"onlyB2b":false,"requireGiftProperty":true,"test":false,"tiers":[{"message":null,"messageTranslations":null,"buys":{"type":"minimumSubtotal","value":40000},"gets":{"type":"percentage","value":100,"targetQuantity":1,"matchRule":{"all":false,"type":"productSelection","include":[],"selection":[{"id":"
2455415286962618534","variants":null}],"exclude":[],"excludeSale":false}}}],"usageLimit":null} } }},{"id": "2396067692710",
24555           "discountType": "CUSTOM",
24556           "discountTitle": "Winter Sweater Promo",
24557           "startsAt": null,
24558           "endsAt": null,
24559           "discountNode": { "config": { "value": {"allowB2b":false,"allowB2B":false,"onlyB2b":false,"appliesOncePerCustomer":false,"attributeKey":"_discount_kit","bucketRules":[{"name":"ALL_RESERVED"},{"name":"Ribbed Sweaters: winter","collectionFilter":[693294661798],"cfp":[0]}],"cartAttribute":null,"currencyCode":null,"customerOperator":"oneOf","customerTags":null,"discountApplicationStrategy":"MAXIMUM","discountRules":[{"message":"Save $25 on 2","messageTranslations":null,"recurring":false,"requireAllTargets":false,"discountValue":{"fixedAmount":{"amount":"25.00","appliesToEachItem":false}},"maxRecurrences":null,"currency":null,"fixedPrice":null,"targetParts":[{"bucket":"Ribbed Sweaters: winter","quantity":null,"targetSelectionStrategy":"cheapest_first"}
24559],"useCompareAtPrice":false,"useMetafieldPrice":false,"conditionParts":[{"bucket":"Ribbed Sweaters: winter","quantity":2,"total":null,"uniqueProducts":null,"uniqueVariants":null,"operator":"equal","order":0}]},{"message":"Save $45 on 3","messageTranslations":null,"recurring":false,"requireAllTargets":false,"discountValue":{"fixedAmount":{"amount":"45.00","appliesToEachItem":false}},"maxRecurrences":null,"currency":null,"fixedPrice":null,"targetParts":[{"bucket":"Ribbed Sweaters: winter","quantity":null,"targetSelectionStrategy":"cheapest_first"}],"useCompareAtPrice":false,"useMetafieldPrice":false,"conditionParts":[{"bucket":"Ribbed Sweaters: winter","quantity":3,"total":null,"uniqueProducts":null,"uniqueVariants":null,"operator":"equal","order":0}]}],"discountTitle":"Winter Sweater Promo","discountType":"CUSTOM","fillingStrategy":"all","locationIds":null,"locationOperator":"oneOf","marketHandles":null,"marketOperator":"oneOf","metafieldKey":"","metafieldNamespace":"","useMetafieldDiscounts":false,"orderDiscountApplicationStrategy":"MAXIMUM","orderDiscountRules":[],"shippingDiscountApplicationStrategy":"ALL","shippingDiscountRules":[],"test":false,"usageLimit":null,"uuid":"81d72569-a154-408d-b1e6-bd1f285fcbcf","consume":false} } }}]
24560  };
24561
24562  // Gift products for GWP
24563  window.discount_kit.gift_products = [];
24564  
24565  
24566    
24567      window.discount_kit.gift_products.push({
24568        product: {"id":15286962618534,"title":"Boston Proper Printed Scarf With Love BP","handle":"boston-proper-printed-scarf-with-love-bp","description":null,"published_at":"2026-09-30T03:06:19-04:00","created_at":"2026-04-16T02:30:04-04:00","vendor":"Boston Proper","type":"Promotions","tags":["2CT80","2CT8071","799","Active","Charmeuse","Fashion","Floral","Full Price","INV5_2CT80","Miscellaneous","N\/A","Non-Apparel","nvgroup_2CT80","Pink","Promotions","Published: 20261001","rtly-gc:offer-free-shipping","Scarves","Winter 26","Work","Woven","YGroup_2CT80"],"price":5000,"price_min":5000,"price_max":5000,"available":true,"price_varies":false,"compare_at_price":5000,"compare_at_price_min":5000,"compare_at_price_max":5000,"compare_at_price_varies":false,"variants":[{"id":56389031657638,"title":"With Love BP \/ One Size","option1":"With Love BP","option2":"One Size","option3":null,"sku":"2CT8071000","requires_shipping":true,"taxable":true,"featured_image":{"id":80304586948774,"product_id":15286962618534,"position":1,"created_at":"2026-10-03T02:33:16-04:00","updated_at":"2026-10-03T02:33:18-04:00","alt":null,"width":1639,"height":2048,"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198","variant_ids":[56389031657638]},"available":true,"name":"Boston Proper Printed Scarf With Love BP - With Love BP \/ One Size","public_title":"With Love BP \/ One Size","options":["With Love BP","One Size"],"price":5000,"weight":0,"compare_at_price":5000,"inventory_management":"shopify","barcode":null,"featured_media":{"alt":null,"id":70645919449254,"position":1,"preview_image":{"aspect_ratio":0.8,"height":2048,"width":1639,"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198"}},"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}],"images":["\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198","\/\/www.bostonproper.com\/cdn\/shop\/files\/2_af52291f-802d-4184-8815-c64ea15071dd.jpg?v=1791009198"],"featured_image":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198","options":["Color","Size"],"media":[{"alt":null,"id":70645919449254,"position":1,"preview_image":{"aspect_ratio":0.8,"height":2048,"width":1639,"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198"},"aspect_ratio":0.8,"height":2048,"media_type":"image","src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2CT8071_SET_e6f3e3ce-5a5f-451b-bc3b-ea1f8f71d236.jpg?v=1791009198","width":1639},{"alt":null,"id":70645919482022,"position":2,"preview_image":{"aspect_ratio":0.8,"height":2048,"width":1639,"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2_af52291f-802d-4184-8815-c64ea15071dd.jpg?v=1791009198"},"aspect_ratio":0.8,"height":2048,"media_type":"image","src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2_af52291f-802d-4184-8815-c64ea15071dd.jpg?v=1791009198","width":1639}],"requires_selling_plan":false,"selling_plan_groups":[],"content":null},
24569        options_with_values: [{"name":"Color","position":1,"values":["With Love BP"]},{"name":"Size","position":2,"values":["One Size"]}]
24570      });
24571    
24572  
24573</script>
24573
24574
24575<script
24576  type='module'
24577  src='https://cdn.shopify.com/extensions/01a0f186-e064-7986-a442-4245fc3eb6fb/discount-kit-634/assets/dk_core.js'
24578></script>
24578
24579<!-- END app snippet -->
24580
24581
24582
24583
24584</div>
24584<script src="https://cdn.shopify.com/storefront/standard-actions.js" type="module" data-source-attribution="shopify.standard_actions"></script>
24584
24585</body>
24586</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.