1<!doctype html> 2<html 3 4 lang="en" 5> 6 <head><link 7 rel="icon" 8 type="image/png" 9 href="//www.bostonproper.com/cdn/shop/files/bp-favicon_2026.jpg?crop=center&height=32&v=1785357425&width=32" 10 > 11 12 13 14<meta charset="utf-8"> 15<meta 16 http-equiv="X-UA-Compatible" 17 content="IE=edge" 18> 19<meta 20 name="viewport" 21 content="width=device-width,initial-scale=1" 22> 23<meta 24 name="view-transition" 25 content="same-origin" 26> 27<meta 28 name="theme-color" 29 content="" 30> 31 32<meta 33 property="og:site_name" 34 content="Boston Proper" 35> 36<meta 37 property="og:url" 38 content="https://www.bostonproper.com/blogs/styleedit" 39> 40<meta 41 property="og:title" 42 content="Style Edit Blog: Womenâs Fashion & Style Tips" 43> 44<meta 45 property="og:type" 46 content="website" 47> 48<meta 49 property="og:description" 50 content="Discover style tips, fashion trends, and outfit inspiration on the Style Edit blog. Stay chic and confident with Boston Proper." 51><meta 52 property="og:image" 53 content="http://www.bostonproper.com/cdn/shop/files/BOS-Symbol-sunset.jpg?v=1785346585" 54 > 55 <meta 56 property="og:image:secure_url" 57 content="https://www.bostonproper.com/cdn/shop/files/BOS-Symbol-sunset.jpg?v=1785346585" 58 > 59 <meta 60 property="og:image:width" 61 content="910" 62 > 63 <meta 64 property="og:image:height" 65 content="753" 66 ><meta 67 name="twitter:card" 68 content="summary_large_image" 69> 70<meta 71 name="twitter:title" 72 content="Style Edit Blog: Womenâs Fashion & Style Tips" 73> 74<meta 75 name="twitter:description" 76 content="Discover style tips, fashion trends, and outfit inspiration on the Style Edit blog. Stay chic and confident with Boston Proper." 77> 78 79<title> 80 Style Edit Blog: Womenâs Fashion & Style Tips 81 – Boston Proper</title> 82 83<link 84 rel="canonical" 85 href="https://www.bostonproper.com/blogs/styleedit" 86> 87 88 89 <meta 90 name="description" 91 content="Discover style tips, fashion trends, and outfit inspiration on the Style Edit blog. Stay chic and confident with Boston Proper." 92 > 93 94<link href="//www.bostonproper.com/cdn/shop/t/1516/assets/overflow-list.css?v=16727044177065489451790192827" as="style" rel="preload"> 95<link href="//www.bostonproper.com/cdn/shop/t/1516/assets/base.css?v=80415010869825589501790192827" rel="stylesheet" type="text/css" media="all" /> 96 97<link 98 rel="preload" 99 as="font" 100 href="//www.bostonproper.com/cdn/fonts/inter/inter_n4.b2a3f24c19b4de56e8871f609e73ca7f6d2e2bb9.woff2" 101 type="font/woff2" 102 crossorigin 103 fetchpriority="low" 104 ><link 105 rel="preload" 106 as="font" 107 href="//www.bostonproper.com/cdn/fonts/inter/inter_n5.d7101d5e168594dd06f56f290dd759fba5431d97.woff2" 108 type="font/woff2" 109 crossorigin 110 fetchpriority="low" 111 ><link 112 rel="preload" 113 as="font" 114 href="//www.bostonproper.com/cdn/fonts/inter/inter_n7.02711e6b374660cfc7915d1afc1c204e633421e4.woff2" 115 type="font/woff2" 116 crossorigin 117 fetchpriority="low" 118 ><link 119 rel="preload" 120 as="font" 121 href="//www.bostonproper.com/cdn/fonts/inter/inter_n7.02711e6b374660cfc7915d1afc1c204e633421e4.woff2" 122 type="font/woff2" 123 crossorigin 124 fetchpriority="low" 125 > 126 127
128<script async crossorigin fetchpriority="high" src="/cdn/shopifycloud/importmap-polyfill/es-modules-shim.2.4.0.js"></script>
vendor: 1 bytes, line 128
128
129<script type="importmap"> 130 { 131 "imports": { 132 "@theme/overflow-list": "//www.bostonproper.com/cdn/shop/t/1516/assets/overflow-list.js?v=46858356770684902511790192827", 133 "@theme/product-title": "//www.bostonproper.com/cdn/shop/t/1516/assets/product-title-truncation.js?v=81744426891537421781790192827", 134 "@theme/component": "//www.bostonproper.com/cdn/shop/t/1516/assets/component.js?v=184240237101443119871790192827", 135 "@theme/dialog": "//www.bostonproper.com/cdn/shop/t/1516/assets/dialog.js?v=150888536568694194021790192827", 136 "@theme/events": "//www.bostonproper.com/cdn/shop/t/1516/assets/events.js?v=1118589085892804011790192827", 137 "@theme/focus": "//www.bostonproper.com/cdn/shop/t/1516/assets/focus.js?v=60436577539430446401790192827", 138 "@theme/morph": "//www.bostonproper.com/cdn/shop/t/1516/assets/morph.js?v=104045809772310330131790192827", 139 "@theme/paginated-list": "//www.bostonproper.com/cdn/shop/t/1516/assets/paginated-list.js?v=95298315036233333871790192827", 140 "@theme/performance": "//www.bostonproper.com/cdn/shop/t/1516/assets/performance.js?v=171015751390534793081790192827", 141 "@theme/product-form": "//www.bostonproper.com/cdn/shop/t/1516/assets/product-form.js?v=138228271698465017521790192827", 142 "@theme/recently-viewed-products": "//www.bostonproper.com/cdn/shop/t/1516/assets/recently-viewed-products.js?v=94729125001750262651790192827", 143 "@theme/scrolling": "//www.bostonproper.com/cdn/shop/t/1516/assets/scrolling.js?v=162288454571026455011790192827", 144 "@theme/section-renderer": "//www.bostonproper.com/cdn/shop/t/1516/assets/section-renderer.js?v=170547751348887101551790192827", 145 "@theme/section-hydration": "//www.bostonproper.com/cdn/shop/t/1516/assets/section-hydration.js?v=108434990705342316311790192827", 146 "@theme/money-formatting": "//www.bostonproper.com/cdn/shop/t/1516/assets/money-formatting.js?v=182191346160333327151790192827", 147 "@theme/utilities": "//www.bostonproper.com/cdn/shop/t/1516/assets/utilities.js?v=28506172887375975941790192827", 148 "@theme/variant-picker": "//www.bostonproper.com/cdn/shop/t/1516/assets/variant-picker.js?v=137587803232570873901790192827", 149 "@theme/media-gallery": "//www.bostonproper.com/cdn/shop/t/1516/assets/media-gallery.js?v=14624021005636302161790192827", 150 "@theme/quick-add": "//www.bostonproper.com/cdn/shop/t/1516/assets/quick-add.js?v=141968020560480616261790192827", 151 "@theme/paginated-list-aspect-ratio": "//www.bostonproper.com/cdn/shop/t/1516/assets/paginated-list-aspect-ratio.js?v=25254270272143792451790192827", 152 "@theme/popover-polyfill": "//www.bostonproper.com/cdn/shop/t/1516/assets/popover-polyfill.js?v=119029313658895111201790192827", 153 "@theme/component-quantity-selector": "//www.bostonproper.com/cdn/shop/t/1516/assets/component-quantity-selector.js?v=67906657287482036641790192827", 154 "@theme/comparison-slider": "//www.bostonproper.com/cdn/shop/t/1516/assets/comparison-slider.js?v=106705562947035711941790192827", 155 "@theme/sticky-add-to-cart": "//www.bostonproper.com/cdn/shop/t/1516/assets/sticky-add-to-cart.js?v=48956925339276737091790192827", 156 "@theme/fly-to-cart": "//www.bostonproper.com/cdn/shop/t/1516/assets/fly-to-cart.js?v=48483246440248933081790192827" 157 } 158 } 159</script>
159 160
161<script 162 src="//www.bostonproper.com/cdn/shop/t/1516/assets/view-transitions.js?v=41230751666534493481790192827" 163 async 164 165></script>
165 166 167<link 168 rel="modulepreload" 169 href="//www.bostonproper.com/cdn/shop/t/1516/assets/utilities.js?v=28506172887375975941790192827" 170 fetchpriority="low" 171> 172<link 173 rel="modulepreload" 174 href="//www.bostonproper.com/cdn/shop/t/1516/assets/component.js?v=184240237101443119871790192827" 175 fetchpriority="low" 176> 177<link 178 rel="modulepreload" 179 href="//www.bostonproper.com/cdn/shop/t/1516/assets/section-renderer.js?v=170547751348887101551790192827" 180 fetchpriority="low" 181> 182<link 183 rel="modulepreload" 184 href="//www.bostonproper.com/cdn/shop/t/1516/assets/section-hydration.js?v=108434990705342316311790192827" 185 fetchpriority="low" 186> 187<link 188 rel="modulepreload" 189 href="//www.bostonproper.com/cdn/shop/t/1516/assets/morph.js?v=104045809772310330131790192827" 190 fetchpriority="low" 191> 192 193 194 195<link 196 rel="modulepreload" 197 href="//www.bostonproper.com/cdn/shop/t/1516/assets/focus.js?v=60436577539430446401790192827" 198 fetchpriority="low" 199> 200<link 201 rel="modulepreload" 202 href="//www.bostonproper.com/cdn/shop/t/1516/assets/recently-viewed-products.js?v=94729125001750262651790192827" 203 fetchpriority="low" 204> 205<link 206 rel="modulepreload" 207 href="//www.bostonproper.com/cdn/shop/t/1516/assets/scrolling.js?v=162288454571026455011790192827" 208 fetchpriority="low" 209> 210<link 211 rel="modulepreload" 212 href="//www.bostonproper.com/cdn/shop/t/1516/assets/events.js?v=1118589085892804011790192827" 213 fetchpriority="low" 214>
215<script 216 src="//www.bostonproper.com/cdn/shop/t/1516/assets/popover-polyfill.js?v=119029313658895111201790192827" 217 type="module" 218 fetchpriority="low" 219></script>
vendor: 1 bytes, line 219
219
220<script 221 src="//www.bostonproper.com/cdn/shop/t/1516/assets/overflow-list.js?v=46858356770684902511790192827" 222 type="module" 223 fetchpriority="low" 224></script>
vendor: 1 bytes, line 224
224
225<script 226 src="//www.bostonproper.com/cdn/shop/t/1516/assets/quick-add.js?v=141968020560480616261790192827" 227 type="module" 228 fetchpriority="low" 229></script>
229 230 231
231<script 232 src="//www.bostonproper.com/cdn/shop/t/1516/assets/cart-discount.js?v=107077853990124422021790192827" 233 type="module" 234 fetchpriority="low" 235 ></script>
235 236 237
238<script 239 src="//www.bostonproper.com/cdn/shop/t/1516/assets/dialog.js?v=150888536568694194021790192827" 240 type="module" 241 fetchpriority="low" 242></script>
vendor: 1 bytes, line 242
242
243<script 244 src="//www.bostonproper.com/cdn/shop/t/1516/assets/variant-picker.js?v=137587803232570873901790192827" 245 type="module" 246 fetchpriority="low" 247></script>
vendor: 1 bytes, line 247
247
248<script 249 src="//www.bostonproper.com/cdn/shop/t/1516/assets/product-card.js?v=28695665944407642501790192827" 250 type="module" 251 fetchpriority="low" 252></script>
vendor: 1 bytes, line 252
252
253<script 254 src="//www.bostonproper.com/cdn/shop/t/1516/assets/product-form.js?v=138228271698465017521790192827" 255 type="module" 256 fetchpriority="low" 257></script>
vendor: 1 bytes, line 257
257
258<script 259 src="//www.bostonproper.com/cdn/shop/t/1516/assets/fly-to-cart.js?v=48483246440248933081790192827" 260 type="module" 261 fetchpriority="low" 262></script>
vendor: 1 bytes, line 262
262
263<script 264 src="//www.bostonproper.com/cdn/shop/t/1516/assets/accordion-custom.js?v=97588419883090888471790192827" 265 type="module" 266 fetchpriority="low" 267></script>
vendor: 1 bytes, line 267
267
268<script 269 src="//www.bostonproper.com/cdn/shop/t/1516/assets/media.js?v=37825095869491791421790192827" 270 type="module" 271 fetchpriority="low" 272></script>
vendor: 1 bytes, line 272
272
273<script 274 src="//www.bostonproper.com/cdn/shop/t/1516/assets/product-price.js?v=83480980452100801711790192827" 275 type="module" 276 fetchpriority="low" 277></script>
vendor: 1 bytes, line 277
277
278<script 279 src="//www.bostonproper.com/cdn/shop/t/1516/assets/product-sku.js?v=121804655373531320511790192827" 280 type="module" 281 fetchpriority="low" 282></script>
vendor: 1 bytes, line 282
282
283<script 284 src="//www.bostonproper.com/cdn/shop/t/1516/assets/product-title-truncation.js?v=81744426891537421781790192827" 285 type="module" 286 fetchpriority="low" 287></script>
vendor: 1 bytes, line 287
287
288<script 289 src="//www.bostonproper.com/cdn/shop/t/1516/assets/product-inventory.js?v=81520546963552472391790192827" 290 type="module" 291 fetchpriority="low" 292></script>
vendor: 1 bytes, line 292
292
293<script 294 src="//www.bostonproper.com/cdn/shop/t/1516/assets/show-more.js?v=94563802205717136101790192827" 295 type="module" 296 fetchpriority="low" 297></script>
vendor: 1 bytes, line 297
297
298<script 299 src="//www.bostonproper.com/cdn/shop/t/1516/assets/slideshow.js?v=168726587398279102001790192827" 300 type="module" 301 fetchpriority="low" 302></script>
vendor: 1 bytes, line 302
302
303<script 304 src="//www.bostonproper.com/cdn/shop/t/1516/assets/layered-slideshow.js?v=30135417790894624731790192827" 305 type="module" 306 fetchpriority="low" 307></script>
vendor: 1 bytes, line 307
307
308<script 309 src="//www.bostonproper.com/cdn/shop/t/1516/assets/anchored-popover.js?v=95953304814728754461790192827" 310 type="module" 311 fetchpriority="low" 312></script>
vendor: 1 bytes, line 312
312
313<script 314 src="//www.bostonproper.com/cdn/shop/t/1516/assets/floating-panel.js?v=151277338116891310371790192827" 315 type="module" 316 fetchpriority="low" 317></script>
vendor: 1 bytes, line 317
317
318<script 319 src="//www.bostonproper.com/cdn/shop/t/1516/assets/video-background.js?v=25237992823806706551790192827" 320 type="module" 321 fetchpriority="low" 322></script>
vendor: 1 bytes, line 322
322
323<script 324 src="//www.bostonproper.com/cdn/shop/t/1516/assets/component-quantity-selector.js?v=67906657287482036641790192827" 325 type="module" 326 fetchpriority="low" 327></script>
vendor: 1 bytes, line 327
327
328<script 329 src="//www.bostonproper.com/cdn/shop/t/1516/assets/media-gallery.js?v=14624021005636302161790192827" 330 type="module" 331 fetchpriority="low" 332></script>
vendor: 1 bytes, line 332
332
333<script 334 src="//www.bostonproper.com/cdn/shop/t/1516/assets/rte-formatter.js?v=40306132146590816021790192827" 335 type="module" 336 fetchpriority="low" 337></script>
vendor: 1 bytes, line 337
337
338<script 339 src="//www.bostonproper.com/cdn/shop/t/1516/assets/volume-pricing.js?v=15442793518842484731790192827" 340 type="module" 341 fetchpriority="low" 342></script>
vendor: 1 bytes, line 342
342
343<script 344 src="//www.bostonproper.com/cdn/shop/t/1516/assets/price-per-item.js?v=144512917617120124431790192827" 345 type="module" 346 fetchpriority="low" 347></script>
vendor: 1 bytes, line 347
347
348<script 349 src="//www.bostonproper.com/cdn/shop/t/1516/assets/volume-pricing-info.js?v=94479640769665442661790192827" 350 type="module" 351 fetchpriority="low" 352></script>
352 353 354 355
355<script 356 src="//www.bostonproper.com/cdn/shop/t/1516/assets/localization.js?v=15585934801240115691790192827" 357 type="module" 358 fetchpriority="low" 359 ></script>
359 360 361 362 363
364<script 365 src="//www.bostonproper.com/cdn/shop/t/1516/assets/auto-close-details.js?v=58350291535404441581790192827" 366 defer="defer" 367></script>
367 368
369<script> 370 const Theme = { 371 translations: { 372 placeholder_image: `Placeholder image`, 373 added: `Added`, 374 recipient_form_fields_visible: `Recipient form fields are now visible`, 375 recipient_form_fields_hidden: `Recipient form fields are now hidden`, 376 recipient_form_error: `There was an error with the form submission`, 377 items_added_to_cart_one: `1 item added to cart`, 378 items_added_to_cart_other: `{{ count }} items added to cart`, 379 cart_count: `Total items in cart`, 380 }, 381 routes: { 382 cart_add_url: '/cart/add.js', 383 cart_change_url: '/cart/change', 384 cart_update_url: '/cart/update', 385 cart_url: '/cart', 386 predictive_search_url: '/search/suggest', 387 search_url: '/search', 388 }, 389 template: { 390 name: 'blog', 391 }, 392 }; 393</script>
393 394<style data-shopify> 395@font-face { 396 font-family: Inter; 397 font-weight: 400; 398 font-style: normal; 399 font-display: swap; 400 src: url("//www.bostonproper.com/cdn/fonts/inter/inter_n4.b2a3f24c19b4de56e8871f609e73ca7f6d2e2bb9.woff2") format("woff2"), 401 url("//www.bostonproper.com/cdn/fonts/inter/inter_n4.af8052d517e0c9ffac7b814872cecc27ae1fa132.woff") format("woff"); 402} 403@font-face { 404 font-family: Inter; 405 font-weight: 700; 406 font-style: normal; 407 font-display: swap; 408 src: url("//www.bostonproper.com/cdn/fonts/inter/inter_n7.02711e6b374660cfc7915d1afc1c204e633421e4.woff2") format("woff2"), 409 url("//www.bostonproper.com/cdn/fonts/inter/inter_n7.6dab87426f6b8813070abd79972ceaf2f8d3b012.woff") format("woff"); 410} 411@font-face { 412 font-family: Inter; 413 font-weight: 400; 414 font-style: italic; 415 font-display: swap; 416 src: url("//www.bostonproper.com/cdn/fonts/inter/inter_i4.feae1981dda792ab80d117249d9c7e0f1017e5b3.woff2") format("woff2"), 417 url("//www.bostonproper.com/cdn/fonts/inter/inter_i4.62773b7113d5e5f02c71486623cf828884c85c6e.woff") format("woff"); 418} 419@font-face { 420 font-family: Inter; 421 font-weight: 700; 422 font-style: italic; 423 font-display: swap; 424 src: url("//www.bostonproper.com/cdn/fonts/inter/inter_i7.b377bcd4cc0f160622a22d638ae7e2cd9b86ea4c.woff2") format("woff2"), 425 url("//www.bostonproper.com/cdn/fonts/inter/inter_i7.7c69a6a34e3bb44fcf6f975857e13b9a9b25beb4.woff") format("woff"); 426} 427@font-face { 428 font-family: Inter; 429 font-weight: 500; 430 font-style: normal; 431 font-display: swap; 432 src: url("//www.bostonproper.com/cdn/fonts/inter/inter_n5.d7101d5e168594dd06f56f290dd759fba5431d97.woff2") format("woff2"), 433 url("//www.bostonproper.com/cdn/fonts/inter/inter_n5.5332a76bbd27da00474c136abb1ca3cbbf259068.woff") format("woff"); 434} 435@font-face { 436 font-family: Inter; 437 font-weight: 500; 438 font-style: italic; 439 font-display: swap; 440 src: url("//www.bostonproper.com/cdn/fonts/inter/inter_i5.4474f48e6ab2b1e01aa2b6d942dd27fa24f2d99f.woff2") format("woff2"), 441 url("//www.bostonproper.com/cdn/fonts/inter/inter_i5.493dbd6ee8e49f4ad722ebb68d92f201af2c2f56.woff") format("woff"); 442} 443 444 445 :root { 446 /* Page Layout */ 447 --sidebar-width: 25rem; 448 --narrow-content-width: 36rem; 449 --normal-content-width: 42rem; 450 --wide-content-width: 46rem; 451 --narrow-page-width: 90rem; 452 --normal-page-width: 120rem; 453 --wide-page-width: 150rem; 454 455 /* Section Heights */ 456 --section-height-small: 15rem; 457 --section-height-medium: 25rem; 458 --section-height-large: 35rem; 459 460 @media screen and (min-width: 40em) { 461 --section-height-small: 40svh; 462 --section-height-medium: 55svh; 463 --section-height-large: 70svh; 464 } 465 466 @media screen and (min-width: 60em) { 467 --section-height-small: 50svh; 468 --section-height-medium: 65svh; 469 --section-height-large: 80svh; 470 } 471 472 /* Letter spacing */ 473 --letter-spacing-sm: 0.06em; 474 --letter-spacing-md: 0.13em; 475 476 /* Font families */ 477 --font-body--family: Inter, sans-serif; 478 --font-body--style: normal; 479 --font-body--weight: 400; 480 --font-subheading--family: Inter, sans-serif; 481 --font-subheading--style: normal; 482 --font-subheading--weight: 500; 483 --font-heading--family: Inter, sans-serif; 484 --font-heading--style: normal; 485 --font-heading--weight: 700; 486 --font-accent--family: Inter, sans-serif; 487 --font-accent--style: normal; 488 --font-accent--weight: 700; 489 490 /* Margin sizes */ 491 --font-heading--spacing: 0.25em; 492 --font-h1--spacing: var(--font-heading--spacing); 493 --font-h2--spacing: var(--font-heading--spacing); 494 --font-h3--spacing: var(--font-heading--spacing); 495 --font-h4--spacing: var(--font-heading--spacing); 496 --font-h5--spacing: var(--font-heading--spacing); 497 --font-h6--spacing: var(--font-heading--spacing); 498 --font-paragraph--spacing: 0.5em; 499 500 /* Heading colors */ 501 --font-h1--color: var(--color-foreground-heading); 502 --font-h2--color: var(--color-foreground-heading); 503 --font-h3--color: var(--color-foreground-heading); 504 --font-h4--color: var(--color-foreground-heading); 505 --font-h5--color: var(--color-foreground-heading); 506 --font-h6--color: var(--color-foreground-heading); 507 508 /** Z-Index / Layering */ 509 --layer-section-background: -2; 510 --layer-lowest: -1; 511 --layer-base: 0; 512 --layer-flat: 1; 513 --layer-raised: 2; 514 --layer-heightened: 4; 515 --layer-sticky: 8; 516 --layer-window-overlay: 10; 517 --layer-header-menu: 12; 518 --layer-overlay: 16; 519 --layer-menu-drawer: 18; 520 --layer-temporary: 20; 521 522 /* Max-width / Measure */ 523 --max-width--body-normal: 32.5em; 524 --max-width--body-narrow: 22.75em; 525 526 --max-width--heading-normal: 32.5em; 527 --max-width--heading-narrow: 19.5em; 528 529 --max-width--display-normal: 13em; 530 --max-width--display-narrow: 9.75em; 531 --max-width--display-tight: 3.25em; 532 533 /* Letter-spacing / Tracking */ 534 --letter-spacing--display-tight: -0.03em; 535 --letter-spacing--display-normal: 0em; 536 --letter-spacing--display-loose: 0.03em; 537 538 --letter-spacing--heading-tight: -0.03em; 539 --letter-spacing--heading-normal: 0em; 540 --letter-spacing--heading-loose: 0.03em; 541 542 --letter-spacing--body-tight: -0.03em; 543 --letter-spacing--body-normal: 0em; 544 --letter-spacing--body-loose: 0.03em; 545 546 /* Line height / Leading */ 547 --line-height: 1; 548 549 --line-height--display-tight: 1; 550 --line-height--display-normal: 1.1; 551 --line-height--display-loose: 1.2; 552 553 --line-height--heading-tight: 1.15; 554 --line-height--heading-normal: 1.25; 555 --line-height--heading-loose: 1.35; 556 557 --line-height--body-tight: 1.2; 558 --line-height--body-normal: 1.4; 559 --line-height--body-loose: 1.6; 560 561 /* Typography presets */ 562 --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); 563 564 /* Hardcoded font sizes */ 565 --font-size--3xs: 0.625rem; 566 --font-size--2xs: 0.75rem; 567 --font-size--xs: 0.8125rem; 568 --font-size--sm: 0.875rem; 569 --font-size--md: 1rem; 570 --font-size--lg: 1.125rem; 571 --font-size--xl: 1.25rem; 572 --font-size--2xl: 1.5rem; 573 --font-size--3xl: 2rem; 574 --font-size--4xl: 2.5rem; 575 --font-size--5xl: 3rem; 576 --font-size--6xl: 3.5rem; 577 578 /* Menu font sizes */ 579 --menu-font-sm--size: 0.875rem; 580 --menu-font-sm--line-height: calc(1.1 + 0.5 * min(16 / 14)); 581 --menu-font-md--size: 1rem; 582 --menu-font-md--line-height: calc(1.1 + 0.5 * min(16 / 16)); 583 --menu-font-lg--size: 1.125rem; 584 --menu-font-lg--line-height: calc(1.1 + 0.5 * min(16 / 18)); 585 --menu-font-xl--size: 1.25rem; 586 --menu-font-xl--line-height: calc(1.1 + 0.5 * min(16 / 20)); 587 --menu-font-2xl--size: 1.75rem; 588 --menu-font-2xl--line-height: calc(1.1 + 0.5 * min(16 / 28)); 589 590 /* Colors */ 591 --color-error: #8B0000; 592 --color-success: #006400; 593 --color-white: #FFFFFF; 594 --color-white-rgb: 255 255 255; 595 --color-black: #000000; 596 --color-instock: #3ED660; 597 --color-lowstock: #EE9441; 598 --color-outofstock: #C8C8C8; 599 600 /* Opacity */ 601 --opacity-5: 0.05; 602 --opacity-8: 0.08; 603 --opacity-10: 0.1; 604 --opacity-15: 0.15; 605 --opacity-20: 0.2;
606 --opacity-25: 0.25; 607 --opacity-30: 0.3; 608 --opacity-40: 0.4; 609 --opacity-50: 0.5; 610 --opacity-60: 0.6; 611 --opacity-70: 0.7; 612 --opacity-80: 0.8; 613 --opacity-85: 0.85; 614 --opacity-90: 0.9; 615 --opacity-subdued-text: var(--opacity-70); 616 617 --shadow-button: 0 2px 3px rgb(0 0 0 / 20%); 618 --gradient-image-overlay: linear-gradient(to top, rgb(0 0 0 / 0.5), transparent); 619 620 /* Spacing */ 621 --margin-3xs: 0.125rem; 622 --margin-2xs: 0.3rem; 623 --margin-xs: 0.5rem; 624 --margin-sm: 0.7rem; 625 --margin-md: 0.8rem; 626 --margin-lg: 1rem; 627 --margin-xl: 1.25rem; 628 --margin-2xl: 1.5rem; 629 --margin-3xl: 1.75rem; 630 --margin-4xl: 2rem; 631 --margin-5xl: 3rem; 632 --margin-6xl: 5rem; 633 634 --scroll-margin: 50px; 635 636 --padding-3xs: 0.125rem; 637 --padding-2xs: 0.25rem; 638 --padding-xs: 0.5rem; 639 --padding-sm: 0.7rem; 640 --padding-md: 0.8rem; 641 --padding-lg: 1rem; 642 --padding-xl: 1.25rem; 643 --padding-2xl: 1.5rem; 644 --padding-3xl: 1.75rem; 645 --padding-4xl: 2rem; 646 --padding-5xl: 3rem; 647 --padding-6xl: 4rem; 648 649 --gap-3xs: 0.125rem; 650 --gap-2xs: 0.3rem; 651 --gap-xs: 0.5rem; 652 --gap-sm: 0.7rem; 653 --gap-md: 0.9rem; 654 --gap-lg: 1rem; 655 --gap-xl: 1.25rem; 656 --gap-2xl: 2rem; 657 --gap-3xl: 3rem; 658 659 --spacing-scale-sm: 0.6; 660 --spacing-scale-md: 0.7; 661 --spacing-scale-default: 1.0; 662 663 /* Checkout buttons gap */ 664 --checkout-button-gap: 10px; 665 666 /* Borders */ 667 --style-border-width: 1px; 668 --style-border-radius-xs: 0.2rem; 669 --style-border-radius-sm: 0.6rem; 670 --style-border-radius-md: 0.8rem; 671 --style-border-radius-50: 50%; 672 --style-border-radius-lg: 1rem; 673 --style-border-radius-pills: 40px; 674 --style-border-radius-inputs: 4px; 675 --style-border-radius-buttons-primary: 14px; 676 --style-border-radius-buttons-secondary: 14px; 677 --style-border-width-primary: 0px; 678 --style-border-width-secondary: 1px; 679 --style-border-width-inputs: 1px; 680 --style-border-radius-popover: 14px; 681 --style-border-popover: 1px none rgb(var(--color-border-rgb) / 50%); 682 --style-border-drawer: 1px none rgb(var(--color-border-rgb) / 50%); 683 --style-border-swatch-opacity: 10%; 684 --style-border-swatch-width: 1px; 685 --style-border-swatch-style: solid; 686 687 /* Animation */ 688 --ease-out-cubic: cubic-bezier(0.33, 1, 0.68, 1); 689 --ease-out-quad: cubic-bezier(0.32, 0.72, 0, 1); 690 --ease-in-out-quad: cubic-bezier(0.455, 0.03, 0.515, 0.955); 691 --animation-speed-fast: 0.0625s; 692 --animation-speed: 0.125s; 693 --animation-speed-slow: 0.2s; 694 --animation-speed-medium: 0.15s; 695 --animation-easing: ease-in-out; 696 --animation-slideshow-easing: cubic-bezier(0.4, 0, 0.2, 1); 697 --drawer-animation-speed: 0.2s; 698 --animation-values-slow: var(--animation-speed-slow) var(--animation-easing); 699 --animation-values: var(--animation-speed) var(--animation-easing); 700 --animation-values-fast: var(--animation-speed-fast) var(--animation-easing); 701 --animation-values-allow-discrete: var(--animation-speed) var(--animation-easing) allow-discrete; 702 --animation-timing-hover: cubic-bezier(0.25, 0.46, 0.45, 0.94); 703 --animation-timing-active: cubic-bezier(0.5, 0, 0.75, 0); 704 --animation-timing-bounce: cubic-bezier(0.34, 1.56, 0.64, 1); 705 --animation-timing-default: cubic-bezier(0, 0, 0.2, 1); 706 --animation-timing-fade-in: cubic-bezier(0.16, 1, 0.3, 1); 707 --animation-timing-fade-out: cubic-bezier(0.4, 0, 0.2, 1); 708 /* Spring definitions suffixed with perceptual duration (d<ms>) and bounce (b<%>)*/ 709 --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%); 710 --spring-d300-b0-duration: 0.4980s; 711 --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%); 712 --spring-d280-b0-duration: 0.4648s; 713 --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%); 714 --spring-d260-b0-duration: 0.4316s; 715 --spring-d220-b0-easing: linear( 716 0, 717 0.0093 1.37%, 718 0.0696 4.12%, 719 0.4667 15.09%, 720 0.6322 20.58%, 721 0.6986 23.32%, 722 0.7793 27.44%, 723 0.8219 30.18%, 724 0.8721, 725 0.9089 38.42%, 726 0.9427, 727 0.9644, 728 0.978 54.88%, 729 0.9881 61.74%, 730 0.9944 69.97%, 731 0.998 80.95%, 732 0.9996 98.78% 733 ); 734 --spring-d220-b0-duration: 0.3818s; 735 --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%); 736 --spring-d180-b0-duration: 0.2988s; 737 738 /* View transitions */ 739 /* View transition old */ 740 --view-transition-old-main-content: var(--animation-speed) var(--animation-easing) both fadeOut; 741 742 /* View transition new */ 743 --view-transition-new-main-content: var(--animation-speed) var(--animation-easing) both fadeIn, var(--animation-speed) var(--animation-easing) both slideInTopViewTransition; 744 745 /* Focus */ 746 --focus-outline-width: 0.09375rem; 747 --focus-outline-offset: 0.2em; 748 749 /* Badges */ 750 --badge-blob-padding-block: 1px; 751 --badge-blob-padding-inline: 12px 8px; 752 --badge-rectangle-padding-block: 1px; 753 --badge-rectangle-padding-inline: 6px; 754 @media screen and (min-width: 750px) { 755 --badge-blob-padding-block: 4px; 756 --badge-blob-padding-inline: 16px 12px; 757 --badge-rectangle-padding-block: 4px; 758 --badge-rectangle-padding-inline: 10px; 759 } 760 761 /* Icons */ 762 --icon-size-2xs: 0.6rem; 763 --icon-size-xs: 0.85rem; 764 --icon-size-sm: 1.25rem; 765 --icon-size-md: 1.375rem; 766 --icon-size-lg: 1.5rem; 767 --icon-stroke-width: 1.5px; 768 769 /* Input */ 770 --input-email-min-width: 200px; 771 --input-search-max-width: 650px; 772 --input-padding-y: 0.8rem; 773 --input-padding-x: 0.8rem; 774 --input-padding: var(--input-padding-y) var(--input-padding-x); 775 --input-box-shadow-width: var(--style-border-width-inputs); 776 --input-box-shadow: 0 0 0 var(--input-box-shadow-width) var(--color-input-border); 777 --input-box-shadow-focus: 0 0 0 calc(var(--input-box-shadow-width) + 0.5px) var(--color-input-border); 778 --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10)); 779 --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5)); 780 --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50));
781 --input-textarea-min-height: 55px; 782 783 /* Checkbox */ 784 --checkbox-size: 22px; 785 --checkbox-border-radius: 7px; 786 --checkbox-border: 1px solid rgb(var(--color-foreground-rgb) / var(--opacity-35-55)); 787 --checkbox-label-padding: 8px; 788 789 @media screen and (min-width: 750px) { 790 --checkbox-size: 16px; 791 --checkbox-border-radius: 5px; 792 --checkbox-label-padding: 6px; 793 } 794 795 /* Button size */ 796 --button-size-sm: 30px; 797 --button-size-md: 36px; 798 --button-size: var(--minimum-touch-target); 799 --button-padding-inline: 24px; 800 --button-padding-block: 16px; 801 802 /* Button font-family */ 803 --button-font-family-primary: var(--font-body--family); 804 --button-font-family-secondary: var(--font-body--family); 805 806 /* Button text case */ 807 --button-text-case: ; 808 --button-text-case-primary: default; 809 --button-text-case-secondary: default; 810 811 /* Borders */ 812 --border-color: rgb(var(--color-border-rgb) / var(--opacity-50)); 813 --border-width-sm: 1px; 814 --border-width-md: 2px; 815 --border-width-lg: 5px; 816 --border-radius-sm: 0.25rem; 817 818 /* Drawers */ 819 --drawer-inline-padding: 25px; 820 --drawer-menu-inline-padding: 2.5rem; 821 --drawer-header-block-padding: 20px; 822 --drawer-content-block-padding: 10px; 823 --drawer-header-desktop-top: 0rem; 824 --drawer-padding: calc(var(--padding-sm) + 7px); 825 --drawer-height: 100dvh; 826 --drawer-width: 95vw; 827 --drawer-max-width: 500px; 828 829 /* Variant Picker Swatches */ 830 --variant-picker-swatch-width-unitless: 34; 831 --variant-picker-swatch-height-unitless: 34; 832 --variant-picker-swatch-width: 34px; 833 --variant-picker-swatch-height: 34px; 834 --variant-picker-swatch-radius: 32px; 835 --variant-picker-border-width: 1px; 836 --variant-picker-border-style: solid; 837 --variant-picker-border-opacity: 10%; 838 839 /* Variant Picker Buttons */ 840 --variant-picker-button-radius: 14px; 841 --variant-picker-button-border-width: 1px; 842 843 /* Slideshow */ 844 --slideshow-controls-size: 3.5rem; 845 --slideshow-controls-icon: 2rem; 846 --peek-next-slide-size: 3rem; 847 848 /* Utilities */ 849 --backdrop-opacity: 0.15; 850 --backdrop-color-rgb: var(--color-shadow-rgb); 851 --minimum-touch-target: 44px; 852 --disabled-opacity: 0.5; 853 --skeleton-opacity: 0.025; 854 855 /* Shapes */ 856 --shape--circle: circle(50% at center); 857 --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%); 858 --shape--diamond: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); 859 --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
859% 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%); 860 861 /* Buy buttons */ 862 --height-buy-buttons: calc(var(--padding-lg) * 2 + var(--icon-size-sm)); 863 864 /* Card image width and height variables */ 865 --card-width-small: 10rem; 866 867 --height-small: 10rem; 868 --height-medium: 11.5rem; 869 --height-large: 13rem; 870 --height-full: 100vh; 871 872 @media screen and (min-width: 750px) { 873 --height-small: 17.5rem; 874 --height-medium: 21.25rem; 875 --height-large: 25rem; 876 } 877 878 /* Modal */ 879 --modal-max-height: 65dvh; 880 --quick-add-modal-height: min(38.5rem, 96vh); 881 --quick-add-modal-width: min(54rem, 96vw); 882 --quick-add-modal-gallery-width: 24rem; 883 884 /* Card styles for search */ 885 --card-bg-hover: rgb(var(--color-foreground-rgb) / var(--opacity-5)); 886 --card-border-hover: rgb(var(--color-foreground-rgb) / var(--opacity-30)); 887 --card-border-focus: rgb(var(--color-foreground-rgb) / var(--opacity-10)); 888 889 /* Cart */ 890 --cart-primary-font-family: var(--font-body--family); 891 --cart-primary-font-style: var(--font-body--style); 892 --cart-primary-font-weight: var(--font-body--weight); 893 --cart-secondary-font-family: var(--font-secondary--family); 894 --cart-secondary-font-style: var(--font-secondary--style); 895 --cart-secondary-font-weight: var(--font-secondary--weight); 896 } 897</style> 898 899 900<style data-shopify> 901 902 903 :root, 904 905 906 907 .color-scheme-1 { 908 --color-background: rgb(254 255 250 / 1.0); 909 /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */ 910 --color-background-rgb: 254 255 250; 911 --opacity-5-15: 0.05; 912 --opacity-10-25: 0.1; 913 --opacity-35-55: 0.35; 914 --opacity-40-60: 0.4; 915 --opacity-30-60: 0.3; 916 --color-foreground: rgb(0 0 0 / 0.81); 917 --color-foreground-rgb: 0 0 0; 918 --color-foreground-heading: rgb(0 0 0 / 1.0); 919 --color-foreground-heading-rgb: 0 0 0; 920 --color-primary: rgb(0 0 0 / 0.81); 921 --color-primary-rgb: 0 0 0; 922 --color-primary-hover: rgb(0 0 0 / 1.0); 923 --color-primary-hover-rgb: 0 0 0; 924 --color-border: rgb(0 0 0 / 0.06); 925 --color-border-rgb: 0 0 0; 926 --color-shadow: rgb(0 0 0 / 1.0); 927 --color-shadow-rgb: 0 0 0; 928 --color-primary-button-text: rgb(255 255 255 / 1.0); 929 --color-primary-button-background: rgb(0 0 0 / 1.0); 930 --color-primary-button-border: rgb(0 0 0 / 1.0); 931 --color-primary-button-hover-text: rgb(255 255 255 / 1.0); 932 --color-primary-button-hover-background: rgb(51 51 51 / 1.0); 933 --color-primary-button-hover-border: rgb(0 0 0 / 1.0); 934 --color-secondary-button-text: rgb(0 0 0 / 1.0); 935 --color-secondary-button-background: rgb(0 0 0 / 0.0); 936 --color-secondary-button-border: rgb(0 0 0 / 1.0); 937 --color-secondary-button-hover-text: rgb(51 51 51 / 1.0); 938 --color-secondary-button-hover-background: rgb(250 250 250 / 1.0); 939 --color-secondary-button-hover-border: rgb(51 51 51 / 1.0); 940 --color-input-background: rgb(255 255 255 / 0.78); 941 --color-input-text: rgb(51 51 51 / 1.0); 942 --color-input-text-rgb: 51 51 51; 943 --color-input-border: rgb(223 223 223 / 1.0); 944 --color-input-hover-background: rgb(0 0 0 / 0.01); 945 --color-variant-background: rgb(255 255 255 / 1.0); 946 --color-variant-border: rgb(0 0 0 / 0.13); 947 --color-variant-text: rgb(0 0 0 / 1.0); 948 --color-variant-text-rgb: 0 0 0; 949 --color-variant-hover-background: rgb(245 245 245 / 1.0); 950 --color-variant-hover-text: rgb(0 0 0 / 1.0); 951 --color-variant-hover-border: rgb(230 230 230 / 1.0); 952 --color-selected-variant-background: rgb(0 0 0 / 1.0); 953 --color-selected-variant-border: rgb(0 0 0 / 1.0); 954 --color-selected-variant-text: rgb(255 255 255 / 1.0); 955 --color-selected-variant-hover-background: rgb(26 26 26 / 1.0); 956 --color-selected-variant-hover-text: rgb(255 255 255 / 1.0); 957 --color-selected-variant-hover-border: rgb(26 26 26 / 1.0); 958 959 --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10)); 960 --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15)); 961 --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50)); 962 --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60)); 963 --font-h1--color: var(--color-foreground-heading); 964 --font-h2--color: var(--color-foreground-heading); 965 --font-h3--color: var(--color-foreground-heading); 966 --font-h4--color: var(--color-foreground-heading); 967 --font-h5--color: var(--color-foreground-heading); 968 --font-h6--color: var(--color-foreground-heading); 969 970 /* Shadows */ 971 972 --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 973 974 975 --shadow-blur: 20px; 976 --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 977 978 } 979 980 981 982 983 .color-scheme-2 {
984 --color-background: rgb(245 245 245 / 1.0); 985 /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */ 986 --color-background-rgb: 245 245 245; 987 --opacity-5-15: 0.05; 988 --opacity-10-25: 0.1; 989 --opacity-35-55: 0.35; 990 --opacity-40-60: 0.4; 991 --opacity-30-60: 0.3; 992 --color-foreground: rgb(0 0 0 / 0.81); 993 --color-foreground-rgb: 0 0 0; 994 --color-foreground-heading: rgb(0 0 0 / 1.0); 995 --color-foreground-heading-rgb: 0 0 0; 996 --color-primary: rgb(0 0 0 / 0.81); 997 --color-primary-rgb: 0 0 0; 998 --color-primary-hover: rgb(255 255 255 / 1.0); 999 --color-primary-hover-rgb: 255 255 255; 1000 --color-border: rgb(223 223 223 / 1.0); 1001 --color-border-rgb: 223 223 223; 1002 --color-shadow: rgb(0 0 0 / 1.0); 1003 --color-shadow-rgb: 0 0 0; 1004 --color-primary-button-text: rgb(255 255 255 / 1.0); 1005 --color-primary-button-background: rgb(0 0 0 / 1.0); 1006 --color-primary-button-border: rgb(0 0 0 / 1.0); 1007 --color-primary-button-hover-text: rgb(255 255 255 / 1.0); 1008 --color-primary-button-hover-background: rgb(51 51 51 / 1.0); 1009 --color-primary-button-hover-border: rgb(51 51 51 / 1.0); 1010 --color-secondary-button-text: rgb(0 0 0 / 1.0); 1011 --color-secondary-button-background: rgb(0 0 0 / 0.0); 1012 --color-secondary-button-border: rgb(0 0 0 / 1.0); 1013 --color-secondary-button-hover-text: rgb(0 0 0 / 1.0); 1014 --color-secondary-button-hover-background: rgb(255 255 255 / 0.36); 1015 --color-secondary-button-hover-border: rgb(51 51 51 / 0.73); 1016 --color-input-background: rgb(0 0 0 / 0.0); 1017 --color-input-text: rgb(0 0 0 / 0.53); 1018 --color-input-text-rgb: 0 0 0; 1019 --color-input-border: rgb(0 0 0 / 0.13); 1020 --color-input-hover-background: rgb(255 255 255 / 0.36); 1021 --color-variant-background: rgb(255 255 255 / 1.0); 1022 --color-variant-border: rgb(230 230 230 / 1.0); 1023 --color-variant-text: rgb(0 0 0 / 1.0); 1024 --color-variant-text-rgb: 0 0 0; 1025 --color-variant-hover-background: rgb(245 245 245 / 1.0); 1026 --color-variant-hover-text: rgb(0 0 0 / 1.0); 1027 --color-variant-hover-border: rgb(230 230 230 / 1.0); 1028 --color-selected-variant-background: rgb(0 0 0 / 1.0); 1029 --color-selected-variant-border: rgb(0 0 0 / 1.0); 1030 --color-selected-variant-text: rgb(255 255 255 / 1.0); 1031 --color-selected-variant-hover-background: rgb(26 26 26 / 1.0); 1032 --color-selected-variant-hover-text: rgb(255 255 255 / 1.0); 1033 --color-selected-variant-hover-border: rgb(26 26 26 / 1.0); 1034 1035 --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10)); 1036 --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15)); 1037 --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50)); 1038 --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60)); 1039 --font-h1--color: var(--color-foreground-heading); 1040 --font-h2--color: var(--color-foreground-heading); 1041 --font-h3--color: var(--color-foreground-heading); 1042 --font-h4--color: var(--color-foreground-heading); 1043 --font-h5--color: var(--color-foreground-heading); 1044 --font-h6--color: var(--color-foreground-heading); 1045 1046 /* Shadows */ 1047 1048 --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1049 1050 1051 --shadow-blur: 20px; 1052 --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1053 1054 } 1055 1056 1057 1058 1059 .color-scheme-3 { 1060 --color-background: rgb(238 241 234 / 1.0); 1061 /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */ 1062 --color-background-rgb: 238 241 234; 1063 --opacity-5-15: 0.05; 1064 --opacity-10-25: 0.1; 1065 --opacity-35-55: 0.35; 1066 --opacity-40-60: 0.4; 1067 --opacity-30-60: 0.3; 1068 --color-foreground: rgb(0 0 0 / 0.81); 1069 --color-foreground-rgb: 0 0 0; 1070 --color-foreground-heading: rgb(0 0 0 / 1.0); 1071 --color-foreground-heading-rgb: 0 0 0; 1072 --color-primary: rgb(0 0 0 / 0.81); 1073 --color-primary-rgb: 0 0 0; 1074 --color-primary-hover: rgb(0 0 0 / 1.0); 1075 --color-primary-hover-rgb: 0 0 0; 1076 --color-border: rgb(0 0 0 / 0.81); 1077 --color-border-rgb: 0 0 0; 1078 --color-shadow: rgb(0 0 0 / 1.0); 1079 --color-shadow-rgb: 0 0 0; 1080 --color-primary-button-text: rgb(255 255 255 / 1.0); 1081 --color-primary-button-background: rgb(0 0 0 / 1.0); 1082 --color-primary-button-border: rgb(0 0 0 / 1.0); 1083 --color-primary-button-hover-text: rgb(255 255 255 / 1.0); 1084 --color-primary-button-hover-background: rgb(51 51 51 / 1.0); 1085 --color-primary-button-hover-border: rgb(51 51 51 / 1.0); 1086 --color-secondary-button-text: rgb(0 0 0 / 1.0); 1087 --color-secondary-button-background: rgb(0 0 0 / 0.0); 1088 --color-secondary-button-border: rgb(0 0 0 / 1.0); 1089 --color-secondary-button-hover-text: rgb(0 0 0 / 0.81); 1090 --color-secondary-button-hover-background: rgb(255 255 255 / 0.36); 1091 --color-secondary-button-hover-border: rgb(0 0 0 / 0.81); 1092 --color-input-background: rgb(0 0 0 / 0.0); 1093 --color-input-text: rgb(0 0 0 / 0.81); 1094 --color-input-text-rgb: 0 0 0; 1095 --color-input-border: rgb(0 0 0 / 0.81); 1096 --color-input-hover-background: rgb(255 255 255 / 0.36); 1097 --color-variant-background: rgb(255 255 255 / 1.0); 1098 --color-variant-border: rgb(230 230 230 / 1.0); 1099 --color-variant-text: rgb(0 0 0 / 1.0); 1100 --color-variant-text-rgb: 0 0 0; 1101 --color-variant-hover-background: rgb(245 245 245 / 1.0); 1102 --color-variant-hover-text: rgb(0 0 0 / 1.0); 1103 --color-variant-hover-border: rgb(230 230 230 / 1.0); 1104 --color-selected-variant-background: rgb(0 0 0 / 1.0); 1105 --color-selected-variant-border: rgb(0 0 0 / 1.0); 1106 --color-selected-variant-text: rgb(255 255 255 / 1.0); 1107 --color-selected-variant-hover-background: rgb(26 26 26 / 1.0); 1108 --color-selected-variant-hover-text: rgb(255 255 255 / 1.0); 1109 --color-selected-variant-hover-border: rgb(26 26 26 / 1.0); 1110 1111 --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10)); 1112 --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15)); 1113 --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50)); 1114 --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60)); 1115 --font-h1--color: var(--color-foreground-heading); 1116 --font-h2--color: var(--color-foreground-heading); 1117 --font-h3--color: var(--color-foreground-heading); 1118 --font-h4--color: var(--color-foreground-heading); 1119 --font-h5--color: var(--color-foreground-heading); 1120 --font-h6--color: var(--color-foreground-heading); 1121 1122 /* Shadows */ 1123 1124 --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1125 1126 1127 --shadow-blur: 20px; 1128 --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1129 1130 } 1131 1132 1133 1134 1135 .color-scheme-4 { 1136 --color-background: rgb(225 237 245 / 1.0); 1137 /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */ 1138 --color-background-rgb: 225 237 245; 1139 --opacity-5-15: 0.05; 1140 --opacity-10-25: 0.1; 1141 --opacity-35-55: 0.35; 1142 --opacity-40-60: 0.4; 1143 --opacity-30-60: 0.3; 1144 --color-foreground: rgb(0 0 0 / 0.81); 1145 --color-foreground-rgb: 0 0 0; 1146 --color-foreground-heading: rgb(0 0 0 / 1.0); 1147 --color-foreground-heading-rgb: 0 0 0; 1148 --color-primary: rgb(0 0 0 / 0.81); 1149 --color-primary-rgb: 0 0 0; 1150 --color-primary-hover: rgb(0 0 0 / 1.0); 1151 --color-primary-hover-rgb: 0 0 0; 1152 --color-border: rgb(29 54 134 / 0.5); 1153 --color-border-rgb: 29 54 134; 1154 --color-shadow: rgb(0 0 0 / 1.0); 1155 --color-shadow-rgb: 0 0 0; 1156 --color-primary-button-text: rgb(255 255 255 / 1.0); 1157 --color-primary-button-background: rgb(0 0 0 / 1.0); 1158 --color-primary-button-border: rgb(29 54 134 / 1.0); 1159 --color-primary-button-hover-text: rgb(255 255 255 / 1.0); 1160 --color-primary-button-hover-background: rgb(51 51 51 / 1.0); 1161 --color-primary-button-hover-border: rgb(0 0 0 / 1.0); 1162 --color-secondary-button-text: rgb(0 0 0 / 1.0); 1163 --color-secondary-button-background: rgb(0 0 0 / 0.0); 1164 --color-secondary-button-border: rgb(0 0 0 / 1.0); 1165 --color-secondary-button-hover-text: rgb(0 0 0 / 0.81); 1166 --color-secondary-button-hover-background: rgb(255 255 255 / 0.36); 1167 --color-secondary-button-hover-border: rgb(0 0 0 / 0.81); 1168 --color-input-background: rgb(0 0 0 / 0.0); 1169 --color-input-text: rgb(0 0 0 / 0.81); 1170 --color-input-text-rgb: 0 0 0; 1171 --color-input-border: rgb(0 0 0 / 0.81); 1172 --color-input-hover-background: rgb(255 255 255 / 0.36); 1173 --color-variant-background: rgb(255 255 255 / 1.0); 1174 --color-variant-border: rgb(230 230 230 / 1.0); 1175 --color-variant-text: rgb(0 0 0 / 1.0); 1176 --color-variant-text-rgb: 0 0 0; 1177 --color-variant-hover-background: rgb(245 245 245 / 1.0); 1178 --color-variant-hover-text: rgb(0 0 0 / 1.0); 1179 --color-variant-hover-border: rgb(230 230 230 / 1.0); 1180 --color-selected-variant-background: rgb(0 0 0 / 1.0); 1181 --color-selected-variant-border: rgb(0 0 0 / 1.0); 1182 --color-selected-variant-text: rgb(255 255 255 / 1.0); 1183 --color-selected-variant-hover-background: rgb(26 26 26 / 1.0); 1184 --color-selected-variant-hover-text: rgb(255 255 255 / 1.0); 1185 --color-selected-variant-hover-border: rgb(26 26 26 / 1.0); 1186 1187 --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10)); 1188 --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15)); 1189 --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50)); 1190 --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60)); 1191 --font-h1--color: var(--color-foreground-heading); 1192 --font-h2--color: var(--color-foreground-heading); 1193 --font-h3--color: var(--color-foreground-heading); 1194 --font-h4--color: var(--color-foreground-heading); 1195 --font-h5--color: var(--color-foreground-heading); 1196 --font-h6--color: var(--color-foreground-heading); 1197 1198 /* Shadows */ 1199 1200 --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1201 1202 1203 --shadow-blur: 20px; 1204 --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1205 1206 } 1207 1208 1209 1210 1211 .color-scheme-5 { 1212 --color-background: rgb(51 51 51 / 1.0); 1213 /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */ 1214 --color-background-rgb: 51 51 51; 1215 --opacity-5-15: 0.15; 1216 --opacity-10-25: 0.25; 1217 --opacity-35-55: 0.55; 1218 --opacity-40-60: 0.6; 1219 --opacity-30-60: 0.6; 1220 --color-foreground: rgb(255 255 255 / 1.0); 1221 --color-foreground-rgb: 255 255 255; 1222 --color-foreground-heading: rgb(255 255 255 / 1.0); 1223 --color-foreground-heading-rgb: 255 255 255; 1224 --color-primary: rgb(255 255 255 / 1.0); 1225 --color-primary-rgb: 255 255 255; 1226 --color-primary-hover: rgb(255 255 255 / 0.69); 1227 --color-primary-hover-rgb: 255 255 255; 1228 --color-border: rgb(255 255 255 / 0.69); 1229 --color-border-rgb: 255 255 255; 1230 --color-shadow: rgb(0 0 0 / 1.0); 1231 --color-shadow-rgb: 0 0 0; 1232 --color-primary-button-text: rgb(0 0 0 / 1.0); 1233 --color-primary-button-background: rgb(255 255 255 / 1.0); 1234 --color-primary-button-border: rgb(255 255 255 / 1.0); 1235 --color-primary-button-hover-text: rgb(255 255 255 / 1.0); 1236 --color-primary-button-hover-background: rgb(0 0 0 / 1.0); 1237 --color-primary-button-hover-border: rgb(0 0 0 / 1.0); 1238 --color-secondary-button-text: rgb(255 255 255 / 1.0); 1239 --color-secondary-button-background: rgb(0 0 0 / 0.0); 1240 --color-secondary-button-border: rgb(255 255 255 / 0.69); 1241 --color-secondary-button-hover-text: rgb(255 255 255 / 0.93); 1242 --color-secondary-button-hover-background: rgb(255 255 255 / 0.04); 1243 --color-secondary-button-hover-border: rgb(255 255 255 / 0.69); 1244 --color-input-background: rgb(51 51 51 / 1.0); 1245 --color-input-text: rgb(255 255 255 / 0.93); 1246 --color-input-text-rgb: 255 255 255; 1247 --color-input-border: rgb(255 255 255 / 0.69); 1248 --color-input-hover-background: rgb(255 255 255 / 0.04); 1249 --color-variant-background: rgb(255 255 255 / 1.0); 1250 --color-variant-border: rgb(230 230 230 / 1.0); 1251 --color-variant-text: rgb(0 0 0 / 1.0); 1252 --color-variant-text-rgb: 0 0 0; 1253 --color-variant-hover-background: rgb(245 245 245 / 1.0); 1254 --color-variant-hover-text: rgb(0 0 0 / 1.0); 1255 --color-variant-hover-border: rgb(230 230 230 / 1.0); 1256 --color-selected-variant-background: rgb(0 0 0 / 1.0); 1257 --color-selected-variant-border: rgb(0 0 0 / 1.0); 1258 --color-selected-variant-text: rgb(255 255 255 / 1.0); 1259 --color-selected-variant-hover-background: rgb(26 26 26 / 1.0); 1260 --color-selected-variant-hover-text: rgb(255 255 255 / 1.0); 1261 --color-selected-variant-hover-border: rgb(26 26 26 / 1.0); 1262 1263 --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10)); 1264 --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15)); 1265 --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50)); 1266 --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60)); 1267 --font-h1--color: var(--color-foreground-heading); 1268 --font-h2--color: var(--color-foreground-heading); 1269 --font-h3--color: var(--color-foreground-heading); 1270 --font-h4--color: var(--color-foreground-heading); 1271 --font-h5--color: var(--color-foreground-heading); 1272 --font-h6--color: var(--color-foreground-heading); 1273 1274 /* Shadows */ 1275 1276 --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1277 1278 1279 --shadow-blur: 20px; 1280 --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1281 1282 } 1283 1284 1285 1286 1287 .color-scheme-6 { 1288 --color-background: rgb(0 0 0 / 0.0); 1289 /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */ 1290 --color-background-rgb: 0 0 0; 1291 --opacity-5-15: 0.15; 1292 --opacity-10-25: 0.25; 1293 --opacity-35-55: 0.55; 1294 --opacity-40-60: 0.6; 1295 --opacity-30-60: 0.6; 1296 --color-foreground: rgb(255 255 255 / 1.0); 1297 --color-foreground-rgb: 255 255 255; 1298 --color-foreground-heading: rgb(255 255 255 / 1.0); 1299 --color-foreground-heading-rgb: 255 255 255; 1300 --color-primary: rgb(255 255 255 / 1.0); 1301 --color-primary-rgb: 255 255 255; 1302 --color-primary-hover: rgb(255 255 255 / 0.69); 1303 --color-primary-hover-rgb: 255 255 255; 1304 --color-border: rgb(230 230 230 / 1.0); 1305 --color-border-rgb: 230 230 230; 1306 --color-shadow: rgb(0 0 0 / 1.0); 1307 --color-shadow-rgb: 0 0 0; 1308 --color-primary-button-text: rgb(0 0 0 / 1.0); 1309 --color-primary-button-background: rgb(255 255 255 / 1.0); 1310 --color-primary-button-border: rgb(255 255 255 / 1.0); 1311 --color-primary-button-hover-text: rgb(255 255 255 / 1.0); 1312 --color-primary-button-hover-background: rgb(0 0 0 / 1.0); 1313 --color-primary-button-hover-border: rgb(0 0 0 / 1.0); 1314 --color-secondary-button-text: rgb(255 255 255 / 1.0);
1314 1315 --color-secondary-button-background: rgb(0 0 0 / 0.0); 1316 --color-secondary-button-border: rgb(255 255 255 / 1.0); 1317 --color-secondary-button-hover-text: rgb(255 255 255 / 1.0); 1318 --color-secondary-button-hover-background: rgb(255 255 255 / 0.08); 1319 --color-secondary-button-hover-border: rgb(255 255 255 / 1.0); 1320 --color-input-background: rgb(255 255 255 / 1.0); 1321 --color-input-text: rgb(0 0 0 / 0.53); 1322 --color-input-text-rgb: 0 0 0; 1323 --color-input-border: rgb(0 0 0 / 0.13); 1324 --color-input-hover-background: rgb(250 250 250 / 1.0); 1325 --color-variant-background: rgb(255 255 255 / 1.0); 1326 --color-variant-border: rgb(230 230 230 / 1.0); 1327 --color-variant-text: rgb(0 0 0 / 1.0); 1328 --color-variant-text-rgb: 0 0 0; 1329 --color-variant-hover-background: rgb(245 245 245 / 1.0); 1330 --color-variant-hover-text: rgb(0 0 0 / 1.0); 1331 --color-variant-hover-border: rgb(230 230 230 / 1.0); 1332 --color-selected-variant-background: rgb(0 0 0 / 1.0); 1333 --color-selected-variant-border: rgb(0 0 0 / 1.0); 1334 --color-selected-variant-text: rgb(255 255 255 / 1.0); 1335 --color-selected-variant-hover-background: rgb(26 26 26 / 1.0); 1336 --color-selected-variant-hover-text: rgb(255 255 255 / 1.0); 1337 --color-selected-variant-hover-border: rgb(26 26 26 / 1.0); 1338 1339 --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10)); 1340 --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15)); 1341 --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50)); 1342 --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60)); 1343 --font-h1--color: var(--color-foreground-heading); 1344 --font-h2--color: var(--color-foreground-heading); 1345 --font-h3--color: var(--color-foreground-heading); 1346 --font-h4--color: var(--color-foreground-heading); 1347 --font-h5--color: var(--color-foreground-heading); 1348 --font-h6--color: var(--color-foreground-heading); 1349 1350 /* Shadows */ 1351 1352 --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1353 1354 1355 --shadow-blur: 20px; 1356 --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1357 1358 } 1359 1360 1361 1362 1363 .color-scheme-58084d4c-a86e-4d0a-855e-a0966e5043f7 { 1364 --color-background: rgb(0 0 0 / 0.0); 1365 /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */ 1366 --color-background-rgb: 0 0 0; 1367 --opacity-5-15: 0.15; 1368 --opacity-10-25: 0.25; 1369 --opacity-35-55: 0.55; 1370 --opacity-40-60: 0.6; 1371 --opacity-30-60: 0.6; 1372 --color-foreground: rgb(0 0 0 / 1.0); 1373 --color-foreground-rgb: 0 0 0; 1374 --color-foreground-heading: rgb(0 0 0 / 1.0); 1375 --color-foreground-heading-rgb: 0 0 0; 1376 --color-primary: rgb(0 0 0 / 1.0); 1377 --color-primary-rgb: 0 0 0; 1378 --color-primary-hover: rgb(0 0 0 / 0.53); 1379 --color-primary-hover-rgb: 0 0 0; 1380 --color-border: rgb(230 230 230 / 1.0); 1381 --color-border-rgb: 230 230 230; 1382 --color-shadow: rgb(0 0 0 / 1.0); 1383 --color-shadow-rgb: 0 0 0; 1384 --color-primary-button-text: rgb(255 255 255 / 1.0); 1385 --color-primary-button-background: rgb(0 0 0 / 1.0); 1386 --color-primary-button-border: rgb(0 0 0 / 1.0); 1387 --color-primary-button-hover-text: rgb(255 255 255 / 1.0); 1388 --color-primary-button-hover-background: rgb(51 51 51 / 1.0); 1389 --color-primary-button-hover-border: rgb(51 51 51 / 1.0); 1390 --color-secondary-button-text: rgb(0 0 0 / 1.0); 1391 --color-secondary-button-background: rgb(0 0 0 / 0.0); 1392 --color-secondary-button-border: rgb(0 0 0 / 1.0); 1393 --color-secondary-button-hover-text: rgb(51 51 51 / 1.0); 1394 --color-secondary-button-hover-background: rgb(250 250 250 / 1.0); 1395 --color-secondary-button-hover-border: rgb(51 51 51 / 1.0); 1396 --color-input-background: rgb(255 255 255 / 1.0); 1397 --color-input-text: rgb(0 0 0 / 0.53); 1398 --color-input-text-rgb: 0 0 0; 1399 --color-input-border: rgb(0 0 0 / 0.13); 1400 --color-input-hover-background: rgb(250 250 250 / 1.0); 1401 --color-variant-background: rgb(255 255 255 / 1.0); 1402 --color-variant-border: rgb(230 230 230 / 1.0); 1403 --color-variant-text: rgb(0 0 0 / 1.0); 1404 --color-variant-text-rgb: 0 0 0; 1405 --color-variant-hover-background: rgb(245 245 245 / 1.0); 1406 --color-variant-hover-text: rgb(0 0 0 / 1.0); 1407 --color-variant-hover-border: rgb(230 230 230 / 1.0); 1408 --color-selected-variant-background: rgb(0 0 0 / 1.0); 1409 --color-selected-variant-border: rgb(0 0 0 / 1.0); 1410 --color-selected-variant-text: rgb(255 255 255 / 1.0); 1411 --color-selected-variant-hover-background: rgb(26 26 26 / 1.0); 1412 --color-selected-variant-hover-text: rgb(255 255 255 / 1.0); 1413 --color-selected-variant-hover-border: rgb(26 26 26 / 1.0); 1414 1415 --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10)); 1416 --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15)); 1417 --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50)); 1418 --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60)); 1419 --font-h1--color: var(--color-foreground-heading); 1420 --font-h2--color: var(--color-foreground-heading); 1421 --font-h3--color: var(--color-foreground-heading); 1422 --font-h4--color: var(--color-foreground-heading); 1423 --font-h5--color: var(--color-foreground-heading); 1424 --font-h6--color: var(--color-foreground-heading); 1425 1426 /* Shadows */ 1427 1428 --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1429 1430 1431 --shadow-blur: 20px; 1432 --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1433 1434 } 1435 1436 1437 1438 1439 .color-scheme-515910f4-a3e9-48d3-8079-ac481ef96b10 { 1440 --color-background: rgb(254 255 250 / 1.0); 1441 /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */ 1442 --color-background-rgb: 254 255 250; 1443 --opacity-5-15: 0.05; 1444 --opacity-10-25: 0.1; 1445 --opacity-35-55: 0.35; 1446 --opacity-40-60: 0.4; 1447 --opacity-30-60: 0.3; 1448 --color-foreground: rgb(0 0 0 / 0.81); 1449 --color-foreground-rgb: 0 0 0; 1450 --color-foreground-heading: rgb(0 0 0 / 1.0); 1451 --color-foreground-heading-rgb: 0 0 0; 1452 --color-primary: rgb(0 0 0 / 0.81); 1453 --color-primary-rgb: 0 0 0; 1454 --color-primary-hover: rgb(0 0 0 / 1.0); 1455 --color-primary-hover-rgb: 0 0 0; 1456 --color-border: rgb(0 0 0 / 0.06); 1457 --color-border-rgb: 0 0 0; 1458 --color-shadow: rgb(0 0 0 / 1.0); 1459 --color-shadow-rgb: 0 0 0; 1460 --color-primary-button-text: rgb(255 255 255 / 1.0); 1461 --color-primary-button-background: rgb(0 0 0 / 1.0); 1462 --color-primary-button-border: rgb(0 0 0 / 1.0); 1463 --color-primary-button-hover-text: rgb(255 255 255 / 1.0); 1464 --color-primary-button-hover-background: rgb(51 51 51 / 1.0); 1465 --color-primary-button-hover-border: rgb(0 0 0 / 1.0); 1466 --color-secondary-button-text: rgb(0 0 0 / 1.0); 1467 --color-secondary-button-background: rgb(0 0 0 / 0.0); 1468 --color-secondary-button-border: rgb(0 0 0 / 1.0); 1469 --color-secondary-button-hover-text: rgb(51 51 51 / 1.0); 1470 --color-secondary-button-hover-background: rgb(250 250 250 / 1.0); 1471 --color-secondary-button-hover-border: rgb(51 51 51 / 1.0); 1472 --color-input-background: rgb(255 255 255 / 0.78); 1473 --color-input-text: rgb(51 51 51 / 1.0); 1474 --color-input-text-rgb: 51 51 51; 1475 --color-input-border: rgb(223 223 223 / 1.0); 1476 --color-input-hover-background: rgb(0 0 0 / 0.01); 1477 --color-variant-background: rgb(255 255 255 / 1.0); 1478 --color-variant-border: rgb(0 0 0 / 0.13); 1479 --color-variant-text: rgb(0 0 0 / 1.0); 1480 --color-variant-text-rgb: 0 0 0; 1481 --color-variant-hover-background: rgb(245 245 245 / 1.0); 1482 --color-variant-hover-text: rgb(0 0 0 / 1.0); 1483 --color-variant-hover-border: rgb(230 230 230 / 1.0); 1484 --color-selected-variant-background: rgb(0 0 0 / 1.0); 1485 --color-selected-variant-border: rgb(0 0 0 / 1.0); 1486 --color-selected-variant-text: rgb(255 255 255 / 1.0); 1487 --color-selected-variant-hover-background: rgb(26 26 26 / 1.0); 1488 --color-selected-variant-hover-text: rgb(255 255 255 / 1.0); 1489 --color-selected-variant-hover-border: rgb(26 26 26 / 1.0); 1490 1491 --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10)); 1492 --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15)); 1493 --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50)); 1494 --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60)); 1495 --font-h1--color: var(--color-foreground-heading); 1496 --font-h2--color: var(--color-foreground-heading); 1497 --font-h3--color: var(--color-foreground-heading); 1498 --font-h4--color: var(--color-foreground-heading); 1499 --font-h5--color: var(--color-foreground-heading); 1500 --font-h6--color: var(--color-foreground-heading); 1501 1502 /* Shadows */ 1503 1504 --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1505 1506 1507 --shadow-blur: 20px; 1508 --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1509 1510 } 1511 1512 1513 1514 1515 .color-scheme-d70ac8c4-eb3e-43d2-9c84-148cdbac2972 { 1516 --color-background: rgb(247 246 234 / 1.0); 1517 /* RGB values only to apply different opacities - Relative color values are not supported in iOS < 16.4 */ 1518 --color-background-rgb: 247 246 234; 1519 --opacity-5-15: 0.05; 1520 --opacity-10-25: 0.1; 1521 --opacity-35-55: 0.35; 1522 --opacity-40-60: 0.4; 1523 --opacity-30-60: 0.3; 1524 --color-foreground: rgb(23 22 9 / 1.0); 1525 --color-foreground-rgb: 23 22 9; 1526 --color-foreground-heading: rgb(23 22 9 / 1.0); 1527 --color-foreground-heading-rgb: 23 22 9; 1528 --color-primary: rgb(23 22 9 / 1.0); 1529 --color-primary-rgb: 23 22 9; 1530 --color-primary-hover: rgb(23 22 9 / 1.0); 1531 --color-primary-hover-rgb: 23 22 9; 1532 --color-border: rgb(0 0 0 / 0.06); 1533 --color-border-rgb: 0 0 0; 1534 --color-shadow: rgb(0 0 0 / 1.0); 1535 --color-shadow-rgb: 0 0 0; 1536 --color-primary-button-text: rgb(255 255 255 / 1.0); 1537 --color-primary-button-background: rgb(0 0 0 / 1.0); 1538 --color-primary-button-border: rgb(0 0 0 / 1.0); 1539 --color-primary-button-hover-text: rgb(255 255 255 / 1.0); 1540 --color-primary-button-hover-background: rgb(51 51 51 / 1.0); 1541 --color-primary-button-hover-border: rgb(0 0 0 / 1.0); 1542 --color-secondary-button-text: rgb(0 0 0 / 1.0); 1543 --color-secondary-button-background: rgb(0 0 0 / 0.0); 1544 --color-secondary-button-border: rgb(0 0 0 / 1.0); 1545 --color-secondary-button-hover-text: rgb(51 51 51 / 1.0); 1546 --color-secondary-button-hover-background: rgb(250 250 250 / 1.0); 1547 --color-secondary-button-hover-border: rgb(51 51 51 / 1.0); 1548 --color-input-background: rgb(255 255 255 / 0.78); 1549 --color-input-text: rgb(51 51 51 / 1.0); 1550 --color-input-text-rgb: 51 51 51; 1551 --color-input-border: rgb(223 223 223 / 1.0); 1552 --color-input-hover-background: rgb(0 0 0 / 0.01); 1553 --color-variant-background: rgb(255 255 255 / 1.0); 1554 --color-variant-border: rgb(0 0 0 / 0.13); 1555 --color-variant-text: rgb(0 0 0 / 1.0); 1556 --color-variant-text-rgb: 0 0 0; 1557 --color-variant-hover-background: rgb(245 245 245 / 1.0); 1558 --color-variant-hover-text: rgb(0 0 0 / 1.0); 1559 --color-variant-hover-border: rgb(230 230 230 / 1.0); 1560 --color-selected-variant-background: rgb(0 0 0 / 1.0); 1561 --color-selected-variant-border: rgb(0 0 0 / 1.0); 1562 --color-selected-variant-text: rgb(255 255 255 / 1.0); 1563 --color-selected-variant-hover-background: rgb(26 26 26 / 1.0); 1564 --color-selected-variant-hover-text: rgb(255 255 255 / 1.0); 1565 --color-selected-variant-hover-border: rgb(26 26 26 / 1.0); 1566 1567 --input-disabled-background-color: rgb(var(--color-foreground-rgb) / var(--opacity-10)); 1568 --input-disabled-border-color: rgb(var(--color-foreground-rgb) / var(--opacity-5-15)); 1569 --input-disabled-text-color: rgb(var(--color-foreground-rgb) / var(--opacity-50)); 1570 --color-foreground-muted: rgb(var(--color-foreground-rgb) / var(--opacity-60)); 1571 --font-h1--color: var(--color-foreground-heading); 1572 --font-h2--color: var(--color-foreground-heading); 1573 --font-h3--color: var(--color-foreground-heading); 1574 --font-h4--color: var(--color-foreground-heading); 1575 --font-h5--color: var(--color-foreground-heading); 1576 --font-h6--color: var(--color-foreground-heading); 1577 1578 /* Shadows */ 1579 1580 --shadow-drawer: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1581 1582 1583 --shadow-blur: 20px; 1584 --shadow-popover: 0px 4px 20px rgb(var(--color-shadow-rgb) / var(--opacity-15)); 1585 1586 } 1587 1588 1589 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 { 1590 color: var(--color-foreground); 1591 background-color: var(--color-background); 1592 } 1593</style> 1594<link rel="preload" as="font" href="//www.bostonproper.com/cdn/shop/t/1516/assets/MessinaSans-Regular.woff2?v=143903206038847021881790192827" type="font/woff2" crossorigin> 1595<link rel="preload" as="font" href="//www.bostonproper.com/cdn/shop/t/1516/assets/MessinaSans-Light.woff2?v=52620737138227856671790192827" type="font/woff2" crossorigin> 1596<link rel="preload" as="font" href="//www.bostonproper.com/cdn/shop/t/1516/assets/Signifier-Light.woff2?v=141591112723842981461790192827" type="font/woff2" crossorigin> 1597 1598<style data-shopify> 1599 /* Hide the browser's native clear "Ã" on type="search" inputs. BP renders 1600 its own custom clear icon (search drawer + /search page), so the native
1601 one showed as a duplicate Ã-on-à when the field had focus/hover. */ 1602 input[type="search"]::-webkit-search-cancel-button, 1603 input[type="search"]::-webkit-search-decoration { 1604 -webkit-appearance: none; 1605 appearance: none; 1606 display: none; 1607 } 1608 1609 /* Third-party tracking pixels (Dstillery, etc.) get injected as 1Ã1 1610 <img> elements appended to <body>. base.css's global 1611 `img { width: 100%; height: auto }` overrides their width/height 1612 attributes and stretches each one into a full-viewport-width square, 1613 dumping a huge blank block below the footer. Pin tracking pixels back 1614 to their intrinsic size and pull them out of flow â the beacon still 1615 fires (display/position don't block the request). 1616 1617 EXCLUSIONS: 1618 :not([class*="stylitics"]) â the Stylitics "How to Wear It" 1619 widget renders each tile as <img width="1" height="1" 1620 class="stylitics-ui-image â¦"> as a lazy-load placeholder and 1621 then resizes via the `--max-size` CSS variable. Without this 1622 exclusion the tiles stay pinned at 1Ã1. 1623 :not([data-testid]) â widget code typically carries a testid; 1624 tracking pixels don't. Defence-in-depth for other vendors 1625 that follow Stylitics's pattern. 1626 :not([loading]) â same. Lazy-loaded content images carry 1627 loading="lazy" / "eager"; tracking beacons don't. */ 1628 img[width="1"][height="1"]:not([class*="stylitics"]):not([data-testid]):not([loading]), 1629 img[width="0"][height="0"]:not([class*="stylitics"]):not([data-testid]):not([loading]) { 1630 width: 1px !important; 1631 height: 1px !important; 1632 position: absolute !important; 1633 pointer-events: none; 1634 } 1635 1636 @font-face { 1637 font-family: 'Messina Sans VF'; 1638 src: url('//www.bostonproper.com/cdn/shop/t/1516/assets/MessinaSans-Light.woff2?v=52620737138227856671790192827') format('woff2'); 1639 font-weight: 300; 1640 font-style: normal; 1641 font-display: swap; 1642 } 1643 @font-face { 1644 font-family: 'Messina Sans VF'; 1645 src: url('//www.bostonproper.com/cdn/shop/t/1516/assets/MessinaSans-Regular.woff2?v=143903206038847021881790192827') format('woff2'); 1646 font-weight: 400; 1647 font-style: normal; 1648 font-display: swap; 1649 } 1650 @font-face { 1651 font-family: 'Messina Sans VF'; 1652 src: url('//www.bostonproper.com/cdn/shop/t/1516/assets/MessinaSans-SemiBold.woff2?v=136830414853171670151790192827') format('woff2'); 1653 font-weight: 500 600; 1654 font-style: normal; 1655 font-display: swap; 1656 } 1657 @font-face { 1658 font-family: 'Messina Sans VF'; 1659 src: url('//www.bostonproper.com/cdn/shop/t/1516/assets/MessinaSans-Bold.woff2?v=151736514687132566241790192827') format('woff2'); 1660 font-weight: 700; 1661 font-style: normal; 1662 font-display: swap; 1663 } 1664 1665 @font-face { 1666 font-family: 'Signifier'; 1667 src: url('//www.bostonproper.com/cdn/shop/t/1516/assets/Signifier-Light.woff2?v=141591112723842981461790192827') format('woff2'); 1668 font-weight: 300; 1669 font-style: normal; 1670 font-display: swap; 1671 } 1672 @font-face { 1673 font-family: 'Signifier'; 1674 src: url('//www.bostonproper.com/cdn/shop/t/1516/assets/Signifier-Regular.woff2?v=76067088345373958441790192827') format('woff2'); 1675 font-weight: 400; 1676 font-style: normal; 1677 font-display: swap; 1678 } 1679 1680 /* ============================================================ 1681 Boston Proper design tokens. 1682 1683 Single source of truth for spacing, colors, and font families 1684 used by BP custom sections (bp-hero-slider, bp-shop-by-category, 1685 bp-product-carousel, ...). New sections SHOULD read from these 1686 tokens instead of hardcoding pixel values or hex colors. See 1687 CLAUDE.md for usage conventions. 1688 ============================================================ */ 1689 :root { 1690 /* Typography â Messina Sans VF is the site-wide default body 1691 family; Signifier is opt-in for display/heading copy. The five 1692 Horizon font-family vars are overridden here so every section 1693 inherits Messina Sans without per-section rules. */ 1694 --font-body--family: 'Messina Sans VF', system-ui, -apple-system, 'Segoe UI', sans-serif; 1695 --font-paragraph--family: 'Messina Sans VF', system-ui, -apple-system, 'Segoe UI', sans-serif; 1696 --font-subheading--family: 'Messina Sans VF', system-ui, -apple-system, 'Segoe UI', sans-serif; 1697 --font-heading--family: 'Messina Sans VF', system-ui, -apple-system, 'Segoe UI', sans-serif; 1698 --font-accent--family: 'Messina Sans VF', system-ui, -apple-system, 'Segoe UI', sans-serif; 1699 1700 --bp-font-body: 'Messina Sans VF', system-ui, -apple-system, 'Segoe UI', sans-serif; 1701 --bp-font-display: 'Signifier', 'Times New Roman', serif; 1702 1703 /* Spacing â values below are the MOBILE defaults; the desktop 1704 overrides live in the @media block at the bottom of :root. Section 1705 gutter is the horizontal distance from viewport edge to content; 1706 section gap is the gap between heading/nav rows or between cards 1707 in a track; card gap is the gap between elements inside a single 1708 card. */ 1709 --bp-section-pad-x: 16px; 1710 --bp-section-pad-y: 32px; 1711 --bp-section-gap: 16px; 1712 --bp-card-gap: 12px; 1713 1714 /* Colors */ 1715 --bp-color-text: #171609; 1716 --bp-color-bg-cream: #F7F6EA; 1717 --bp-color-bg-page: #FEFFFA; 1718 --bp-color-promo: #B5341B; 1719 /* #CA3D3D was only 4.55:1 on cream (razor-thin pass). Nudged to 1720 #C23636 (~5.0:1 on cream) for AA margin â imperceptibly darker red. */ 1721 --bp-color-sales-red: #C23636; 1722 --bp-color-cta-text: #FDFFFA; 1723 /* Sand CTA palette (Figma). Filled sand button + its inverse. Paired 1724 so `--sand` and `--sand-invert` just swap fg/bg. */ 1725 --bp-color-cta-sand: #E8DFD0; 1726 --bp-color-cta-sand-text: #2B241A; 1727 /* Body-copy grey darkened from #74736B (4.39:1 on cream / 4.14:1 on 1728 neutral â failed WCAG AA 4.5:1) to #666559, which clears 4.5:1 on 1729 white, cream and neutral. Disabled/OOS greys stay #74736B (exempt). */ 1730 --bp-color-body-copy: #666559; 1731 /* Muted/secondary ink for eyebrows, sub-labels, counts. Replaces the 1732 scattered rgba(23,22,9,0.45â0.55) usages that failed WCAG AA 4.5:1 1733 (~3.0â4.05:1). 0.65 â 4.9:1 on white/cream. */ 1734 --bp-color-text-muted: rgba(23, 22, 9, 0.65); 1735 --bp-color-neutral: #F0EFEA; 1736 1737 /* Type scale â single source for the sizes already used across the 1738 BP sections. Mobile values live here; desktop overrides are in the 1739 @media block below. Consumed by the .bp-fs-* utility classes and 1740 by the shared blocks (_bp-heading, _bp-body). */ 1741 --bp-fs-h1: 36px; /* hero / page lead (mobile of clamp(36,6vw,50)) */ 1742 --bp-fs-h2: 32px; /* section title (matches bp-fc/bp-itb/bp-grid mobile) */ 1743 --bp-fs-h3: 28px; 1744 --bp-fs-h4: 24px; 1745 --bp-fs-h5: 20px; 1746 --bp-fs-h6: 16px; 1747 1748 --bp-fs-body-lg: 17px; /* eyebrows + lead descriptions */ 1749 --bp-fs-body-md: 14px; /* default body copy */ 1750 --bp-fs-body-sm: 13px; /* fine print / meta */ 1751 --bp-fs-body-xs: 12px; /* micro labels */ 1752 } 1753 1754 /* Desktop spacing + type-scale overrides â single point of truth for 1755 the breakpoint where the BP layout shifts from mobile-compact to 1756 desktop-roomy. */ 1757 @media screen and (min-width: 1024px) { 1758 :root { 1759 --bp-section-pad-x: 40px; 1760 --bp-section-pad-y: 40px; 1761 --bp-section-gap: 20px; 1762 1763 --bp-fs-h1: 50px; /* hero */ 1764 --bp-fs-h2: 40px; /* section title (bp-fc h1 variant / bp-itb desktop) */ 1765 --bp-fs-h3: 32px; /* sub-section */ 1766 --bp-fs-h4: 24px; 1767 --bp-fs-h5: 20px; 1768 --bp-fs-h6: 18px; 1769 } 1770 } 1771 1772 /* Type-scale utility classes â apply just the size + tracking + 1773 leading. Family/colour come from the wrapping element so the same 1774 scale step works for display (Signifier) and body (Messina) copy. */ 1775 .bp-fs-h1 { font-size: var(--bp-fs-h1); letter-spacing: -0.02em; line-height: 110%; } 1776 .bp-fs-h2 { font-size: var(--bp-fs-h2); letter-spacing: -0.02em; line-height: 115%; } 1777 .bp-fs-h3 { font-size: var(--bp-fs-h3); letter-spacing: -0.02em; line-height: 120%; } 1778 .bp-fs-h4 { font-size: var(--bp-fs-h4); letter-spacing: -0.01em; line-height: 125%; } 1779 .bp-fs-h5 { font-size: var(--bp-fs-h5); line-height: 130%; } 1780 .bp-fs-h6 { font-size: var(--bp-fs-h6); line-height: 135%; } 1781 1782 .bp-fs-body-lg { font-size: var(--bp-fs-body-lg); line-height: 150%; } 1783 .bp-fs-body-md { font-size: var(--bp-fs-body-md); line-height: 145%; } 1784 .bp-fs-body-sm { font-size: var(--bp-fs-body-sm); line-height: 145%; } 1785 .bp-fs-body-xs { font-size: var(--bp-fs-body-xs); line-height: 145%; } 1786 1787 /* Topnav alignment: pin the header rows and announcement bar to the
1788 same 40px gutter as the BP custom sections. 1789 1790 Horizon's section system uses a 3-column grid: 1791 minmax(--page-margin, 1fr) 1792 --full-page-grid-central-column-width (clamped to --page-content-width = 1440px) 1793 minmax(--page-margin, 1fr) 1794 On viewports wider than ~1520px the side tracks grow above 1795 --page-margin to center the 1440px content column. So overriding 1796 --page-margin alone keeps the side tracks at 40px MIN but they 1797 still expand on wide screens. We also override the central column 1798 to "100% - 80px" so the 1fr side tracks collapse to exactly the 1799 40px minimum on every viewport, regardless of width. */ 1800 .header__row, 1801 .announcement-bar { 1802 --page-margin: var(--bp-section-pad-x); 1803 --full-page-grid-central-column-width: calc(100% - var(--bp-section-pad-x) * 2); 1804 } 1805 1806 /* Mobile header â keep the right-side icons (search / wishlist / 1807 bag) inside the viewport on narrow widths (â¤749px). The BP 1808 logo is an inline SVG (bp-logo.svg) rendered with a fixed 1809 --header-logo-image-width-mobile: 198px via inline style on 1810 the wrapper span. Combined with 4 à ~44px bookend cells that 1811 hold the hamburger / search / wishlist / bag, the total width 1812 hits 374px which is iPhone X (375px) viewport width â leaving 1813 no room for the bag icon. Cap the SVG container width with 1814 clamp() so the logo scales down on narrow viewports while 1815 staying close to 198px once there's enough room for it. */ 1816 @media screen and (max-width: 749px) { 1817 .header__row .header-logo { 1818 min-width: 0; 1819 max-width: 100%; 1820 overflow: hidden; 1821 } 1822 .header__row .header-logo__image, 1823 .header__row .header-logo__image--svg { 1824 width: clamp(140px, 42vw, 198px); 1825 height: auto; 1826 max-width: 100%; 1827 } 1828 .header__row .header-logo__image--svg svg { 1829 width: 100%; 1830 height: auto; 1831 max-width: 100%; 1832 display: block; 1833 } 1834 1835 /* The scroll-logo variant (small icon-only mark, "Header 1836 scroll-logo swap") must NOT be clamped up to wordmark width. 1837 It shares the .header-logo__image / .header-logo__image--svg 1838 classes with the original/inverse wordmark above, so the 1839 generic rule clamps it to 140-198px too. 44x44 (to match the 1840 right-side action icon hit area) looked oversized/misaligned 1841 in practice â 30x30 reads closer to the intended mark size 1842 while still being bigger than the original 23x18px inline 1843 value baked into blocks/_header-logo.liquid. object-fit: 1844 contain (images) / SVG's default preserveAspectRatio (inline 1845 fallback mark) keep the artwork itself from distorting. */ 1846 .header__row .header-logo__image-container--scroll .header-logo__image, 1847 .header__row .header-logo__image-container--scroll .header-logo__image--svg { 1848 width: 30px; 1849 height: 30px; 1850 max-width: none; 1851 } 1852 1853 .header__row .header-logo__image-container--scroll .header-logo__image--svg svg { 1854 width: 100%; 1855 height: 100%; 1856 max-width: none; 1857 } 1858 1859 /* Nudge to correct residual vertical misalignment of the scroll 1860 mark that flex-centering alone didn't fully resolve (mobile 1861 compact bar only â the original/inverse wordmark is unaffected 1862 since this is scoped to data-bp-nav='compact'). */ 1863 #header-component[data-bp-nav='compact'] .header__row .header-logo { 1864 padding-bottom: 6px; 1865 } 1866 } 1867 1868 /* Announcement bar slide alignment. 1869 1870 Horizon ships `.text-block--align-center` (and -left / -right) 1871 that set `--text-align: center` on the slide as a CSS variable, 1872 plus an inline `--text-align: center` from the schema, but no 1873 rule in `.text-block` actually consumes it back into the 1874 text-align property â only `.button` does. So the alignment 1875 class + inline var are inert without this consumer. 1876 1877 Apply text-align: var(--text-align) on the slide + paragraph so 1878 the schema's alignment choice takes effect. Defaults to center, 1879 which matches the design and is what the BP announcement bar 1880 always wants regardless of theme settings. */ 1881 .announcement-bar__slide, 1882 .announcement-bar__text { 1883 text-align: var(--text-align, center); 1884 } 1885 1886 /* Announcement bar pause/play control (Atlas parity). Pinned to the 1887 right edge of the bar; inherits the bar's text color. The button is 1888 rendered by sections/header-announcements.liquid and wired to 1889 Horizon's announcement-bar-component pause()/play(). */ 1890 .bp-announcement-playpause { 1891 position: absolute; 1892 right: 10px; 1893 top: 50%; 1894 transform: translateY(-50%); 1895 display: inline-flex; 1896 align-items: center; 1897 justify-content: center; 1898 width: 28px; 1899 height: 28px; 1900 padding: 0; 1901 background: transparent; 1902 border: 0; 1903 color: var(--color-foreground, currentColor); 1904 cursor: pointer; 1905 opacity: 0.75; 1906 transition: opacity 0.15s ease; 1907 } 1908 .bp-announcement-playpause:hover { opacity: 1; } 1909 /* Show exactly ONE glyph, reflecting the bar's actual state: the PAUSE bars 1910 while playing (click to pause), the PLAY triangle while paused (click to 1911 play). Driven off the bar's `[paused]` attribute so it stays correct 1912 through Horizon's re-render of the bar (which reset the JS `hidden` toggle, 1913 leaving both â or the wrong â icon showing). `!important` to beat the 1914 cascade rule that was overriding the play SVG's `hidden` (QA 7/27). */ 1915 .bp-announcement-playpause .bp-announcement-playpause__pause { display: block !important; } 1916 .bp-announcement-playpause .bp-announcement-playpause__play { display: none !important; } 1917 announcement-bar-component[paused] .bp-announcement-playpause__pause { display: none !important; } 1918 announcement-bar-component[paused] .bp-announcement-playpause__play { display: block !important; } 1919 /* The play/pause is pinned at the bar's right edge (right:10px), and 1920 Horizon's next carat also lands at the right edge (slideshow-arrows is 1921 `inset:0` with `justify-content:space-between`), so the two overlap â
1922 on desktop AND mobile (QA 7/27, Adrienne). Pull the arrow track's right 1923 edge in past the button so the next carat sits just left of it â Atlas 1924 order: [â¦slides] [next] [play/pause]. Only the next arrow moves (the prev 1925 stays at left via space-between); the centered slide text is a separate 1926 element and is unaffected. */ 1927 .announcement-bar slideshow-arrows { right: 40px; } 1928 1929 /* a11y (WCAG 2.1.1): keep the desktop mega-menu submenu open while 1930 keyboard focus is inside it. Horizon only reveals it on 1931 [aria-expanded='true'] + :hover (blocks/_header-menu.liquid:422), so 1932 tabbing into the panel could collapse it if the trigger's blur fires 1933 /deactivate before focus lands. Mirrors the :hover rule for focus. */ 1934 .menu-list__submenu:focus-within { 1935 --submenu-content-opacity: 1; 1936 visibility: visible; 1937 } 1938 1939 /* Keyboard-only down caret on top-level mega-menu items (menubar pattern â 1940 Alfred 7/27). Shown when a trigger is focused via the keyboard 1941 (:focus-visible) so keyboard users get a clear "opens a submenu" 1942 affordance; mouse hover/click never shows it. The caret is a CSS triangle 1943 in the link's own colour. bp-mega-hover.js wires the menubar behaviour 1944 (Enter/Space/ArrowDown opens, arrows navigate, Escape/Tab close). */ 1945 .menu-list__list-item.bp-menu-item-li > .menu-list__link[aria-haspopup='true'] { 1946 position: relative; 1947 } 1948 .menu-list__list-item.bp-menu-item-li > .menu-list__link[aria-haspopup='true']:focus-visible::after { 1949 content: ""; 1950 position: absolute; 1951 left: 50%; 1952 /* Centered just BELOW the label rather than inline after it â the inline 1953 caret overlapped the (fixed-min-width, centered) nav text (QA 7/27). */ 1954 top: calc(50% + 0.85em); 1955 transform: translate(-50%, -50%); 1956 width: 0; 1957 height: 0; 1958 border-inline: 4px solid transparent; 1959 border-top: 5px solid currentColor; 1960 pointer-events: none; 1961 } 1962 1963 /* Off-white page background (#FEFFFA, Figma spec) applied GLOBALLY â 1964 every template, not just index/collection (PDPs etc. were falling 1965 back to Horizon's default white). Sections that paint their own bg 1966 (cream bands, color schemes) still win over the body. The nav header 1967 rows are overridden to match. The announcement bar is intentionally 1968 NOT included â it's driven by its own merchant color scheme 1969 (header-announcements.liquid), and forcing off-white would erase a 1970 colored/dark promo bar. */ 1971 body { 1972 background-color: var(--bp-color-bg-page); 1973 } 1974 .header, 1975 .header__row, 1976 .header-wrapper { 1977 background-color: var(--bp-color-bg-page); 1978 } 1979 1980 /* QA 7/16 â the Figma page color is off-white #FEFFFA, not pure white. 1981 Horizon's DEFAULT color scheme (scheme-1) paints #ffffff, and that's 1982 what the PDP main sections, the header, and the mega-menu read through 1983 --color-background â so those surfaces stayed white despite the body 1984 override above. Remap just the white scheme to the BP page-bg token so 1985 every scheme-1 surface (all pages that use the default scheme) goes 1986 off-white. bp-fonts renders AFTER color-schemes in theme.liquid, so this 1987 wins on equal specificity without !important. The other schemes 1988 (grey #f5f5f5, cream #eef1ea, blue, dark) are intentional â left alone. */ 1989 .color-scheme-1 { 1990 --color-background: var(--bp-color-bg-page); 1991 --color-background-rgb: 254, 255, 250; 1992 } 1993 1994 /* ============================================================ 1995 BP Product Drawer â re-skin Horizon's quick-add modal as a 1996 right-side slide-in drawer. 1997 1998 MOVED to assets/bp-fonts-deferred.css (loaded non-render- 1999 blocking from theme.liquid). The drawer is a native <dialog 2000 class="quick-add-modal"> that is UA display:none until a card 2001 click opens it â an interaction-revealed surface â so its 2002 open/appearance rules don't need to block first paint. Horizon's 2003 own base .quick-add-modal styles stay render-blocking and keep 2004 the dialog functional. See CLAUDE.md "Topnav 40px gutter" note 2005 for the specificity-bumping pattern the moved rules use. 2006 ============================================================ */ 2007 2008 /* ============================================================
2009 BP product card â shared by bp-product-carousel and bp-collection 2010 (PLP). Lives here (not in either section) because both surfaces 2011 need the styles, and CSS in a section stylesheet block only loads 2012 when that section is rendered. 2013 ============================================================ */ 2014 .bp-card-host { display: contents; } 2015 2016 .bp-card { 2017 position: relative; 2018 display: flex; 2019 flex-direction: column; 2020 gap: var(--bp-card-gap); 2021 color: var(--bp-color-text); 2022 } 2023 2024 .bp-card__media { 2025 position: relative; 2026 display: block; 2027 aspect-ratio: 3 / 4; 2028 overflow: hidden; 2029 background: var(--bp-color-bg-cream); 2030 color: inherit; 2031 } 2032 .bp-card__media-link { 2033 position: absolute; 2034 inset: 0; 2035 display: block; 2036 text-decoration: none; 2037 color: inherit; 2038 } 2039 .bp-card__quick-add { 2040 position: absolute; 2041 width: 1px; 2042 height: 1px; 2043 overflow: hidden; 2044 clip: rect(0 0 0 0); 2045 pointer-events: none; 2046 } 2047 .bp-card__image { 2048 position: absolute; 2049 inset: 0; 2050 width: 100%; 2051 height: 100%; 2052 object-fit: cover; 2053 display: block; 2054 transition: opacity 0.4s ease; 2055 } 2056 .bp-card__image--secondary { opacity: 0; } 2057 /* Hover-swap default: when the merchant turns secondary-hover off 2058 via the §9.4 setting, the secondary image stays hidden. 2059 The primary only fades out when a secondary image is actually 2060 present (`:has(.bp-card__image--secondary)`). Single-image 2061 products (many Collective / Hanky Panky items) render no secondary 2062 element, so without this guard the primary faded to opacity 0 on 2063 hover and the card went BLANK â hover must keep showing the first 2064 image when there's nothing to swap to (QA 7/31). */ 2065 @media (hover: hover) { 2066 .bp-card[data-bp-card-secondary-hover='true'] .bp-card__media:has(.bp-card__image--secondary):hover .bp-card__image--primary { opacity: 0; } 2067 .bp-card[data-bp-card-secondary-hover='true'] .bp-card__media:hover .bp-card__image--secondary { opacity: 1; } 2068 } 2069 2070 .bp-card__badges { 2071 position: absolute; 2072 top: 12px; 2073 left: 12px; 2074 z-index: 2; 2075 display: flex; 2076 flex-direction: column; 2077 align-items: flex-start; 2078 gap: 6px; 2079 } 2080 2081 .bp-card__badge { 2082 background: var(--bp-color-bg-cream); 2083 color: var(--bp-color-text); 2084 padding: 4px 10px; 2085 font-family: var(--bp-font-display); 2086 font-size: 14px; 2087 font-style: normal; 2088 font-weight: 300; 2089 line-height: 120%; 2090 letter-spacing: -0.28px; 2091 } 2092 2093 .bp-card__quick { 2094 position: absolute; 2095 bottom: 12px; 2096 right: 12px; 2097 z-index: 2; 2098 width: 36px; 2099 height: 36px; 2100 border-radius: 0; 2101 border: 1px solid rgba(23, 22, 9, 0.15); 2102 background: var(--bp-color-bg-page); 2103 color: var(--bp-color-text); 2104 display: inline-flex; 2105 align-items: center; 2106 justify-content: center; 2107 cursor: pointer; 2108 opacity: 0; 2109 transform: translateY(4px); 2110 transition: opacity 0.2s ease, transform 0.2s ease, background-color 0.2s ease; 2111 } 2112 .bp-card__quick:hover { background: var(--bp-color-text); color: #fff; } 2113 2114 /* Quick-drawer gallery nav (.bp-qd-gallery-nav) is injected by JS onto 2115 <bp-pdp-gallery>. Its positioning/flip styles live inside a mobile 2116 @media block scoped to .bp-qd__media-slot, so on desktop â or when the 2117 gallery is the main PDP gallery (not in the drawer) â the buttons fall 2118 to the bottom unstyled: two disabled, both-right-pointing arrows. Hide 2119 the nav globally by default; bp-quick-drawer's mobile rules re-show it 2120 inside the drawer media slot. */ 2121 .bp-qd-gallery-nav { display: none; } 2122 2123 /* Quick-view button visibility â driven by §9.4 setting keys. 2124 "Always" applies on any device (logically: always = always); 2125 "Hover" only fires on hover-capable devices. Mobile show/hide 2126 is keyed on (hover: none) so it doesn't fight the desktop rules 2127 on touch laptops that report (hover: hover). */ 2128 2129 /* "Always visible" â opt-out of the hover-reveal animation. */ 2130 .bp-card[data-bp-card-qv-vis-d='always'] .bp-card__quick { 2131 opacity: 1; 2132 transform: none; 2133 } 2134 2135 /* Hover-capable devices: hover-to-reveal (default for desktop). */ 2136 @media (hover: hover) { 2137 .bp-card[data-bp-card-qv-vis-d='hover'] .bp-card__media:hover .bp-card__quick { 2138 opacity: 1; 2139 transform: translateY(0); 2140 } 2141 } 2142 2143 /* Touch-only: explicit mobile show/hide. */ 2144 @media (hover: none) { 2145 .bp-card[data-bp-card-qv-vis-m='shown'] .bp-card__quick { 2146 opacity: 1; 2147 transform: none; 2148 } 2149 .bp-card[data-bp-card-qv-vis-m='hidden'] .bp-card__quick { 2150 display: none; 2151 } 2152 } 2153 2154 /* Whole-product trigger style â make the card surface look clickable 2155 and remove the bag-icon affordance. The bag itself isn't rendered
2156 in this mode (see bp-product-card.liquid), so this just signals 2157 interactivity. */ 2158 .bp-card[data-bp-card-qb-style='whole_product'] { 2159 cursor: pointer; 2160 } 2161 2162 /* Swatch host wrapper â passes through for layout; the click target 2163 is the inner `.swatch` element (Horizon's). */ 2164 .bp-card__swatch-host { display: inline-flex; cursor: pointer; } 2165 2166 .bp-card__body { 2167 display: flex; 2168 flex-direction: column; 2169 gap: 6px; 2170 } 2171 .bp-card__collection { 2172 margin: 0; 2173 font-family: var(--bp-font-body); 2174 font-size: 11px; 2175 font-weight: 500; 2176 letter-spacing: 0.08em; 2177 text-transform: uppercase; 2178 color: var(--bp-color-text-muted); 2179 line-height: 1.3; 2180 } 2181 .bp-card__title { 2182 margin: 0; 2183 font-family: var(--bp-font-body); 2184 font-size: 15px; 2185 font-weight: 400; 2186 line-height: 1.3; 2187 letter-spacing: -0.15px; 2188 } 2189 .bp-card__title a { 2190 color: inherit; 2191 text-decoration: none; 2192 } 2193 .bp-card__title a:hover { text-decoration: underline; text-underline-offset: 3px; } 2194 2195 .bp-card__price-row { 2196 display: flex; 2197 flex-wrap: wrap; 2198 align-items: baseline; 2199 gap: 6px 10px; 2200 font-family: var(--bp-font-body); 2201 font-size: 14px; 2202 font-weight: 500; 2203 line-height: 145%; 2204 letter-spacing: -0.14px; 2205 } 2206 .bp-card__price { 2207 color: var(--bp-color-text, #171609); 2208 font-weight: 500; 2209 } 2210 .bp-card__compare { 2211 /* Strikethrough/compare price grey â #74736B, matching the PDP 2212 (bp-pdp-styles .compare-at-price) per QA (Amber). NB: #74736B is the 2213 WCAG-exempt grey (it fails AA 4.5:1); kept consistent with the PDP at 2214 the team's request over the darker --bp-color-body-copy (#666559). */ 2215 color: #74736B; 2216 text-decoration: line-through; 2217 font-weight: 500; 2218 } 2219 .bp-card__promo { 2220 color: #CA3D3D; 2221 font-size: 12px; 2222 font-weight: 400; 2223 line-height: 145%; 2224 letter-spacing: -0.12px; 2225 flex-basis: 100%; 2226 } 2227 /* Desktop: try to sit inline with the price; when it doesn't fit, 2228 flex-wrap pushes it to the next line. No margin-left:auto here 2229 â that would right-align the wrapped copy. Plain flex-grow:0 2230 keeps it hugging the price on the same line. */ 2231 @media screen and (min-width: 1024px) { 2232 .bp-card__promo { 2233 flex-basis: auto; 2234 margin-left: 0; 2235 text-align: left; 2236 } 2237 } 2238 2239 .bp-card__swatches { 2240 display: flex; 2241 align-items: center; 2242 gap: 10px; 2243 margin: 8px 0 0; 2244 padding: 4px; 2245 list-style: none; 2246 } 2247 .bp-card__swatch-item { 2248 display: inline-flex; 2249 align-items: center; 2250 position: relative; 2251 } 2252 /* Sale-discount badge on a swatch â Body/Semi/Tiny spec: 2253 Messina 10 / 660 / 145% / -0.1px, Sales-Red on white with a 2254 red border. Anchors top-right of the swatch dot. */ 2255 .bp-card__swatch-discount { 2256 position: absolute; 2257 top: -6px; 2258 right: -8px; 2259 display: inline-flex; 2260 flex-direction: column; 2261 justify-content: center; 2262 align-items: center; 2263 padding: 0 2px; 2264 border: 1px solid #CA3D3D; 2265 background: #FDFFFA; 2266 color: #CA3D3D; 2267 text-align: center; 2268 font-family: var(--bp-font-body); 2269 font-size: 10px; 2270 font-weight: 700; 2271 line-height: 145%; 2272 letter-spacing: -0.1px; 2273 pointer-events: none; 2274 white-space: nowrap; 2275 } 2276 /* BP a11y: interactive swatches are a <button> wrapping a decorative 2277 <img>. The button is a transparent wrapper (focus ring only) â the 2278 visual ring stays on .bp-card__swatch-img so the many bare-<span> 2279 swatch renderers (Bloomreach cards/carousel, search, you'll-also-love) 2280 keep it without needing the button. */ 2281 .bp-card__swatch { 2282 appearance: none; 2283 -webkit-appearance: none; 2284 padding: 0; 2285 border: 0; 2286 background: transparent; 2287 border-radius: 50%; 2288 cursor: pointer; 2289 display: block; 2290 line-height: 0; 2291 flex-shrink: 0; 2292 } 2293 .bp-card__swatch:focus-visible { 2294 outline: 2px solid var(--bp-color-text); 2295 outline-offset: 4px; 2296 } 2297 .bp-card__swatch-img { 2298 width: 24px; 2299 height: 24px; 2300 border-radius: 50%; 2301 object-fit: cover; 2302 display: block; 2303 flex-shrink: 0;
2304 /* 2px white gap + 1px cream ring â layered box-shadow keeps 2305 the element size stable while painting the ring outside the image. */ 2306 box-shadow: 0 0 0 2px #fff, 0 0 0 3px #E1E0D4; 2307 } 2308 /* Design-preview mock dot â solid background color, no image, 2309 same 23px footprint as the real swatch. */ 2310 .bp-card__swatch-img--mock { 2311 background-clip: content-box; 2312 background-size: cover; 2313 border-color: rgba(23, 22, 9, 0.15); 2314 } 2315 /* Active ring targets the visible dot whether the active class sits on 2316 the button (bp-product-card / bp-card-hydrate) or directly on the img 2317 (bare-span renderers). */ 2318 .bp-card__swatch--active .bp-card__swatch-img, 2319 .bp-card__swatch-img.bp-card__swatch--active { 2320 box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--bp-color-text); 2321 } 2322 .bp-card__swatch-more { 2323 font-family: var(--bp-font-body); 2324 font-size: 12px; 2325 color: rgba(23, 22, 9, 0.65); 2326 margin-left: 2px; 2327 } 2328 /* +N is now a PDP link â keep it visually identical to the old text 2329 (inherit colour, no underline) but tappable, with a hover cue. */ 2330 .bp-card__swatch-more-link { 2331 color: inherit; 2332 text-decoration: none; 2333 } 2334 .bp-card__swatch-more-link:hover { text-decoration: underline; text-underline-offset: 2px; } 2335 2336 /* ============================================================ 2337 BP Shop-the-Look drawer â global styles. 2338 2339 MOVED to assets/bp-fonts-deferred.css (loaded non-render- 2340 blocking from theme.liquid). `.bp-stl-drawer` is a native 2341 <dialog> (UA display:none until .showModal() opens it from a 2342 "Shop the look" trigger) â an interaction-revealed surface with 2343 no closed-state hide rule of its own â so its appearance rules 2344 don't need to block first paint. Markup: snippets/ 2345 bp-stl-drawer.liquid; behavior: assets/bp-stl-drawer.js. 2346 ============================================================ */ 2347 2348 /* ============================================================ 2349 BP Footer utilities bar â override Horizon's footer-utilities 2350 so the bottom copyright / policy bar inherits the cream 2351 background that bp-footer uses, and the link color stays on-brand. 2352 ============================================================ */ 2353 .footer-utilities { 2354 background-color: var(--bp-color-bg-cream); 2355 color: var(--bp-color-text); 2356 } 2357 .footer-utilities a { 2358 color: var(--bp-color-text); 2359 } 2360 2361 /* ============================================================ 2362 BP Mega Menu (desktop) â markup lives in blocks/_bp-menu-item.liquid. 2363 Horizon already handles submenu positioning, hover open/close, 2364 and the <header-menu> layout. We only add: vertical centering of 2365 the menu row + the .bp-mega* content styles for the dropdown. 2366 ============================================================ */ 2367 2368 /* Vertically center menu items in the header row */ 2369 header-menu .menu-list, 2370 .menu-list { 2371 align-items: center; 2372 } 2373 2374 /* Top-level nav links â smooth hover transitions. 2375 Uses Messina Sans VF (variable font) so font-weight can transition 2376 smoothly via font-variation-settings rather than snapping. Plus a 2377 gentle underline that grows from the center under each label. */ 2378 .menu-list__list-item .menu-list__link { 2379 position: relative; 2380 transition: opacity 0.2s ease, font-variation-settings 0.25s ease; 2381 font-variation-settings: 'wght' 400; 2382 } 2383 .menu-list__list-item .menu-list__link::after { 2384 content: ''; 2385 position: absolute; 2386 left: 50%; 2387 bottom: 0; 2388 width: 0; 2389 height: 1px; 2390 background: currentColor; 2391 transform: translateX(-50%); 2392 transition: width 0.25s ease; 2393 pointer-events: none; 2394 } 2395 .menu-list__list-item:hover .menu-list__link, 2396 .menu-list__list-item:focus-within .menu-list__link, 2397 .menu-list__list-item.bp-menu-open .menu-list__link, 2398 .menu-list__list-item .menu-list__link[aria-expanded='true'], 2399 .menu-list__list-item .menu-list__link.menu-list__link--active { 2400 font-weight: 700; 2401 font-variation-settings: 'wght' 700; 2402 } 2403 .menu-list__list-item:hover .menu-list__link::after, 2404 .menu-list__list-item:focus-within .menu-list__link::after, 2405 .menu-list__list-item.bp-menu-open .menu-list__link::after { 2406 width: 100%; 2407 } 2408 /* Sibling fade â when one nav item is hovered/open, gently dim the others */ 2409 .menu-list:hover .menu-list__list-item .menu-list__link, 2410 .menu-list:has(.bp-menu-open) .menu-list__list-item .menu-list__link { 2411 opacity: 0.55; 2412 } 2413 .menu-list:hover .menu-list__list-item:hover .menu-list__link, 2414 .menu-list .menu-list__list-item.bp-menu-open .menu-list__link, 2415 .menu-list .menu-list__list-item:focus-within .menu-list__link { 2416 opacity: 1; 2417 } 2418 2419 /* BP mega submenu â own classes (.bp-mega-submenu, not Horizon's 2420 .menu-list__submenu) so Horizon's submenu CSS doesn't apply. Open/ 2421 close is driven by .bp-menu-open on the LI, set by our JS hover 2422 handler (assets/bp-mega-hover.js) with a debounced close. */ 2423 .bp-mega-submenu { 2424 position: fixed; 2425 left: 0; 2426 right: 0; 2427 top: var(--header-height, 60px); 2428 width: 100vw; 2429 max-width: 100vw; 2430 z-index: 90; 2431 /* Off-white to match the header (QA 7/16) â falls back to the BP page 2432 bg token, not #fff, if --color-background is ever unset. */ 2433 background: var(--color-background, var(--bp-color-bg-page)); 2434 box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06); 2435 opacity: 0; 2436 pointer-events: none; 2437 transition: opacity 0.15s ease; 2438 } 2439 .menu-list__list-item.bp-menu-open > .bp-mega-submenu { 2440 opacity: 1; 2441 pointer-events: auto; 2442 } 2443 .bp-mega-submenu__inner { 2444 width: 100%; 2445 /* CLAUDE.md spacing tokens â match the rest of the BP sections. 2446 Top is 20px (a touch tight against the nav row); sides + bottom 2447 use the standard --bp-section-pad-x / -y so the content's left 2448 edge aligns with the logo (which sits at --bp-section-pad-x via 2449 the topnav --page-margin override in this same file). No 2450 max-width / centering â full-bleed minus gutters. */ 2451 padding: 20px var(--bp-section-pad-x) var(--bp-section-pad-y); 2452 box-sizing: border-box; 2453 } 2454 2455 /* Layout: columns + (optional) right-side promos. Uses BP spacing 2456 tokens (CLAUDE.md): --bp-section-gap = 20px desktop. */ 2457 .bp-mega { 2458 display: flex; 2459 align-items: flex-start; 2460 gap: var(--bp-section-gap); 2461 align-self: stretch; 2462 width: 100%; 2463 white-space: normal; 2464 word-wrap: break-word; 2465 overflow-wrap: break-word; 2466 font-family: var(--font-body--family); 2467 font-size: var(--font-size--sm); 2468 line-height: 1.4; 2469 color: var(--color-foreground); 2470 } 2471 .bp-mega *, .bp-mega *::before, .bp-mega *::after { white-space: normal; } 2472 2473 /* Columns side-by-side, equal width, BP spacing */ 2474 .bp-mega__columns { 2475 flex: 1 1 auto; 2476 display: flex; 2477 gap: var(--bp-section-gap); 2478 } 2479 .bp-mega__column { 2480 flex: 1 1 0; 2481 min-width: 0; 2482 } 2483 2484 .bp-mega__column { 2485 display: flex; 2486 flex-direction: column; 2487 gap: var(--gap-sm); 2488 min-width: 0; 2489 } 2490 /* Column / tab heading â Body/Semi/Small (Messina Sans VF, 14px, 660). */ 2491 .bp-mega__heading { 2492 margin: 0 0 var(--bp-card-gap); 2493 color: var(--bp-color-text); 2494 font-family: var(--bp-font-body); 2495 font-size: 14px; 2496 font-style: normal; 2497 font-weight: 700; 2498 line-height: 145%; 2499 letter-spacing: -0.14px; 2500 } 2501 .bp-mega__heading a { color: inherit; text-decoration: none; } 2502 2503 .bp-mega__links { 2504 list-style: none; 2505 margin: 0; 2506 padding: 0; 2507 display: flex; 2508 flex-direction: column; 2509 gap: 6px; 2510 } 2511 .bp-mega__links a { 2512 font-family: var(--font-body--family); 2513 font-size: var(--font-size--sm); 2514 color: var(--color-foreground); 2515 text-decoration: none; 2516 line-height: 1.4; 2517 } 2518 .bp-mega__links a:hover { text-decoration: underline; } 2519 2520 .bp-mega__promos { 2521 flex: 0 0 auto; 2522 /* Pin to the right edge of the dropdown (just inside the 2523 --bp-section-pad-x gutter). margin-inline-start:auto pushes us 2524 past the columns regardless of how much space they take. */ 2525 margin-inline-start: auto; 2526 display: grid; 2527 /* Default = two fixed-width columns. The :has(:only-child) rule 2528 below swaps to a single wider column when only one promo 2529 renders. Was repeat(auto-fit, 220px), but auto-fit would 2530 collapse to a single column on dropdowns where the menu 2531 columns squeezed this container narrow â making the second 2532 promo wrap below the first instead of sitting beside it. */ 2533 grid-template-columns: repeat(2, 220px); 2534 gap: var(--bp-section-gap); 2535 justify-content: end; 2536 } 2537 .bp-mega__promo { min-width: 0; max-width: 100%; } 2538 .bp-mega__promo-link { 2539 display: flex; 2540 flex-direction: column; 2541 gap: var(--gap-xs); 2542 text-decoration: none; 2543 color: var(--color-foreground); 2544 width: 100%; 2545 } 2546 .bp-mega__promo-image { 2547 position: relative; 2548 width: 100%; 2549 aspect-ratio: 4 / 5; 2550 background: var(--color-foreground-muted, #ddd); 2551 overflow: hidden; 2552 } 2553 .bp-mega__promo-image svg, 2554 .bp-mega__promo-image img, 2555 .bp-mega__promo-video { 2556 position: absolute; 2557 inset: 0; 2558 width: 100%; 2559 height: 100%; 2560 object-fit: cover; 2561 display: block; 2562 } 2563 2564 /* Promo typography â Messina Sans VF semi (660) for the title; 2565 500 for the body copy. Colors: Black for title, --bp-color-body-copy 2566 (#74736B) for the supporting paragraph. */ 2567 .bp-mega__promo-title { 2568 margin: 0; 2569 color: var(--bp-color-text); 2570 font-family: var(--bp-font-body); 2571 font-size: 14px; 2572 font-style: normal; 2573 font-weight: 700; 2574 line-height: 145%; 2575 letter-spacing: -0.14px; 2576 } 2577 .bp-mega__promo-copy { 2578 margin: 0; 2579 color: var(--bp-color-body-copy); 2580 font-family: var(--bp-font-body); 2581 font-size: 12px; 2582 font-style: normal; 2583 font-weight: 500; 2584 line-height: 145%; 2585 letter-spacing: -0.12px; 2586 } 2587 .bp-mega__promo-cta { 2588 margin-top: 4px; 2589 color: var(--bp-color-text); 2590 font-family: var(--bp-font-body); 2591 font-size: 12px; 2592 font-weight: 500; 2593 line-height: 145%; 2594 letter-spacing: -0.12px; 2595 text-decoration: underline; 2596 text-underline-offset: 3px; 2597 } 2598 2599 /* Single-promo variant: when only one promo is rendered inside a 2600 columns_promos dropdown, give it the width of two regular promos 2601 (~460px) and a 3:2 landscape image, capped at 370px tall. Driven 2602 by :only-child so no Liquid changes needed. */ 2603 .bp-mega__promos:has(> .bp-mega__promo:only-child) { 2604 grid-template-columns: minmax(0, 460px); 2605 } 2606 .bp-mega__promos > .bp-mega__promo:only-child .bp-mega__promo-image { 2607 aspect-ratio: 3 / 2; 2608 height: 370px; 2609 width: 100%; 2610 align-self: stretch; 2611 } 2612 2613 @media screen and (max-width: 989px) { 2614 .bp-mega--columns-promos { flex-direction: column; } 2615 .bp-mega__promos { grid-template-columns: repeat(2, minmax(0, 1fr)); } 2616 } 2617 2618 /* ----- Layout: image_tiles (Occasions) ---------------------------- 2619 Flat row of tiles. Each tile = square image + title + Shop Now. 2620 Tile width is fluid; on tighter widths the row wraps. Designed 2621 to lay out 6 tiles in one row at desktop widths. */ 2622 .bp-mega--image-tiles { display: block; } 2623 .bp-mega__tiles { 2624 display: grid; 2625 grid-template-columns: repeat(6, minmax(0, 1fr)); 2626 gap: var(--bp-section-gap); 2627 width: 100%; 2628 } 2629 @media screen and (max-width: 1279px) { 2630 .bp-mega__tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); } 2631 } 2632 @media screen and (max-width: 989px) { 2633 .bp-mega__tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); } 2634 } 2635 .bp-mega__tile { 2636 display: flex; 2637 flex-direction: column; 2638 gap: var(--bp-card-gap); 2639 color: var(--bp-color-text); 2640 text-decoration: none; 2641 } 2642 .bp-mega__tile-image { 2643 position: relative; 2644 aspect-ratio: 1 / 1; 2645 background: var(--bp-color-bg-cream); 2646 overflow: hidden; 2647 } 2648 /* Image-tiles layout ONLY: 4/5 portrait per the wireframe â the square 2649 (1/1) cropped the imagery (Ernie 7/27). Scoped to the image_tiles 2650 container so other mega layouts are unaffected. The <img> still 2651 object-fit:covers this box. */ 2652 .bp-mega--image-tiles .bp-mega__tile-image { 2653 aspect-ratio: 4 / 5; 2654 } 2655 .bp-mega__tile-image img, 2656 .bp-mega__tile-image svg { 2657 position: absolute; 2658 inset: 0; 2659 width: 100%; 2660 height: 100%; 2661 object-fit: cover; 2662 display: block; 2663 } 2664 .bp-mega__tile-title { 2665 margin: 0; 2666 font-family: var(--bp-font-body); 2667 font-size: 15px; 2668 font-weight: 500; 2669 line-height: 1.3; 2670 letter-spacing: -0.15px; 2671 color: var(--bp-color-text); 2672 } 2673 .bp-mega__tile-cta { 2674 font-family: var(--bp-font-body); 2675 font-size: 13px; 2676 line-height: 1.4; 2677 color: var(--bp-color-text); 2678 text-decoration: underline; 2679 text-underline-offset: 3px; 2680 } 2681 2682 /* ----- Layout: tabs_promos (Brands We Love) ----------------------- 2683 3-column grid: vertical tab list | active panel | promos. 2684 Tab activation is handled by assets/bp-mega-hover.js (initTabs). */ 2685 .bp-mega--tabs-promos { display: block; } 2686 .bp-mega__tabs { 2687 display: grid; 2688 grid-template-columns: minmax(180px, 1fr) minmax(0, 2fr) minmax(0, 2fr); 2689 gap: var(--bp-section-gap); 2690 width: 100%; 2691 align-items: start; 2692 } 2693 .bp-mega__tabs-list { 2694 list-style: none; 2695 margin: 0; 2696 padding: 0; 2697 display: flex; 2698 flex-direction: column; 2699 gap: 4px; 2700 } 2701 .bp-mega__tab { 2702 display: flex; 2703 align-items: center; 2704 justify-content: space-between; 2705 width: 100%; 2706 padding: 14px 16px; 2707 background: transparent; 2708 border: 0; 2709 cursor: pointer; 2710 text-align: left; 2711 color: var(--bp-color-text); 2712 font-family: var(--bp-font-body); 2713 font-size: 14px; 2714 line-height: 1.3; 2715 letter-spacing: -0.14px; 2716 transition: background-color 0.15s ease, font-weight 0.15s ease; 2717 } 2718 .bp-mega__tab:hover { 2719 background: var(--bp-color-neutral); 2720 } 2721 .bp-mega__tab.is-active { 2722 background: var(--bp-color-neutral); 2723 font-weight: 600; 2724 } 2725 .bp-mega__tab-chevron { 2726 display: inline-flex; 2727 align-items: center; 2728 justify-content: center; 2729 flex: 0 0 auto; 2730 margin-left: 12px; 2731 opacity: 0.85; 2732 /* New chevron asset is drawn left-pointing; flip to point right 2733 (toward the tab panel that opens on the right). */ 2734 transform: scaleX(-1); 2735 } 2736 .bp-mega__tabs-panels { 2737 min-width: 0; 2738 } 2739 .bp-mega__tab-panel { 2740 display: none; 2741 padding: 4px 0; 2742 } 2743 .bp-mega__tab-panel.is-active { 2744 display: block; 2745 } 2746 /* Tabs layout uses a slightly looser link gap (8px vs 6px elsewhere). */ 2747 .bp-mega--tabs-promos .bp-mega__links { 2748 gap: 8px; 2749 } 2750 /* Two-column tab links (merchant toggle: block.settings.tabs_link_columns). 2751 Long lists like Brands We Love overflow one tall column and leave the 2752 right half of the panel empty; splitting into two balanced columns uses 2753 that white space beside the promos. Give the panel track more room (3fr) 2754 so both columns breathe, then flow the <ul> as CSS multi-column â items 2755 fill top-to-bottom of column 1, then column 2, which keeps an 2756 alphabetical brand list reading naturally (AâM | NâZ). */ 2757 .bp-mega__tabs[data-bp-tab-columns="2"] { 2758 grid-template-columns: minmax(180px, 1fr) minmax(0, 3fr) minmax(0, 2fr); 2759 } 2760 .bp-mega__tabs[data-bp-tab-columns="2"] .bp-mega__links { 2761 display: block; 2762 columns: 2; 2763 column-gap: var(--bp-section-gap); 2764 } 2765 .bp-mega__tabs[data-bp-tab-columns="2"] .bp-mega__links li { 2766 margin-bottom: 8px; 2767 break-inside: avoid; 2768 -webkit-column-break-inside: avoid; 2769 } 2770 .bp-mega__tabs[data-bp-tab-columns="2"] .bp-mega__links li:last-child { 2771 margin-bottom: 0; 2772 } 2773 .bp-mega__promos--tabs { 2774 /* Match the columns_promos promos (styleEDIT): fixed 220px columns so the 2775 images render full-size. `minmax(0,1fr)` collapsed them to a sliver 2776 because the promos container is content-sized (flex:0 0 auto) â the 2777 fr units had no defined width to divide, so the 4:5 images shrank to 2778 their min. The tabs dropdown has ample room on the right (tabs + brand 2779 list only fill the left half). */ 2780 grid-template-columns: repeat(2, 220px); 2781 display: grid; 2782 gap: var(--bp-section-gap); 2783 } 2784 2785 @media screen and (max-width: 989px) { 2786 .bp-mega__tabs, 2787 .bp-mega__tabs[data-bp-tab-columns="2"] { grid-template-columns: 1fr; } 2788 .bp-mega__promos--tabs { grid-template-colu
2788mns: repeat(2, minmax(0, 1fr)); } 2789 /* Not enough width for two link columns once the tabs stack â collapse. */ 2790 .bp-mega__tabs[data-bp-tab-columns="2"] .bp-mega__links { columns: 1; } 2791 } 2792 2793 @media screen and (max-width: 749px) { 2794 .bp-mega { display: none; } 2795 } 2796 2797 /* BP Cart Drawer â markup, CSS, and JS live in 2798 snippets/bp-cart-drawer.liquid (rendered from theme.liquid). 2799 Hide Horizon's cart-drawer-component since BP has its own. */ 2800 cart-drawer-component { display: none !important; } 2801 2802 /* ===== §9.1 BP Section knobs â base rules =========================== 2803 Consumes CSS variables emitted by snippets/bp-section-knobs.liquid. 2804 Sections opt in by carrying `data-bp-section`, `data-section-id`, 2805 and `data-bp-mode-{d,m}` attributes on the wrapping element. 2806 Mobile is the default; desktop overrides at â¥1024px (§1). 2807 ================================================================= */ 2808 2809 [data-bp-section] { 2810 background: var(--bp-knobs-bg-section, transparent); 2811 color: var(--bp-knobs-text, var(--bp-color-text)); 2812 } 2813 2814 [data-bp-section][data-bp-mode-m='padded'] { 2815 padding-block: var(--bp-knobs-pad-y-m, var(--bp-section-pad-y)); 2816 padding-inline: var(--bp-knobs-pad-x-m, var(--bp-section-pad-x)); 2817 } 2818 [data-bp-section][data-bp-mode-m='full'] { 2819 padding-block: var(--bp-knobs-pad-y-m, var(--bp-section-pad-y)); 2820 padding-inline: 0; 2821 } 2822 2823 /* Inner block â only renders meaningfully when padded. Holds the 2824 inner background color so a padded section can have a section bg 2825 AND a different inner-block bg (per §9.1). */ 2826 [data-bp-section] .bp-section__inner { 2827 background: var(--bp-knobs-bg-inner, transparent); 2828 } 2829 2830 /* Title alignment â opt in via class `bp-section__title` on the 2831 heading. text-align is inheritable, so descendant copy follows. */ 2832 [data-bp-section] .bp-section__title { 2833 text-align: var(--bp-knobs-align-m, start); 2834 } 2835 2836 @media screen and (min-width: 1024px) { 2837 [data-bp-section][data-bp-mode-d='padded'] { 2838 padding-block: var(--bp-knobs-pad-y-d, var(--bp-section-pad-y)); 2839 padding-inline: var(--bp-knobs-pad-x-d, var(--bp-section-pad-x)); 2840 } 2841 [data-bp-section][data-bp-mode-d='full'] { 2842 padding-block: var(--bp-knobs-pad-y-d, var(--bp-section-pad-y)); 2843 padding-inline: 0; 2844 } 2845 [data-bp-section] .bp-section__title { 2846 text-align: var(--bp-knobs-align-d, start); 2847 } 2848 } 2849 2850 /* ===== §9.3 BP Media block â base rules ============================ 2851 Used by snippets/bp-section-media.liquid. The snippet emits a 2852 [data-bp-media] wrapper with optional `--bp-media-ratio-{d,m}` 2853 custom properties and an optional .bp-media__overlay child. 2854 The overlay's solid vs. gradient + coverage live entirely in CSS 2855 so the merchant gets live-preview without re-rendering markup. 2856 2857 §9.3 rule: images always fill the full width of their slot. 2858 position:relative + absolute children + object-fit cover does 2859 this regardless of the slot's height (which the section sizes). 2860 ================================================================= */ 2861 2862 [data-bp-media] { 2863 position: relative; 2864 overflow: hidden; 2865 width: 100%; 2866 /* Mobile-first ratio. Falls through to the desktop ratio when no 2867 mobile-specific value is set. `auto` (the default) leaves the 2868 slot to be sized by its parent (e.g. fixed mobile band height, 2869 desktop grid row stretch). */ 2870 aspect-ratio: var(--bp-media-ratio-m, var(--bp-media-ratio-d, auto)); 2871 } 2872 2873 [data-bp-media] .bp-media__image, 2874 [data-bp-media] .bp-media__video { 2875 position: absolute; 2876 inset: 0; 2877 width: 100%; 2878 height: 100%; 2879 /* Fit: cover (default, fills + crops) vs contain (whole asset shown, 2880 may letterbox against the slot bg). Set per media block via the 2881 {prefix}_fit knob â e.g. a rotating-logo video that must never be 2882 cropped uses 'contain'. */ 2883 object-fit: var(--bp-media-fit, cover); 2884 /* Focal point. Mobile-first; desktop override below. 2885 Merchants pick from a 9-position select on the media block. */ 2886 object-position: var(--bp-media-pos-m, var(--bp-media-pos-d, center center)); 2887 display: block; 2888 } 2889 2890 [data-bp-media] .bp-media__placeholder { 2891 position: absolute; 2892 inset: 0; 2893 background: linear-gradient(135deg, #e8e6df 0%, #cfccc1 100%); 2894 } 2895 2896 /* Overlay â sits on top of the media, solid or gradient. The 2897 coverage % indicates how much of the height (anchored to the 2898 bottom) carries the colour: 2899 - solid: a hard band from 0 to coverage% (transparent above) 2900 - gradient: fades from full colour at the bottom to transparent 2901 at coverage% from the bottom 2902 Selectors are unscoped so block-level surfaces (hero slides, 2903 look tiles, category cards) can use the same overlay without 2904 needing the [data-bp-media] block-prefix machinery â drop the 2905 element inside any position:relative parent and it fills it. */ 2906 .bp-media__overlay { 2907 position: absolute; 2908 inset: 0; 2909 pointer-events: none; 2910 /* Opacity is responsive: --â¦-opacity-m (mobile) then the single 2911 --â¦-opacity, then a default. Desktop override lives in the media 2912 query below. */ 2913 opacity: var(--bp-media-overlay-opacity-m, var(--bp-media-overlay-opacity, 0.3)); 2914 } 2915 /* Gradient DIRECTION + COVERAGE are driven per breakpoint by 2916 --bp-media-overlay-dir-{m,d} and --bp-media-overlay-coverage-{m,d} 2917 (emitted from the "Overlay position" + "Coverage" controls â 2918 bottomâ`to top`, topâ`to bottom`, leftâ`to right`, rightâ`to left`). 2919 Each falls back to its single-value var, then the bottom-anchored / 2920 full-image default, so sections that set only the shared values (or 2921 nothing) are unchanged. */ 2922 .bp-media__overlay--solid { 2923 background: linear-gradient( 2924 var(--bp-media-overlay-dir-m, to top), 2925 var(--bp-media-overlay-color, #000) 0, 2926 var(--bp-media-overlay-color, #000) var(--bp-media-overlay-coverage-m, var(--bp-media-overlay-coverage, 100%)), 2927 transparent var(--bp-media-overlay-coverage-m, var(--bp-media-overlay-coverage, 100%)) 2928 ); 2929 } 2930 .bp-media__overlay--gradient { 2931 background: linear-gradient( 2932 var(--bp-media-overlay-dir-m, to top), 2933 var(--bp-media-overlay-color, #000) 0, 2934 transparent var(--bp-media-overlay-coverage-m, var(--bp-media-overlay-coverage, 100%)) 2935 ); 2936 } 2937 2938 @media screen and (min-width: 1024px) { 2939 [data-bp-media] { 2940 aspect-ratio: var(--bp-media-ratio-d, auto); 2941 } 2942 [data-bp-media] .bp-media__image, 2943 [data-bp-media] .bp-media__video { 2944 object-position: var(--bp-media-pos-d, center center); 2945 } 2946 /* Desktop overlay â opacity, direction, and coverage each fall back to 2947 the mobile value, then the single-value var, then the default, so a 2948 desktop-only or single-value setup still works. */ 2949 .bp-media__overlay { 2950 opacity: var(--bp-media-overlay-opacity-d, var(--bp-media-overlay-opacity-m, var(--bp-media-overlay-opacity, 0.3))); 2951 } 2952 .bp-media__overlay--solid { 2953 background: linear-gradient( 2954 var(--bp-media-overlay-dir-d, var(--bp-media-overlay-dir-m, to top)), 2955 var(--bp-media-overlay-color, #000) 0, 2956 var(--bp-media-overlay-color, #000) var(--bp-media-overlay-coverage-d, var(--bp-media-overlay-coverage-m, var(--bp-media-overlay-coverage, 100%))), 2957 transparent var(--bp-media-overlay-coverage-d, var(--bp-media-overlay-coverage-m, var(--bp-media-overlay-coverage, 100%))) 2958 ); 2959 } 2960 .bp-media__overlay--gradient { 2961 background: linear-gradient( 2962 var(--bp-media-overlay-dir-d, var(--bp-media-overlay-dir-m, to top)), 2963 var(--bp-media-overlay-color, #000) 0, 2964 transparent var(--bp-media-overlay-coverage-d, var(--bp-media-overlay-coverage-m, var(--bp-media-overlay-coverage, 100%))) 2965 ); 2966 } 2967 } 2968 2969 /* ===== WCAG 2.2.2 pause/play button (bp-section-media.liquid) ======
2970 Shown whenever a video autoplays without native controls. Positioned 2971 bottom-left inside [data-bp-media]; z-index 2 keeps it above the 2972 overlay (which sits at z-index 1 by stacking order). ============== */ 2973 .bp-media__pause-btn { 2974 position: absolute; 2975 bottom: 12px; 2976 left: 12px; 2977 z-index: 2; 2978 display: inline-flex; 2979 align-items: center; 2980 justify-content: center; 2981 width: 40px; 2982 height: 40px; 2983 padding: 0; 2984 border: none; 2985 border-radius: 50%; 2986 background-color: rgba(0, 0, 0, 0.6); 2987 color: #fff; 2988 cursor: pointer; 2989 transition: background-color 0.15s ease; 2990 } 2991 .bp-media__pause-btn:hover, 2992 .bp-media__pause-btn:focus { 2993 background-color: rgba(0, 0, 0, 0.82); 2994 } 2995 .bp-media__pause-btn:focus-visible { 2996 outline: 2px solid #fff; 2997 outline-offset: 2px; 2998 } 2999 .bp-media__pause-btn:focus:not(:focus-visible) { 3000 outline: none; 3001 } 3002 3003 /* ===== §9.2 BP CTA Group + Button â base rules ===================== 3004 Sections wrap their CTAs in `[data-bp-cta-group]` with 3005 `data-dir-d="row|column"` and `data-dir-m="row|column"` to 3006 control multi-button layout per breakpoint. Each button is a 3007 `.bp-cta` rendered by snippets/bp-cta-button.liquid carrying 3008 `data-w-{d,m}="fit|custom"` plus inline `--bp-cta-w-{d,m}` 3009 custom-percent values for the Custom width mode. 3010 ================================================================= */ 3011 3012 [data-bp-cta-group] { 3013 display: flex; 3014 flex-direction: column; 3015 flex-wrap: wrap; 3016 gap: 12px; 3017 align-items: stretch; 3018 } 3019 /* Full-width toggle stretches the group container itself (not just its 3020 buttons), so a group centered/shrink-wrapped by its parent still spans 3021 the full available width and its stacked buttons truly fill it. Only the 3022 CTA-group block opts in (data-full-width="true"); legacy section-level 3023 groups have no attribute and are unaffected. */ 3024 [data-bp-cta-group][data-full-width='true'] { width: 100%; } 3025 [data-bp-cta-group][data-dir-m='row'] { 3026 flex-direction: row; 3027 align-items: center; 3028 } 3029 @media screen and (min-width: 1024px) { 3030 [data-bp-cta-group][data-dir-d='row'] { 3031 flex-direction: row; 3032 align-items: center; 3033 } 3034 [data-bp-cta-group][data-dir-d='column'] { 3035 flex-direction: column; 3036 align-items: stretch; 3037 } 3038 } 3039 3040 /* Button width â default Fit (content-sized). Custom mode picks 3041 the width up from the inline --bp-cta-w-{d,m} variable. 3042 In a STACKED group, buttons grow to full container width â UNLESS the 3043 group opts out via the Full-width toggle (bp-cta-group emits 3044 data-full-width="false"), where align-self:start defeats the group's 3045 align-items:stretch so each button hugs its fit/custom width instead. 3046 Groups with no attribute (legacy section-level [data-bp-cta-group]) 3047 keep the full-width default. */ 3048 .bp-cta[data-w-m='fit'] { width: auto; } 3049 .bp-cta[data-w-m='custom'] { width: var(--bp-cta-w-m, 100%); } 3050 @media screen and (max-width: 1023px) { 3051 [data-bp-cta-group]:not([data-dir-m='row']):not([data-full-width='false']) .bp-block-cta { width: 100%; } 3052 [data-bp-cta-group]:not([data-dir-m='row']):not([data-full-width='false']) .bp-cta { width: 100%; } 3053 [data-bp-cta-group]:not([data-dir-m='row'])[data-full-width='false'] .bp-block-cta, 3054 [data-bp-cta-group]:not([data-dir-m='row'])[data-full-width='false'] .bp-cta { align-self: flex-start; } 3055 } 3056 @media screen and (min-width: 1024px) { 3057 .bp-cta[data-w-d='fit'] { width: auto; } 3058 .bp-cta[data-w-d='custom'] { width: var(--bp-cta-w-d, 100%); } 3059 [data-bp-cta-group][data-dir-d='column']:not([data-full-width='false']) .bp-block-cta { width: 100%; } 3060 [data-bp-cta-group][data-dir-d='column']:not([data-full-width='false']) .bp-cta { width: 100%; } 3061 [data-bp-cta-group][data-dir-d='column'][data-full-width='false'] .bp-block-cta, 3062 [data-bp-cta-group][data-dir-d='column'][data-full-width='false'] .bp-cta { align-self: flex-start; } 3063 } 3064 3065 /* Base button shape â height + padding + typography. The colour 3066 palette comes from the section-local --bp-knobs-text + a small 3067 set of role-specific defaults below; sections can also layer in 3068 their own per-section CTA tokens via extra classes. */ 3069 .bp-cta { 3070 display: inline-flex; 3071 align-items: center; 3072 justify-content: center; 3073 gap: 8px; 3074 height: 52px; 3075 padding: 0 28px; 3076 font-family: var(--bp-font-body); 3077 font-size: 17px; 3078 font-weight: 500; 3079 line-height: normal; 3080 letter-spacing: -0.17px; 3081 text-decoration: none; 3082 /* Default variant (secondary-like) â outlined dark on transparent. 3083 Always uses BP brand tokens, NOT --bp-knobs-text, so the button 3084 palette stays consistent regardless of the section's text color. 3085 Sections that need a different palette layer in their own scoped 3086 override (e.g. hero slides on dark imagery use `primary-light`). */ 3087 border: 1px solid var(--bp-color-text); 3088 color: var(--bp-color-text); 3089 background: transparent; 3090 transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, opacity 0.2s ease; 3091 cursor: pointer; 3092 white-space: nowrap; 3093 box-sizing: border-box; 3094 }
3095 /* Keyboard focus indicator (WCAG 2.4.7). No focus style existed, so tabbing 3096 to a CTA showed nothing â flagged on the Image + Text Banner (Alfred, 7/27, 3097 ADA). `:focus-visible` (not `:focus`) so a mouse click doesn't leave a 3098 ring. The ring is OFFSET outside the button so it sits on the section/page 3099 background: a dark ring reads on the light surfaces every standard variant 3100 lives on; the on-dark variants (used over imagery) switch to the light 3101 label color below. Matches the existing `.bp-card__swatch:focus-visible` 3102 pattern. Also keep link-style CTAs underlined on hover so they never 3103 collapse to plain text (the second half of the ticket). */ 3104 .bp-cta:focus-visible { 3105 outline: 2px solid var(--bp-color-text); 3106 outline-offset: 3px; 3107 } 3108 .bp-cta--primary-light:focus-visible, 3109 .bp-cta--secondary-light:focus-visible, 3110 .bp-cta--link-white:focus-visible { 3111 outline-color: var(--bp-color-cta-text); 3112 } 3113 .bp-cta--link:hover, 3114 .bp-cta--link:focus-visible, 3115 .bp-cta--link-white:hover, 3116 .bp-cta--link-white:focus-visible { 3117 text-decoration: underline; 3118 } 3119 .bp-cta__icon { 3120 display: inline-flex; 3121 align-items: center; 3122 width: 20px; 3123 height: 20px; 3124 } 3125 .bp-cta__icon img { 3126 width: 100%; 3127 height: 100%; 3128 display: block; 3129 object-fit: contain; 3130 } 3131 3132 /* Primary â fixed BP brand palette: dark fill + light label. The 3133 palette stays consistent across sections regardless of the 3134 section's `bp_text_color` setting; sections that need a different 3135 look on dark imagery pick `primary-light` (white fill, dark 3136 label) instead. */ 3137 .bp-cta--primary { 3138 background: var(--bp-color-text); 3139 color: var(--bp-color-cta-text); 3140 border-color: var(--bp-color-text); 3141 } 3142 .bp-cta--primary:hover { 3143 background: transparent; 3144 color: var(--bp-color-text); 3145 } 3146 3147 /* Primary-light: inverse of primary â white fill + dark label. 3148 Use on sections that sit on dark imagery (e.g. hero closing 3149 sliders) where a dark filled CTA clashes with the background. */ 3150 .bp-cta--primary-light { 3151 background: var(--bp-color-bg-page); 3152 color: var(--bp-color-text); 3153 border-color: #fff; 3154 } 3155 /* primary-light is the white-filled button used ON DARK imagery / dark 3156 sections. Its hover must stay LIGHT â transparent fill + near-white label 3157 and border â otherwise it resolves to dark-on-dark and the button reads 3158 "all black" on hover (QA: Dragana â "Find your look" / "View Details" on 3159 the homepage promo header). This is the correct default for the style, so 3160 it no longer needs the per-CTA "Hover style: White" opt-in. */ 3161 .bp-cta--primary-light:hover { 3162 background: transparent; 3163 color: var(--bp-color-cta-text); 3164 border-color: var(--bp-color-cta-text); 3165 } 3166 3167 /* Sand: filled sand (#E8DFD0) button with dark-brown (#2B241A) label. 3168 Hover inverts to the sand-invert palette. */ 3169 .bp-cta--sand { 3170 background: var(--bp-color-cta-sand); 3171 color: var(--bp-color-cta-sand-text); 3172 border-color: var(--bp-color-cta-sand); 3173 } 3174 .bp-cta--sand:hover { 3175 background: var(--bp-color-cta-sand-text); 3176 color: var(--bp-color-cta-sand); 3177 border-color: var(--bp-color-cta-sand-text); 3178 } 3179 3180 /* Sand (inverted): dark-brown fill with sand label â the invert of 3181 --sand. Hover swaps to the filled-sand palette. */ 3182 .bp-cta--sand-invert { 3183 background: var(--bp-color-cta-sand-text); 3184 color: var(--bp-color-cta-sand); 3185 border-color: var(--bp-color-cta-sand-text); 3186 } 3187 .bp-cta--sand-invert:hover { 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 3193 .bp-cta--secondary:hover { 3194 background: var(--bp-color-text); 3195 color: var(--bp-color-cta-text); 3196 } 3197 3198 /* Secondary-light: the on-dark counterpart to `secondary`. Same 3199 outlined geometry, but a WHITE border + WHITE label on a 3200 transparent fill so it reads on dark imagery (e.g. the "Who we are" 3201 banner over a photo) where the standard dark `secondary` outline 3202 would disappear. Hover inverts exactly like `secondary` does â 3203 fills with the border color (white) and flips the label dark. */ 3204 .bp-cta--secondary-light { 3205 background: transparent; 3206 color: var(--bp-color-cta-text); 3207 border-color: var(--bp-color-cta-text); 3208 } 3209 .bp-cta--secondary-light:hover { 3210 background: var(--bp-color-cta-text); 3211 color: var(--bp-color-text); 3212 border-color: var(--bp-color-cta-text); 3213 } 3214 .bp-cta--link { 3215 height: auto; 3216 padding: 0; 3217 border: 0; 3218 text-decoration: underline; 3219 text-underline-offset: 4px; 3220 } 3221 .bp-cta--link:hover { opacity: 0.65; } 3222 3223 /* Underline link, white text â for CTAs sitting on dark imagery / 3224 dark section backgrounds where the standard `link` (which inherits 3225 foreground color) would read black-on-black. Same geometry as 3226 `--link`; explicitly sets color to var(--bp-color-cta-text) so it 3227 doesn't pick up the surrounding text color. */ 3228 .bp-cta--link-white { 3229 height: auto; 3230 padding: 0; 3231 border: 0; 3232 background: transparent; 3233 color: var(--bp-color-cta-text, #FDFFFA); 3234 text-decoration: underline; 3235 text-underline-offset: 4px; 3236 } 3237 .bp-cta--link-white:hover { opacity: 0.65; } 3238 3239 /* Opt-in hover: transparent fill + white border + white text. Set per CTA 3240 via the BP CTA block's "Hover style" = White. For CTAs on dark backgrounds 3241 (e.g. the black homepage promo bar) where the default per-style hover 3242 resolves to dark-on-dark (QA: Dragana). !important so it wins over the 3243 equal-specificity per-variant :hover rules regardless of source order. */ 3244 .bp-cta--hover-white:hover { 3245 background: transparent !important; 3246 color: #fff !important; 3247 border-color: #fff !important; 3248 opacity: 1 !important; 3249 } 3250 3251 /* (Legacy --bp-cta-on override removed â primary's palette is now 3252 fixed at the base, so there's no longer a white-on-white scenario 3253 for sections to opt out of. Sections that need a light CTA on 3254 dark imagery should pick the `primary-light` variant instead.) */ 3255 3256 /* ===== §9.1.x Text-overlay placement (9-position) ================== 3257 Used by sections that lay copy on top of media (hero slides, 3258 grid tiles). The wrapping element opts in via `[data-bp-overlay]` 3259 and reads four custom properties per breakpoint emitted by 3260 snippets/bp-overlay-place.liquid: 3261 --bp-overlay-block-{d,m} start | center | end (vertical) 3262 --bp-overlay-inline-{d,m} start | center | end (horizontal) 3263 --bp-overlay-text-{d,m} start | center | end 3264 3265 The element is a column-direction flex container, so the 3266 vertical (block) axis is the MAIN axis (justify-content) and the 3267 horizontal (inline) axis is the CROSS axis (align-items). The 3268 text-align inherits from this container down to descendants. */ 3269 [data-bp-overlay] { 3270 display: flex; 3271 flex-direction: column; 3272 justify-content: var(--bp-overlay-block-m, end); 3273 align-items: var(--bp-overlay-inline-m, center); 3274 } 3275 [data-bp-overlay] > * { 3276 text-align: var(--bp-overlay-text-m, center); 3277 } 3278 @media screen and (min-width: 1024px) { 3279 [data-bp-overlay] { 3280 justify-content: var(--bp-overlay-block-d, center); 3281 align-items: var(--bp-overlay-inline-d, start); 3282 } 3283 [data-bp-overlay] > * { 3284 text-align: var(--bp-overlay-text-d, start); 3285 } 3286 } 3287 3288 /* ============================================================ 3289 Discount Kit (Helium) â Peak Progress GWP bar 3290 Targets the markup the app's embed injects (`#peak-progress-wrapper`). 3291 Restyled to match the BP free-gift bar in the Figma: Messina Sans 3292 typography, BP color tokens, slim 4px track with cream background + 3293 gold fill + a dot indicator at the fill's right edge. 3294 If marketing later swaps in a different DK block (e.g. tiered), 3295 these selectors stop matching gracefully â DK's own styles show 3296 through. 3297 ============================================================ */ 3298 #peak-progress-wrapper { 3299 padding: 16px 0 24px; 3300 border-bottom: 1px solid rgba(23, 22, 9, 0.08); 3301 font-family: var(--bp-font-body); 3302 color: var(--bp-color-text); 3303 } 3304 #peak-progress-wrapper .peak-progress-container { 3305 display: block; 3306 } 3307 #peak-progress-wrapper .peak-progress-message { 3308 display: flex; 3309 justify-content: space-between; 3310 align-items: baseline; 3311 margin-bottom: 8px; 3312 gap: 12px; 3313 } 3314 #peak-progress-wrapper .threshold-title, 3315 #peak-progress-wrapper .threshold-count-message, 3316 #peak-progress-wrapper .threshold-counter { 3317 font-family: var(--bp-font-body); 3318 font-size: 14px; 3319 font-weight: 700; 3320 letter-spacing: -0.14px; 3321 color: var(--bp-color-text); 3322 } 3323 #peak-progress-wrapper .peak-progress-bar-outer { 3324 position: relative; 3325 height: 4px; 3326 background: #E8DFD0; 3327 border-radius: 0; 3328 overflow: visible; 3329 } 3330 #peak-progress-wrapper .peak-progress-bar-inner { 3331 position: relative; 3332 height: 100%; 3333 background: #EBAE55; 3334 border-radius: 0; 3335 transition: width 0.3s ease; 3336 } 3337 /* Dot indicator at the right edge of the fill â matches the BP Figma. 3338 Pinned to the inner bar's end via `right: 0` + `translate(50%, -50%)` 3339 so it tracks the fill width without extra JS. */ 3340 #peak-progress-wrapper .peak-progress-bar-inner::after { 3341 content: ''; 3342 position: absolute; 3343 top: 50%; 3344 right: 0; 3345 transform: translate(50%, -50%); 3346 width: 12px; 3347 height: 12px; 3348 border-radius: 50%; 3349 background: var(--bp-color-bg-page); 3350 border: 2px solid #EBAE55; 3351 box-sizing: border-box; 3352 } 3353 #peak-progress-wrapper .progress-copy { 3354 margin: 12px 0 0; 3355 } 3356 #peak-progress-wrapper .peak-progress-amount { 3357 font-family: var(--bp-font-body); 3358 font-size: 13px; 3359 color: var(--bp-color-body-copy); 3360 } 3361 3362 /* ============================================================ 3363 BP Search Drawer + Search Panel 3364 ============================================================ */ 3365 3366 /* Prevent Horizon's search modal from appearing â bp-search-drawer 3367 always intercepts the trigger and handles search instead (its own JS 3368 branches internally on settings.bp_br_search_enabled to pick 3369 Bloomreach vs. native Shopify results; the container/UI is the same 3370 either way). Target both the custom-element wrapper and the inner dialog. */ 3371 dialog-component#search-modal, 3372 #search-modal dialog { 3373 display: none !important; 3374 } 3375 3376 /* /search page â hide the "Search" / "Search results" title (it stays in 3377 the DOM as the page's a11y <h1>, just visually hidden) and let the 3378 search input span full width, so the page opens with a full-width bar 3379 over the two-column results, matching the topnav search popup. */ 3380 .search-page__header h1 { 3381 position: absolute !important; 3382 width: 1px; 3383 height: 1px; 3384 margin: -1px; 3385 padding: 0; 3386 border: 0; 3387 overflow: hidden; 3388 clip: rect(0 0 0 0); 3389 white-space: nowrap; 3390 } 3391 .search-page__header { 3392 display: block; 3393 } 3394 3395 /* Restyle Horizon's boxed _search-input into the Figma underline bar: 3396 search icon + input on one row, a single bottom rule, full width. */ 3397 .search-page__header .search-page-input__parent { width: 100%; } 3398 .search-page__header search-page-input-component { 3399 max-width: 100% !important; 3400 width: 100%; 3401 display: flex; 3402 align-items: center; 3403 gap: 8px; 3404 margin: 0 0 28px; 3405 padding-block: 10px; 3406 border-bottom: 1px solid var(--bp-color-body-copy, #74736B); 3407 background: transparent; 3408 } 3409 .search-page__header .search-page-input { 3410 border: 0 !important; 3411 border-radius: 0 !important; 3412 background: transparent !important; 3413 padding: 4px 0 !important; 3414 font-family: var(--bp-font-body); 3415 font-size: 16px; 3416 color: var(--bp-color-text); 3417 } 3418 .search-page__header .search-page-input::placeholder { 3419 color: rgba(23, 22, 9, 0.62); 3420 } 3421 /* Icon inline (Horizon positions it absolutely for the boxed look). */ 3422 .search-page__header search-page-input-component .search__icon { 3423 position: static !important; 3424 left: auto !important; 3425 flex-shrink: 0; 3426 width: 44px; 3427 height: 44px; 3428 aspect-ratio: 1 / 1; 3429 color: var(--bp-color-text); 3430 opacity: 0.6; 3431 } 3432 .search-page__header search-page-input-component .search__icon svg { 3433 width: 44px; 3434 height: 44px; 3435 } 3436 /* Keep the clear button pinned to the right edge of the row. */ 3437 .search-page__header search-page-input-component .search__reset-button { 3438 right: 0; 3439 } 3440
3441 .bp-sp { 3442 background: var(--bp-color-bg-page); 3443 padding: 28px var(--bp-section-pad-x) 40px; 3444 } 3445 3446 .bp-sp__body { 3447 display: grid; 3448 grid-template-columns: 200px 1fr; 3449 gap: 48px; 3450 align-items: start; 3451 } 3452 3453 .bp-sp__sidebar { 3454 display: flex; 3455 flex-direction: column; 3456 gap: 24px; 3457 flex-shrink: 0; 3458 } 3459 3460 .bp-sp__group-title { 3461 margin: 0 0 10px; 3462 font-family: var(--bp-font-body); 3463 font-size: 13px; 3464 font-weight: 700; 3465 line-height: 145%; 3466 color: var(--bp-color-text); 3467 } 3468 3469 .bp-sp__links { 3470 list-style: none; 3471 margin: 0; 3472 padding: 0; 3473 display: flex; 3474 flex-direction: column; 3475 gap: 8px; 3476 } 3477 3478 .bp-sp__link { 3479 font-family: var(--bp-font-body); 3480 font-size: 14px; 3481 font-weight: 400; 3482 line-height: 145%; 3483 color: var(--bp-color-text); 3484 text-decoration: none; 3485 } 3486 .bp-sp__link:hover { 3487 text-decoration: underline; 3488 text-underline-offset: 3px; 3489 } 3490 3491 .bp-sp__products-title { 3492 margin: 0 0 16px; 3493 font-family: var(--bp-font-body); 3494 font-size: 13px; 3495 font-weight: 700; 3496 line-height: 145%; 3497 color: var(--bp-color-text); 3498 } 3499 3500 .bp-sp__grid { 3501 list-style: none; 3502 margin: 0; 3503 padding: 0; 3504 display: grid; 3505 /* Tablet 3 per row; desktop 4 (below); mobile 2 (below). 3-up read as too 3506 large on desktop for both the /search results and the topnav search- 3507 drawer suggested results, which share this grid (QA 7/16, Adrienne). */ 3508 grid-template-columns: repeat(3, 1fr); 3509 gap: var(--bp-section-gap); 3510 } 3511 @media screen and (min-width: 1024px) { 3512 .bp-sp__grid { 3513 grid-template-columns: repeat(4, 1fr); 3514 } 3515 } 3516 3517 .bp-sp__item { 3518 min-width: 0; 3519 } 3520 .bp-sp__item > product-card, 3521 .bp-sp__item .bp-card-host { display: contents; } 3522 3523 /* Match the sitewide product-card ratio (3 / 4, see .bp-card__media above). 3524 The old 325 / 513 (~0.634) was taller/narrower than the source art, so 3525 object-fit: cover cropped the sides of every search-drawer thumbnail. */ 3526 .bp-sp__item .bp-card__media { 3527 aspect-ratio: 3 / 4; 3528 height: auto; 3529 } 3530 3531 .bp-sp__footer { 3532 margin-top: 24px; 3533 } 3534 3535 .bp-sp__view-all { 3536 display: inline-flex; 3537 align-items: center; 3538 justify-content: center; 3539 padding: 10px 28px; 3540 font-family: var(--bp-font-body); 3541 font-size: 14px; 3542 font-weight: 500; 3543 line-height: 1; 3544 letter-spacing: 0.01em; 3545 color: var(--bp-color-text); 3546 background: transparent; 3547 border: 1px solid var(--bp-color-text); 3548 cursor: pointer; 3549 text-decoration: none; 3550 transition: background 0.15s ease, color 0.15s ease; 3551 } 3552 .bp-sp__view-all:hover { 3553 background: var(--bp-color-text); 3554 color: var(--bp-color-cta-text, #FDFFFA); 3555 } 3556 3557 @media screen and (max-width: 1023px) { 3558 .bp-sp__body { 3559 grid-template-columns: 180px 1fr; 3560 gap: 32px; 3561 } 3562 } 3563 3564 @media screen and (max-width: 767px) { 3565 .bp-sp { 3566 padding: 20px 16px 32px; 3567 } 3568 .bp-sp__body { 3569 grid-template-columns: 1fr; 3570 gap: 24px; 3571 } 3572 .bp-sp__grid { 3573 grid-template-columns: repeat(2, 1fr); 3574 } 3575 .bp-sp__view-all { 3576 width: 100%; 3577 } 3578 } 3579 3580 /* GTM / ad-network tracking pixels injected into <body> are 1Ã1 3581 images rendered inline, adding ~20px of line-height space below 3582 the footer. Force them out of the normal flow. We target by 3583 domain and by size so legitimate content images are unaffected. 3584 3585 EXCLUSIONS on the size-based selector mirror the earlier rule 3586 (~L37) â the Stylitics "How to Wear It" widget renders each tile 3587 as <img width="1" height="1" class="stylitics-ui-image" 3588 data-testid="stylitics-ui-image" loading="eager"> as a lazy-load 3589 placeholder, then resizes via Stylitics' --max-size CSS variable. 3590 Without these :not() guards the tiles stay pinned at 1Ã1 and the 3591 widget looks empty. */ 3592 img[src*="dstillery.com"], 3593 img[src*="doubleclick.net"], 3594 img[src*="google-analytics.com"], 3595 img[src*="facebook.com/tr"], 3596 img[src*="bat.bing.com"], 3597 img[width="1"][height="1"]:not([class*="stylitics"]):not([data-testid]):not([loading]) { 3598 position: absolute !important; 3599 width: 1px !important; 3600 height: 1px !important; 3601 overflow: hidden !important; 3602 pointer-events: none !important; 3603 } 3604 3605 /* ============================================================ 3606 Narvar (Shipping Protection) â restyle injected buttons + hide 3607 the Narvar product surface. 3608 3609 Narvar's storefront JS injects: 3610 - <button id="CartDrawer-Checkout-DP-With"> primary checkout 3611 - <button id="CartDrawer-Checkout-DP-Without"> secondary "without 3612 shipping protection" 3613 - A product page for the underlying SKU `narvardeliveryprotection` 3614 (shouldn't be browsable as a normal product) 3615 3616 Atlas's CSS used Tailwind utilities (rgb(0 0 0 / opacity), 50px 3617 height, font-weight 600). We rewrite using BP design tokens 3618 (--bp-color-text, --bp-color-cta-text, --bp-font-body, 52px to 3619 match the BP cart drawer's other checkout buttons) so the 3620 Narvar buttons land in the same visual rhythm as the rest of 3621 the BP cart drawer instead of looking like an Atlas/Tailwind 3622 graft. 3623 3624 Atlas reference: Narvar custom CSS pasted by client 2026-05-22. 3625 ============================================================ */ 3626 3627 /* NOTE: previously had a global 3628 div[data-product-handle="narvardeliveryprotection"] 3629 { display: none !important; } 3630 rule here to hide the Narvar SKU from PLP/search. Removed â 3631 our cart line items now (correctly, for Narvar to detect them) 3632 carry data-product-handle, so the rule also hid the Narvar 3633 line ITEM in the cart, breaking checkout. Hide the product 3634 from PLP/search via Shopify product visibility instead 3635 (Admin â Product â Sales channels â uncheck Online Store) 3636 or by leaving it out of every collection. 3637 3638 Now also adding the canonical CartPage-* IDs alongside the 3639 CartDrawer-* ones â Narvar uses different ID prefixes on the 3640 /cart page vs the drawer, so the styling has to cover both. */ 3641 3642 /* Primary checkout button (Narvar injects this in place of the 3643 stock checkout button when the toggle is ON). Match BP's 3644 `.bp-cart-drawer__btn--primary` look. */ 3645 button#CartDrawer-Checkout-DP-With { 3646 height: 52px; 3647 margin: 0; 3648 padding: 0 24px; 3649 background: var(--bp-color-text); 3650 color: var(--bp-color-cta-text); 3651 border: 1px solid var(--bp-color-text); 3652 font-family: var(--bp-font-body); 3653 font-size: 17px; 3654 font-weight: 500; 3655 line-height: normal; 3656 letter-spacing: -0.17px; 3657 text-transform: none; 3658 cursor: pointer; 3659 transition: opacity 0.2s ease, background 0.2s ease; 3660 } 3661 button#CartDrawer-Checkout-DP-With:hover { 3662 opacity: 0.85; 3663 } 3664 3665 /* Narvar's current widget build adds its own stable class 3666 (.narvar-cart-widget-button-checkout) alongside the DP-With id and 3667 ships `background` + text-color rules on that class via a 3668 stylesheet it injects itself (loaded later, after bp-fonts.liquid, 3669 via GTM) â same load-order problem already documented above for 3670 the CTA-casing fix. Out-specify with the bp-cart-drawer ancestor +
3671 !important so BP black always wins regardless of when Narvar's 3672 stylesheet lands, instead of just hoping the ID selector above is 3673 specific enough. */ 3674 bp-cart-drawer button#CartDrawer-Checkout-DP-With, 3675 bp-cart-drawer button.narvar-cart-widget-button-checkout { 3676 background: var(--bp-color-text, #171609) !important; 3677 color: var(--bp-color-cta-text) !important; 3678 } 3679 3680 /* Protection total appended to the primary Checkout button. Narvar 3681 renders a `#checkout-price` span inside its DP-With button on BOTH 3682 the flyout and the /cart page. We previously hid it on the flyout 3683 only (`bp-cart-drawer #checkout-price { display:none }`), per an 3684 earlier "design doesn't show the price" note â but the /cart page 3685 was never scoped by that rule, so it always showed the total. That 3686 left the two surfaces inconsistent: page had the total, flyout did 3687 not. QA 7/27 (Dragana) asks the flyout to match the page, so the 3688 hide is removed and the total (subtotal + protection) shows on the 3689 checkout button on both surfaces. */ 3690 3691 /* Secondary "Checkout without shipping protection" button. Match 3692 BP's `.bp-cart-drawer__btn--secondary` look â same height, BP 3693 typography, dark outline on cream/white surface. */ 3694 button#CartDrawer-Checkout-DP-Without { 3695 height: 52px; 3696 margin: 0; 3697 padding: 0 24px; 3698 background: transparent; 3699 color: var(--bp-color-text); 3700 border: 1px solid var(--bp-color-text); 3701 font-family: var(--bp-font-body); 3702 font-size: 17px; 3703 font-weight: 500; 3704 line-height: normal; 3705 letter-spacing: -0.17px; 3706 text-transform: none; 3707 cursor: pointer; 3708 transition: background 0.2s ease, color 0.2s ease; 3709 } 3710 button#CartDrawer-Checkout-DP-Without:hover { 3711 background: var(--bp-color-bg-cream); 3712 } 3713 3714 /* Same buttons but on the /cart page â Narvar uses CartPage-* IDs 3715 there. Mirror the styling so the cart page looks consistent with 3716 the drawer. */ 3717 button#CartPage-Checkout-DP-With { 3718 height: 52px; 3719 margin: 0; 3720 padding: 0 24px; 3721 background: var(--bp-color-text); 3722 color: var(--bp-color-cta-text); 3723 border: 1px solid var(--bp-color-text); 3724 font-family: var(--bp-font-body); 3725 font-size: 17px; 3726 font-weight: 500; 3727 line-height: normal; 3728 letter-spacing: -0.17px; 3729 cursor: pointer; 3730 transition: opacity 0.2s ease; 3731 } 3732 button#CartPage-Checkout-DP-With:hover { 3733 opacity: 0.85; 3734 } 3735 button#CartPage-Checkout-DP-Without { 3736 height: 52px; 3737 margin: 0; 3738 padding: 0 24px; 3739 background: transparent; 3740 color: var(--bp-color-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: background 0.2s ease; 3749 } 3750 button#CartPage-Checkout-DP-Without:hover { 3751 background: var(--bp-color-bg-cream); 3752 } 3753 3754 /* Narvar widget mount â collapse margin until Narvar populates it, 3755 so the empty <div> doesn't leave a phantom gap above the 3756 subtotal block. `:not(:empty)` keeps the natural spacing once 3757 Narvar's React renders content into the mount. */ 3758 .bp-cart-drawer__narvar-widget:not(:empty) { 3759 margin: 0; 3760 } 3761 3762 /* ---- Shipping Protection loading skeleton (QA 7/27, Dragana) ---- 3763 Narvar injects the real cream box a few seconds after the flyout opens / 3764 the cart page loads (its async bundle). This shimmer placeholder holds the 3765 box's shape until then, so there's no empty-whitespace gap that then pops. 3766 It mimics `.narvar-cart-widget-card` (cream, 8px padding, column, ~64px). 3767 Hidden the instant Narvar's real widget lands in the adjacent mount 3768 (`:has(+ mount > *)`) and when the JS marks it done / times out. 3769 Supersedes the earlier reserve-space approach (#307), which read as an 3770 empty whitespace gap. */ 3771 .bp-cart-drawer__sp-skeleton, 3772 .bp-cart-page__sp-skeleton { 3773 display: flex; 3774 flex-direction: column; 3775 gap: 8px; 3776 padding: 8px; 3777 min-height: 64px; 3778 box-sizing: border-box; 3779 background: var(--bp-color-bg-cream, #F7F6EA); 3780 border-radius: 0; 3781 } 3782 .bp-cart-drawer__sp-skeleton:has(+ .bp-cart-drawer__narvar-widget > *), 3783 .bp-cart-page__sp-skeleton:has(+ .bp-cart-page__narvar-widget > *), 3784 .bp-sp-skeleton--hidden { 3785 display: none !important; 3786 } 3787 .bp-cart-drawer__sp-skeleton-head, 3788 .bp-cart-page__sp-skeleton-head { 3789 display: flex; 3790 align-items: center; 3791 justify-content: space-between; 3792 gap: 8px; 3793 }
3794 .bp-sp-skeleton-bar { 3795 display: block; 3796 height: 12px; 3797 border-radius: 2px; 3798 background: linear-gradient( 3799 90deg, 3800 rgba(23, 22, 9, 0.06) 25%, 3801 rgba(23, 22, 9, 0.12) 37%, 3802 rgba(23, 22, 9, 0.06) 63% 3803 ); 3804 background-size: 400% 100%; 3805 animation: bpSpShimmer 1.4s ease infinite; 3806 } 3807 .bp-cart-drawer__sp-skeleton-title, 3808 .bp-cart-page__sp-skeleton-title { width: 128px; height: 14px; } 3809 .bp-cart-drawer__sp-skeleton-amt, 3810 .bp-cart-page__sp-skeleton-amt { width: 44px; height: 14px; } 3811 .bp-cart-drawer__sp-skeleton-desc, 3812 .bp-cart-page__sp-skeleton-desc { width: 82%; height: 10px; } 3813 @keyframes bpSpShimmer { 3814 0% { background-position: 100% 50%; } 3815 100% { background-position: 0 50%; } 3816 } 3817 @media (prefers-reduced-motion: reduce) { 3818 .bp-sp-skeleton-bar { animation: none; } 3819 } 3820 3821 /* Shipping Protection â skin Narvar's NATIVE widget as the BP cream box 3822 (design parity). Narvar owns the price + copy + opt-out logic; we only 3823 style its card. Key off Narvar's STABLE classes (narvar-cart-widget-*) 3824 only â the _*_196oa_* hashes change on every app version. */ 3825 .narvar-cart-widget-card { 3826 background: var(--bp-color-bg-cream, #F7F6EA) !important; 3827 /* Figma parity (QA 7/23, Brooke): 8px padding + flex container. 3828 Direct children are Narvar's header row (title + amount) and the 3829 description â they MUST stack, so column direction is required; 3830 row (the flex default) would sit the description beside the 3831 header. Narvar owns the header's own internal left/right layout 3832 via its hashed classes; we don't touch it. */ 3833 display: flex !important; 3834 flex-direction: column !important; 3835 padding: 8px !important; 3836 gap: 8px !important; 3837 justify-content: center !important; 3838 /* stretch (not flex-start) so the direct children fill the row â 3839 Narvar's header row needs full width for its own space-between to 3840 push the amount to the right. Setting width:100% on the header 3841 directly isn't an option: its class (_196oa_) is a per-version 3842 hash. Text stays left-aligned either way. */ 3843 align-items: stretch !important; 3844 align-self: stretch !important; 3845 color: var(--bp-color-text, #171609) !important; 3846 border-radius: 0 !important; 3847 } 3848 /* Force BP black on ALL widget text â Narvar's --color-accent (blue) leaks 3849 into nested spans (the amount + title inner spans). */ 3850 .narvar-cart-widget-card, 3851 .narvar-cart-widget-card * { 3852 color: var(--bp-color-text, #171609) !important; 3853 } 3854 /* The design shows just the "Shipping Protection" label + info icon â 3855 hide Narvar's UPS/InsureShield logo image IN THE CARD only (the info 3856 modal shares the .narvar-cart-widget-logo class and keeps its hero logo). */ 3857 .narvar-cart-widget-card .narvar-cart-widget-logo { 3858 display: none !important; 3859 } 3860 .narvar-cart-widget-title { 3861 /* Heading / H6 â Signifier */ 3862 font-family: var(--bp-font-display) !important; 3863 font-size: 14px !important; 3864 font-weight: 300 !important; 3865 line-height: 120% !important; 3866 letter-spacing: -0.28px !important; 3867 color: var(--bp-color-text, #171609) !important; 3868 } 3869 .narvar-cart-widget-amount, 3870 .narvar-cart-widget-amount span { 3871 /* Body / Book / Small â Messina, right-aligned */ 3872 font-family: var(--bp-font-body) !important; 3873 font-size: 14px !important; 3874 font-weight: 400 !important; 3875 letter-spacing: -0.14px !important; 3876 color: var(--bp-color-text, #171609) !important; 3877 } 3878 .narvar-cart-widget-description { 3879 /* Body / Book / Tiny â Messina */ 3880 font-family: var(--bp-font-body) !important; 3881 font-size: 10px !important; 3882 font-weight: 400 !important; 3883 line-height: 145% !important; 3884 letter-spacing: -0.1px !important; 3885 color: var(--bp-color-text, #171609) !important; 3886 margin-top: -12px; 3887 } 3888 /* Mobile: pull the description up tight under the header (QA 7/23, Brooke). */ 3889 @media screen and (max-width: 749px) { 3890 .narvar-cart-widget-description { 3891 margin-top: -16px !important; 3892 } 3893 } 3894 /* Info icon â BP black (Narvar defaults to a blue accent) + clickable 3895 (the drawer closes on click so Narvar's info surface isn't clipped). */ 3896 .narvar-cart-widget-info-icon { 3897 fill: var(--bp-color-text, #171609) !important; 3898 width: 13px !important; 3899 height: 13px !important; 3900 cursor: pointer; 3901 } 3902 3903 /* ---- Narvar Shipping Protection info modal ("Peace of mind, delivered"). 3904 Narvar injects it with minimal/broken styles; skin it with BP tokens. 3905 Stable IDs (#insurance-modal-*) are reliable â the _*_1mgdm_* hashes churn 3906 per app version. Shown when the widget info icon is clicked (the cart 3907 drawer closes so this isn't clipped). ---- */ 3908 #insurance-modal-container { 3909 position: fixed; 3910 inset: 0; 3911 width: 100vw; 3912 z-index: 9999999999; 3913 display: flex; 3914 align-items: center; 3915 justify-content: center; 3916 padding: 16px; 3917 background: rgba(23, 22, 9, 0.45); 3918 } 3919 #insurance-modal-content { 3920 position: relative; 3921 width: 100%; 3922 max-width: 420px; 3923 max-height: 88vh; 3924 overflow-y: auto; 3925 background: #FDFFFA; 3926 color: var(--bp-color-text, #171609); 3927 font-family: var(--bp-font-body); 3928 padding: 32px 24px 24px; 3929 } 3930 #insurance-modal-header { 3931 position: relative; 3932 text-align: center; 3933 margin-bottom: 20px; 3934 } 3935 #insurance-modal-icon-wrapper { 3936 display: flex; 3937 justify-content: center; 3938 margin-bottom: 12px; 3939 } 3940 #insurance-modal-icon-image { 3941 width: auto !important; 3942 height: 40px !important; 3943 } 3944 #insurance-modal-hero-title { 3945 font-family: var(--bp-font-display); 3946 font-size: 22px; 3947 font-weight: 300; 3948 line-height: 120%; 3949 letter-spacing: -0.44px; 3950 margin: 0; 3951 color: var(--bp-color-text, #171609); 3952 } 3953 #insurance-modal-close-button { 3954 position: absolute; 3955 top: -14px; 3956 right: -8px; 3957 background: transparent; 3958 border: 0; 3959 padding: 4px; 3960 line-height: 0; 3961 cursor: pointer; 3962 } 3963 #insurance-modal-features-list { 3964 list-style: none; 3965 padding: 0; 3966 margin: 0 0 4px; 3967 } 3968 #insurance-modal-features-list li { margin: 0 0 14px; } 3969 [id^="insurance-modal-feature-"][id$="-title"] { 3970 font-family: var(--bp-font-body); 3971 font-size: 14px; 3972 font-weight: 600; 3973 color: var(--bp-color-text, #171609); 3974 } 3975 [id^="insurance-modal-feature-"][id$="-text"] { 3976 font-family: var(--bp-font-body); 3977 font-size: 13px; 3978 line-height: 145%; 3979 color: var(--bp-color-text, #171609); 3980 } 3981 #insurance-modal-content hr { 3982 border: 0; 3983 border-top: 1px solid rgba(23, 22, 9, 0.15); 3984 margin: 16px 0; 3985 } 3986 #insurance-modal-body-text, 3987 #insurance-modal-footer { 3988 font-family: var(--bp-font-body); 3989 font-size: 11px; 3990 line-height: 150%; 3991 color: var(--bp-color-body-copy, #74736B); 3992 margin: 0; 3993 } 3994 #insurance-modal-footer a { color: inherit; text-decoration: underline; }
3995 #insurance-modal-powered-by { align-items: center; } 3996 /* The "Powered by Narvar Secure" logo has no width/height attr, so a global 3997 img rule was stretching it â pin it to its intrinsic 16px. */ 3998 #insurance-modal-powered-by-icon { 3999 width: 16px !important; 4000 height: 16px !important; 4001 flex: 0 0 16px; 4002 } 4003 4004 /* Narvar's toggle-card shell ships with a built-in `margin: 1rem 0` 4005 from its CSS module (hashed class `_card_196oa_1`, which changes 4006 on every Narvar extension bump). We target the stable widget-style 4007 class instead â `.opt-out-button` is the class Narvar's React 4008 applies to the card root when its widget_style setting is the 4009 opt-out button variant (matches what BP uses). Zero out the 4010 margin so our drawer's own `gap` controls spacing. 4011 4012 If a future widget-style switch is made (toggle / checkbox / 4013 opt-in-button / add-button / flyout), add the corresponding 4014 class here â see Narvar's `C` constant for the full list. */ 4015 .opt-out-button { 4016 margin: 0 !important; 4017 } 4018 4019 /* Spacing between Narvar's primary (DP-With) and secondary 4020 (DP-Without) injected buttons. Narvar's React inlines 4021 `style="margin: 1rem 0"` on the DP-Without button; force a 4022 top-only gap so the buttons sit flush against the form 4023 bottom but still breathe between each other. Applied to both 4024 surfaces (drawer + cart page). */ 4025 button#CartDrawer-Checkout-DP-Without, 4026 button#CartPage-Checkout-DP-Without { 4027 margin: 0.5rem 0 0 !important; 4028 } 4029 /* Mobile: tighter 4px gap between the primary + secondary Narvar 4030 buttons (half the desktop value, same ratio as before â was 8px 4031 over 1rem/16px). Kept directly after the 0.5rem rule above â equal 4032 specificity + !important on both means source order decides, so 4033 this MUST come last to win on mobile. */ 4034 @media screen and (max-width: 749px) { 4035 button#CartDrawer-Checkout-DP-Without, 4036 button#CartPage-Checkout-DP-Without { 4037 margin: 4px 0 0 !important; 4038 } 4039 } 4040 4041 /* CTA casing (QA 7/14) â Narvar's injected checkout buttons should read 4042 Title Case ("Checkout Without Shipping Protection"), matching the native 4043 "Checkout" / "View Bag" CTAs and the design. The Narvar app's custom_css 4044 (config/settings_data.json) forces text-transform: uppercase at the same 4045 `button#id` specificity as bp-fonts, so load order decided it â hence the 4046 inconsistent casing. Out-specify by scoping to the BP cart wrappers 4047 (bp-cart-drawer / bp-cart-page â higher specificity) + !important so BP 4048 always wins. `capitalize` (not `none`) because Narvar's own label text is 4049 lower/upper-cased, so capitalize is what yields the Title-Case look. */ 4050 bp-cart-drawer button#CartDrawer-Checkout-DP-With, 4051 bp-cart-drawer button#CartDrawer-Checkout-DP-Without, 4052 bp-cart-page button#CartPage-Checkout-DP-With, 4053 bp-cart-page button#CartPage-Checkout-DP-Without { 4054 text-transform: capitalize !important; 4055 } 4056 4057 /* ============================================================ 4058 BP hero slide + shop-by-category link styles â moved here 4059 from sections/blocks during the block migration. 4060 4061 Why: Shopify's per-block / per-section stylesheet loading 4062 proved unreliable for these specific markup patterns when 4063 the section was migrated from inline section-defined blocks 4064 to theme blocks. Putting the rules in the global bp-fonts 4065 style block guarantees they apply regardless of which 4066 section/block stylesheet Shopify chooses to load. 4067 4068 References: 4069 - blocks/_bp-hero-slide.liquid (rendered article markup) 4070 - blocks/_bp-shop-link.liquid (rendered <li> markup) 4071 - sections/bp-hero-slider.liquid (wrapper + nav + dots) 4072 - sections/bp-shop-by-category.liquid (heading + <ul>) 4073 ============================================================ */ 4074 4075 /* Shopify wraps every rendered theme block in a 4076 <div class="shopify-block" data-shopify-editor-block="..."> 4077 wrapper for theme-editor click-to-edit. That wrapper breaks 4078 direct-child layouts (the slide track's grid, the link list's 4079 flex row, etc.) because the slide/list-item is no longer a 4080 direct child of the parent â it sits inside the wrapper. 4081 4082 `display: contents` makes the wrapper layout-transparent: its 4083 children behave as if they were direct children of the 4084 parent for layout purposes (grid items, flex items). Block 4085 identity for the editor stays â the wrapper still exists in 4086 the DOM and carries data-shopify-editor-block. */ 4087 .bp-hero__track > .shopify-block, 4088 .bp-hero__content-inner > .shopify-block, 4089 .bp-shop-by-category__list > .shopify-block { 4090 display: contents; 4091 } 4092 4093 /* ----- bp-hero-slide ----- */ 4094 4095 .bp-hero__slide { 4096 grid-column: 1 / 2; 4097 grid-row: 1 / 2; 4098 position: relative; 4099 display: block; 4100 width: 100%; 4101 max-width: 100vw;
4102 min-height: var(--bp-hero-min-height-mobile); 4103 aspect-ratio: var(--bp-hero-ratio-m, auto); 4104 color: var(--bp-hero-text-color); 4105 4106 opacity: 0; 4107 visibility: hidden; 4108 pointer-events: none; 4109 transition: opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1), 4110 visibility 0s linear 0.8s; 4111 } 4112 4113 bp-hero-slider[data-has-ratio-m='true'] .bp-hero__slide { 4114 display: flex; 4115 flex-direction: column; 4116 /* Unset the min-height so the slide's own aspect-ratio (set on 4117 .bp-hero__slide above) drives its height on mobile. A min-height 4118 floor here (e.g. max(50vh, max-content)) overrode the ratio and 4119 pinned every slide to ~50vh, so the picked "Aspect ratio (mobile)" 4120 had no visible effect. Copy taller than the ratio still grows the 4121 slide via the flex column's max-content. */ 4122 min-height: unset; 4123 } 4124 bp-hero-slider[data-has-ratio-m='true'] .bp-hero__content { 4125 flex: 1; 4126 position: relative; 4127 width: 100%; 4128 min-height: auto; 4129 } 4130 @media screen and (min-width: 1024px) { 4131 bp-hero-slider[data-has-ratio-d='true'] .bp-hero__slide { 4132 display: flex; 4133 flex-direction: column; 4134 min-height: max-content; 4135 } 4136 bp-hero-slider[data-has-ratio-d='true'] .bp-hero__content { 4137 flex: 1; 4138 position: relative; 4139 width: 100%; 4140 min-height: auto; 4141 } 4142 } 4143 4144 .bp-hero__slide.is-active { 4145 opacity: 1; 4146 visibility: visible; 4147 pointer-events: auto; 4148 transition: opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1), 4149 visibility 0s linear 0s; 4150 } 4151 4152 @media (prefers-reduced-motion: reduce) { 4153 .bp-hero__slide, 4154 .bp-hero__slide.is-active { 4155 transition: none; 4156 } 4157 /* a11y (WCAG 2.3.3): neutralise every smooth-scroll rail site-wide in 4158 one place â the BP carousels (product-carousel, category-tiles, 4159 shop-the-look, tabbed-gallery, our-most-loved, cart, etc.) each set 4160 `scroll-behavior: smooth` locally. This overrides them all for users 4161 who prefer reduced motion, instead of guarding 13 files. */ 4162 html:focus-within, 4163 *, 4164 *::before, 4165 *::after { 4166 scroll-behavior: auto !important; 4167 } 4168 } 4169 4170 .bp-hero__media { 4171 position: absolute; 4172 inset: 0; 4173 width: 100%; 4174 height: 100%; 4175 overflow: hidden; 4176 background: var(--color-background-muted, #f3f3f0); 4177 z-index: 0; 4178 } 4179 4180 .bp-hero__picture { 4181 position: absolute; 4182 inset: 0; 4183 width: 100%; 4184 height: 100%; 4185 display: block; 4186 } 4187 4188 .bp-hero__image { 4189 position: absolute; 4190 inset: 0; 4191 width: 100%; 4192 height: 100%; 4193 object-fit: cover; 4194 object-position: var(--bp-hero-img-pos-m); 4195 display: block; 4196 } 4197 @media screen and (min-width: 1024px) { 4198 .bp-hero__image { 4199 object-position: var(--bp-hero-img-pos-d); 4200 } 4201 } 4202 4203 .bp-hero__image--placeholder { 4204 background: linear-gradient(135deg, #e8e6df 0%, #cfccc1 100%); 4205 } 4206 4207 .bp-hero__content { 4208 position: relative; 4209 z-index: 1; 4210 flex-direction: column; 4211 min-height: var(--bp-hero-min-height-mobile); 4212 padding: var(--bp-hero-content-padding-mobile); 4213 padding-bottom: 88px; 4214 gap: 16px; 4215 color: var(--bp-hero-text-color); 4216 } 4217 4218 .bp-hero__content-inner { 4219 display: flex; 4220 flex-direction: column; 4221 gap: 16px; 4222 width: 100%; 4223 max-width: var(--bp-hero-content-max-mobile); 4224 align-items: var(--bp-overlay-inline-m, start); 4225 } 4226 @media screen and (min-width: 1024px) { 4227 .bp-hero__content-inner { 4228 align-items: var(--bp-overlay-inline-d, start); 4229 } 4230 } 4231 4232 .bp-hero__eyebrow { 4233 margin: 0; 4234 color: var(--bp-hero-text-color); 4235 font-family: var(--bp-font-body); 4236 font-size: 17px; 4237 font-style: normal; 4238 font-weight: 500; 4239 line-height: 110%; 4240 letter-spacing: -0.17px; 4241 text-transform: uppercase; 4242 } 4243 4244 .bp-hero__title { 4245 margin: 0; 4246 color: var(--bp-hero-text-color); 4247 font-family: var(--bp-font-display); 4248 font-size: clamp(36px, 6vw, 50px); 4249 font-style: normal; 4250 font-weight: 300; 4251 line-height: 120%; 4252 letter-spacing: -1px; 4253 } 4254 4255 .bp-hero__description { 4256 margin: 0; 4257 color: var(--bp-hero-text-color); 4258 font-family: var(--bp-font-body); 4259 font-size: 17px; 4260 font-style: normal; 4261 font-weight: 500; 4262 line-height: 145%; 4263 letter-spacing: -0.17px; 4264 } 4265 .bp-hero__description > * { 4266 margin: 0; 4267 color: inherit; 4268 font: inherit; 4269 letter-spacing: inherit; 4270 } 4271 .bp-hero__description > * + * { 4272 margin-top: 8px; 4273 } 4274 4275 .bp-hero__ctas { 4276 margin-top: 16px; 4277 width: 100%; 4278 align-items: var(--bp-overlay-inline-m, start); 4279 justify-content: var(--bp-overlay-inline-m, start); 4280 } 4281 4282 .bp-hero__cta.bp-cta { 4283 border-color: var(--bp-hero-text-color); 4284 color: #000; 4285 } 4286 .bp-hero__cta.bp-cta--primary { 4287 background: var(--bp-color-text); 4288 color: #fff; 4289 } 4290 .bp-hero__cta.bp-cta--primary:hover { 4291 background: transparent; 4292 color: var(--bp-hero-text-color); 4293 } 4294 .bp-hero__cta.bp-cta--primary-light { 4295 background: var(--bp-color-bg-page); 4296 color: var(--bp-color-text); 4297 border-color: #fff; 4298 } 4299 .bp-hero__cta.bp-cta--primary-light:hover { 4300 background: transparent; 4301 color: var(--bp-hero-text-color); 4302 border-color: var(--bp-hero-text-color); 4303 } 4304 .bp-hero__cta.bp-cta--secondary:hover { 4305 background: var(--bp-hero-text-color); 4306 color: #fff; 4307 } 4308 4309 @media screen and (max-width: 480px) { 4310 .bp-hero__content { 4311 padding-bottom: 24px; 4312 } 4313 } 4314 4315 @media screen and (max-width: 749px) { 4316 .bp-hero__title { 4317 font-size: clamp(24px, 6vw, 36px); 4318 letter-spacing: -0.5px; 4319 } 4320 } 4321 4322 @media screen and (min-width: 1024px) { 4323 .bp-hero__slide {
4324 min-height: var(--bp-hero-min-height-desktop); 4325 aspect-ratio: var(--bp-hero-ratio-d, auto); 4326 } 4327 4328 .bp-hero__content { 4329 min-height: var(--bp-hero-min-height-desktop); 4330 padding: var(--bp-hero-content-padding-desktop); 4331 padding-bottom: var(--bp-hero-content-padding-desktop); 4332 } 4333 4334 .bp-hero__content-inner { 4335 max-width: none; 4336 gap: 20px; 4337 } 4338 .bp-hero__description { 4339 max-width: var(--bp-hero-content-max-desktop); 4340 } 4341 4342 .bp-hero__ctas { 4343 width: 100%; 4344 margin-top: 24px; 4345 align-items: var(--bp-overlay-inline-d, start); 4346 justify-content: var(--bp-overlay-inline-d, start); 4347 } 4348 4349 .bp-hero__cta.bp-cta { 4350 min-width: 140px; 4351 } 4352 } 4353 4354 /* ----- bp-shop-by-category link ----- */ 4355 4356 .bp-shop-by-category__item { 4357 flex-shrink: 0; 4358 } 4359 4360 .bp-shop-by-category__link { 4361 display: inline-block; 4362 color: inherit; 4363 text-decoration: underline; 4364 text-underline-offset: 4px; 4365 font-family: var(--bp-font-body); 4366 font-size: 17px; 4367 font-style: normal; 4368 font-weight: 500; 4369 line-height: normal; 4370 letter-spacing: -0.17px; 4371 transition: opacity 0.2s ease; 4372 } 4373 .bp-shop-by-category__link:hover { opacity: 0.65; } 4374 4375 /* ============================================================ 4376 PAGE.CAREERS / PAGE.ABOUTUS â default body-copy color 4377 ------------------------------------------------------------ 4378 Body-style bp-text blocks default to var(--bp-color-body-copy, 4379 #74736B). Overrides the FINAL fallback in bp-text's color chain 4380 (`color: var(--bp-text-color, var(--bp-knobs-text, 4381 var(--bp-color-text))))` â not the `color` property itself â 4382 so a merchant-set text_color on the block (which writes 4383 --bp-text-color inline) STILL WINS. 4384 4385 Scoped to .bp-text--ff-body so display-family bp-text (h1-h6 4386 using Signifier) keeps the dark --bp-color-text default. 4387 ============================================================ */ 4388 main[data-template='page.careers'] .bp-text--ff-body, 4389 main[data-template='page.aboutus'] .bp-text--ff-body, 4390 main[data-template='page.sherylsloves'] .bp-text--ff-body, 4391 main[data-template='page.prospect-introduction'] .bp-text--ff-body { 4392 --bp-color-text: var(--bp-color-body-copy, #74736B); 4393 } 4394 4395 /* /pages/customer-care â hero (bp-image-text-banner) keeps the 32px 4396 mobile top padding but drops bottom padding to 0 so the link 4397 grid below sits flush against the hero. The §9.1 bp_padding_y_m 4398 knob is a single value (block top+bottom); the override below 4399 zeros only padding-block-end. */ 4400 @media screen and (max-width: 1023px) { 4401 main[data-template='page.customer-care'] [data-section-id$='__hero'] { 4402 padding-block-end: 0 !important; 4403 } 4404 } 4405 4406 /* /pages/prospect-introduction â imagery grid content-tile spec. 4407 The Figma frame is 40px padding / 10px gap / flex-column / 4408 flex-start / stretch on the inner copy stack. Default §9.1.x 4409 tile-content uses 24Ã16 padding and 8px gap; override here. */ 4410 main[data-template='page.prospect-introduction'] [data-section-id$='__bp_intro_imagery_grid'] .bp-grid__tile-content { 4411 padding: 40px !important; 4412 } 4413 main[data-template='page.prospect-introduction'] [data-section-id$='__bp_intro_imagery_grid'] .bp-grid__tile-content-inner { 4414 display: flex !important; 4415 flex-direction: column !important; 4416 align-items: flex-start !important; 4417 gap: 10px !important; 4418 align-self: stretch !important; 4419 } 4420 4421 /* /pages/brands-we-love â intro section spec. 4422 The section stays full-bleed (bp_bg_section cream extends to 4423 viewport edges) and uses its natural stacked layout. The 4424 overrides just dial the vertical padding to 80/40 and zero 4425 the bp-fc__inner padding + min-height that were stacking on 4426 top of the §9.1 section padding. */ 4427 html body [data-section-id$='__bwl_intro'], 4428 html body [data-section-id='bwl_intro'] { 4429 padding-block: 80px 40px !important; 4430 } 4431 html body [data-section-id$='__bwl_intro'] .bp-fc__inner, 4432 html body [data-section-id='bwl_intro'] .bp-fc__inner { 4433 padding: 0 !important; 4434 min-height: 0 !important; 4435 gap: 0 !important; 4436 } 4437 html body [data-section-id$='__bwl_intro'] .bp-fc__features:empty, 4438 html body [data-section-id='bwl_intro'] .bp-fc__features:empty { 4439 display: none !important; 4440 } 4441 @media (max-width: 1023px) { 4442 html body [data-section-id$='__bwl_intro'], 4443 html body [data-section-id='bwl_intro'] { 4444 padding-block: 40px 24px !important; 4445 } 4446 } 4447 4448 /* /pages/brands-we-love â brand-grid tile titles match Figma H4: 4449 24/300/Signifier/120%/-0.48px, white. The global .bp-fs-h4 sets 4450 125% / -0.01em; this scoped rule tightens line-height + letter- 4451 spacing to the spec exactly. The H4 preset on bp-text already 4452 supplies size 24 + tag h4; per-instance JSON overrides 4453 (font_family: display, font_weight: 300) carry the family/weight. */ 4454 html body [data-section-id$='__bwl_grid'] .bp-grid__tile .bp-text.bp-fs-h4, 4455 html body [data-section-id='bwl_grid'] .bp-grid__tile .bp-text.bp-fs-h4 { 4456 line-height: 120% !important; 4457 letter-spacing: -0.48px !important; 4458 } 4459 4460 /* /pages/brands-we-love â hero "big one" CTA forced to left. 4461 The single Shop Now CTA must hug the left edge of the slide on 4462 both breakpoints. Forces the group's main-axis to flex-start 4463 AND defeats the §9.2 mobile stretch rule 4464 ([data-bp-cta-group]:not([data-dir-m='row']) .bp-block-cta { width: 100% }) 4465 which was making the button full-width on mobile and centering 4466 the label via the button's own justify-content: center. */ 4467 html body [data-section-id$='__bwl_hero'] .bp-hero__content [data-bp-cta-group], 4468 html body [data-section-id='bwl_hero'] .bp-hero__content [data-bp-cta-group] { 4469 justify-content: flex-start !important;
4470 align-items: flex-start !important; 4471 } 4472 html body [data-section-id$='__bwl_hero'] .bp-hero__content [data-bp-cta-group] .bp-block-cta, 4473 html body [data-section-id$='__bwl_hero'] .bp-hero__content [data-bp-cta-group] .bp-cta, 4474 html body [data-section-id='bwl_hero'] .bp-hero__content [data-bp-cta-group] .bp-block-cta, 4475 html body [data-section-id='bwl_hero'] .bp-hero__content [data-bp-cta-group] .bp-cta { 4476 width: auto !important; 4477 margin-right: auto !important; 4478 align-self: flex-start !important; 4479 } 4480 4481 /* ============================================================ 4482 YOTPO WIDGET â BP typography overrides 4483 ============================================================ 4484 Yotpo injects its widget via tf-integration / yotpo-loader 4485 scripts and inlines its own font (Futura-PT / Open Sans) on 4486 the rendered elements. Force the BP body family on every 4487 Yotpo text node so reviews + Q&A match the rest of the site. 4488 The review BODY copy (.yotpo-read-more-text + 4489 .yotpo-comment-content retailer reply) additionally gets the 4490 Figma "Body/XSmall Book" spec â Messina 12 / 400 / 145% / 4491 -0.12 / body-copy gray. */ 4492 .yotpo-widget-instance, 4493 .yotpo-widget-instance *, 4494 .yotpo-reviews-main-widget, 4495 .yotpo-reviews-main-widget *, 4496 .yotpo-reviews-star-ratings-widget, 4497 .yotpo-reviews-star-ratings-widget * { 4498 font-family: var(--bp-font-body), 'Messina Sans VF', system-ui, -apple-system, sans-serif !important; 4499 } 4500 .yotpo-widget-instance .yotpo-read-more-text, 4501 .yotpo-widget-instance .yotpo-text-container, 4502 .yotpo-widget-instance .yotpo-comment-content { 4503 color: var(--bp-color-body-copy, #74736B) !important; 4504 font-family: var(--bp-font-body), 'Messina Sans VF', system-ui, sans-serif !important; 4505 font-size: 12px !important; 4506 font-style: normal !important; 4507 font-weight: 400 !important; 4508 line-height: 145% !important; 4509 letter-spacing: -0.12px !important; 4510 } 4511 /* Bold title elements â review headline + retailer reply heading. 4512 Figma "Body/Semi/Small" spec: Messina 14 / 660 / 145% / -0.14 4513 in BP black (#171609). */ 4514 .yotpo-widget-instance .yotpo-review-title, 4515 .yotpo-widget-instance .yotpo-comment-title { 4516 color: var(--bp-color-text, #171609) !important; 4517 font-family: var(--bp-font-body), 'Messina Sans VF', system-ui, sans-serif !important; 4518 font-size: 14px !important; 4519 font-style: normal !important; 4520 font-weight: 700 !important; 4521 line-height: 145% !important; 4522 letter-spacing: -0.14px !important; 4523 } 4524 4525 /* "With media" toggle â Yotpo renders a button > label > SVG-circle 4526 stack that flexes weirdly under the BP font override (label 4527 becomes block-level, SVG drops below the text). Pin the button 4528 to flex/row + 8px gap, keep the SVG inline. When aria-pressed, 4529 fill the circle so the selected state reads. */ 4530 .yotpo-widget-instance .yotpo-media-select { 4531 display: inline-flex !important; 4532 flex-direction: row !important; 4533 align-items: center !important; 4534 gap: 8px !important; 4535 background: transparent !important; 4536 border: 1px solid rgba(23, 22, 9, 0.18) !important; 4537 border-radius: 0 !important; 4538 padding: 10px 12px !important; 4539 cursor: pointer !important; 4540 color: var(--bp-color-text, #171609) !important; 4541 font-family: var(--bp-font-body), 'Messina Sans VF', system-ui, sans-serif !important; 4542 font-size: 14px !important; 4543 font-weight: 500 !important; 4544 line-height: 145% !important; 4545 letter-spacing: -0.14px !important; 4546 } 4547 .yotpo-widget-instance .yotpo-media-select .yotpo-radio-base { 4548 display: inline-flex !important; 4549 align-items: center !important; 4550 flex: 1 1 auto !important; 4551 margin: 0 !important; 4552 padding: 0 !important; 4553 cursor: pointer !important; 4554 } 4555 .yotpo-widget-instance .yotpo-media-select .yotpo-selected-value { 4556 color: inherit !important; 4557 line-height: inherit !important; 4558 } 4559 .yotpo-widget-instance .yotpo-media-select .yotpo-radio-icon { 4560 flex: 0 0 auto !important; 4561 width: 16px !important; 4562 height: 16px !important; 4563 display: block !important; 4564 } 4565 .yotpo-widget-instance .yotpo-media-select[aria-pressed='true'] .yotpo-radio-icon circle { 4566 fill: var(--bp-color-text, #171609) !important; 4567 stroke: var(--bp-color-text, #171609) !important; 4568 } 4569 4570 /* ââ Header scroll-logo swap âââââââââââââââââââââââââââââââââââââ 4571 Swaps the header logo to the dedicated "scroll" variant
4572 (settings.logo_scroll, rendered in blocks/_header-logo.liquid) 4573 when the nav enters its compact state. Independent of Horizon's 4574 transparent/inverse logo system â only the logo mark swaps. 4575 Selectors carry #header-component so they outrank the existing 4576 `.header-logo:has(...)` / `.header-logo__image-container--inverse` 4577 display rules regardless of source order. 4578 4579 ââ Why data-bp-nav and not data-sticky-state ââââââââââââââââââ 4580 These rules used to key off Horizon's [data-sticky-state='active'] 4581 (assets/header.js #observeStickyPosition). That flag is written by 4582 Horizon's IntersectionObserver from the header's own visibility â 4583 and the rules below CHANGE the header's height and position. Any 4584 state whose styles perturb the geometry that produces the state is 4585 a feedback loop: the observer writes a value, the header resizes / 4586 unpins, the observer re-fires, writes the opposite value. The 4587 header strobes between variants. (Measured 2026-07-14: with 4588 threshold: 1, isIntersecting is false at ratio 0.9888 and true at 4589 ratio 1, so Horizon's flag flips at exactly rect.top === 0 â the 4590 single offset where a header pinned at top: -1px hands off from 4591 in-flow to pinned. That is where the strobe appeared.) 4592 4593 data-bp-nav is owned solely by the scroll-threshold state machine 4594 in layout/theme.liquid, driven by scrollY â an input the header's 4595 own size cannot perturb. Horizon keeps writing data-sticky-state 4596 for its own purposes (opacity, view-transition-name); it no longer 4597 drives any geometry, so the two can never fight. */ 4598 .header-logo__image-container--scroll { 4599 display: none; 4600 } 4601 4602 /* ââ Positioning model ââââââââââââââââââââââââââââââââââââââââââââ 4603 Resting nav is IN FLOW and scrolls away with the page; only the 4604 compact bar is fixed. Cancels Horizon's `position: sticky; 4605 top: -1px` for sticky="always" (sections/header.liquid:553). 4606 4607 .header-section keeps the resting header's height via 4608 --bp-header-rest-h even while the child is fixed, so nothing below 4609 ever shifts when the compact bar engages. That reserved space is 4610 what makes scrollY a stable trigger: no reflow â no scroll 4611 anchoring â no feedback into the threshold. Without it, going 4612 fixed would pull ~70px of content up and move the very scroll 4613 offset the state machine reads. 4614 4615 !important + the body prefix because Horizon's rule is 4616 `.header-section:has(> #header-component[sticky='always'])`, whose 4617 :has() takes the specificity of its argument (an id + attr), and 4618 section stylesheet blocks are bundled separately from this inline 4619 style tag â source order isn't guaranteed. 4620 4621 NB: don't write Liquid tag delimiters in these comments, even 4622 inside a CSS comment. Liquid parses tags before CSS exists, so a 4623 literal stylesheet/style tag written here is read as a real tag 4624 nested inside this style block and throws at compile. */ 4625 body .header-section:has(> #header-component[sticky='always']) { 4626 position: static !important; 4627 top: auto !important; 4628 min-height: var(--bp-header-rest-h, auto); 4629 } 4630 4631 #header-component[data-bp-nav='compact'] { 4632 position: fixed; 4633 top: 0; 4634 left: 0; 4635 right: 0; 4636 z-index: var(--layer-sticky); 4637 } 4638 4639 /* flex (not block) so the icon centers on both axes instead of 4640 sitting on the inline text baseline, which left descender 4641 whitespace below it and made it look pushed toward the top of 4642 the row. */ 4643 #header-component[data-bp-nav='compact'] .header-logo__image-container--scroll { 4644 display: flex; 4645 align-items: center; 4646 justify-content: center; 4647 } 4648 4649 #header-component[data-bp-nav='compact'] .header-logo__image-container--original, 4650 #header-component[data-bp-nav='compact'] .header-logo__image-container--inverse { 4651 display: none; 4652 } 4653 4654 /* Design request: collapse header__columns vertical padding to 0 4655 the moment the header becomes sticky, so the sticky bar sits flush 4656 rather than keeping the resting-state --header-padding. Overrides 4657 header.liquid's `.header__columns { --padding-block-start/end }` 4658 (assets/base.css .spacing-style reads these into padding-block). */ 4659 #header-component[data-bp-nav='compact'] .header__columns { 4660 --padding-block-start: 0px; 4661 --padding-block-end: 0px; 4662 } 4663 4664 /* Design request: once the logo has swapped to the compact scroll 4665 mark, let the left and right grid tracks (.header__column--left,
4666 .header__column--right) hug their content width instead of the 4667 resting-state 1fr / minmax(max-content, 1fr) tracks â frees up 4668 space for the center column while sticky. --header-left/-right 4669 feed --header-template-columns (grid-template-columns) above; 4670 the ID selector's specificity beats every non-sticky :has()-based 4671 --header-left/-right override in this file. */ 4672 #header-component[data-bp-nav='compact'] .header__columns { 4673 --header-left: max-content; 4674 --header-right: max-content; 4675 } 4676 4677 /* --------------------------------------------------------------- 4678 Quick-view product template (?view=quickview) â Atlas parity. 4679 4680 The Publitas digital-catalog product modal loads 4681 /products/<handle>?view=quickview inside its #prod-frame iframe. 4682 That renders templates/product.quickview.json (the buy box only). 4683 Strip the site chrome so the iframe shows an optimized product 4684 view â no topnav, announcement bar, footer, sticky ATC, or chat â 4685 rather than the whole storefront. 4686 4687 Scoped with :has() off the <main data-template> attribute 4688 (theme.liquid emits data-template="blog", which 4689 resolves to "product.quickview" here), so nothing leaks onto 4690 the normal PDP. Matches Atlas templates/product.quickview.liquid, 4691 which display:none's #shopify-section-header / -footer / etc. 4692 --------------------------------------------------------------- */ 4693 4694 /* Hide all site chrome in the quickview modal. display:none is correct 4695 here: the cart drawer is removed from the iframe entirely (see 4696 bp-quickview-cart-bridge.liquid). The just-added item is shown by the 4697 PARENT catalog page's cart drawer instead â it runs in full page 4698 context (so its section-scoped line re-render works reliably) and 4699 opens in the top layer, above the Publitas modal. Trying to render the 4700 drawer inside the iframe was fragile: its syncItemsList() walks 4701 ancestor shopify-section wrappers and re-fetches sections against the 4702 iframe URL, which didn't repopulate the just-added line. */ 4703 body:has(main[data-template='product.quickview']) #header-group, 4704 body:has(main[data-template='product.quickview']) > footer, 4705 body:has(main[data-template='product.quickview']) .bp-sticky-atc, 4706 body:has(main[data-template='product.quickview']) #chat-button { 4707 display: none !important; 4708 } 4709 4710 /* Same hides keyed off the BODY CLASS (layout/theme.liquid adds 4711 `template-quickview`) instead of `:has(mainâ¦)`. The `:has(mainâ¦)` form only 4712 matches AFTER <main> parses â which comes after the header â so on each 4713 product change the header / announcement bar / BP logo / top menu flashed 4714 visible for a frame before being hidden (Dragana QA 7/22). The body class 4715 is present at first paint, so these hide with no flash. 4716 This block ALSO strips the PDP-only buy-box extras the digital-catalog quick 4717 view shouldn't show (Dragana QA 7/22): the gallery breadcrumb + "How to Wear 4718 It" chip, the size-chart link, the TrueFit find-my-size widget, and the 4719 Product Detail / Size & Fit / Shipping & Returns accordions. */ 4720 body.template-quickview #header-group, 4721 body.template-quickview > footer, 4722 body.template-quickview .bp-sticky-atc, 4723 body.template-quickview #chat-button, 4724 body.template-quickview .bp-pdp-gallery__crumbs, 4725 body.template-quickview .bp-pdp-gallery__htwi, 4726 body.template-quickview .bp-size-chart-link, 4727 body.template-quickview .tfc-fitrec-product, 4728 body.template-quickview .bp-acc { 4729 display: none !important; 4730 } 4731 4732 body:has(main[data-template='product.quickview']) main.content-for-layout { 4733 padding-top: 0; 4734 margin-top: 0; 4735 } 4736 4737 /* PDP sticky add-to-cart bar (.bp-sticky-atc, z-index: 100) sits above 4738 everything by design, but that also puts it above the mobile nav 4739 drawer (bp-mobile-drawer, z-index ~5-6 off --layer-heightened) â 4740 covering the bottom menu items when the drawer is open on a PDP. 4741 Hide it for the duration instead of escalating the drawer's z-index, 4742 which would ripple into every other component sharing that token. */ 4743 body:has(bp-mobile-drawer .bp-mobile-drawer__details[open]) .bp-sticky-atc { 4744 display: none !important; 4745 } 4746 4747 /* ============================================================ 4748 AB Tasty social-proof popup ("POPULAR! N views in the last N days", 4749 injected at runtime via GTM/AB Tasty â .ab_widget_container_social-proof_*). 4750 It was anchored to the left of the PDP gallery and overflowed the image
4751 frame / got clipped at the viewport's left edge on wide monitors (QA 7/21). 4752 Re-anchor it as a safe bottom-left toast so it stays fully on-screen at any 4753 width and can't overlap the gallery. NOTE: the auto-dismiss timing ("not 4754 gone in a few seconds") is an AB Tasty CAMPAIGN setting, not theme code. 4755 ============================================================ */ 4756 .ab_widget_container_social-proof_content { 4757 position: fixed !important; 4758 left: 16px !important; 4759 right: auto !important; 4760 bottom: 16px !important; 4761 top: auto !important; 4762 transform: none !important; 4763 max-width: min(320px, calc(100vw - 32px)) !important; 4764 z-index: 30 !important; 4765 } 4766 4767 /* ============================================================ 4768 Yotpo referral widget (instance 506320) â BP-controlled overrides. 4769 These previously lived only in Yotpo's dashboard Custom CSS; kept here 4770 so they're version-controlled and survive a Yotpo re-config. Renders on 4771 the refer-a-friend page and the Proper Insider rewards page. Class names 4772 are doubled to outrank Yotpo's runtime-injected single-class rules. 4773 ============================================================ */ 4774 .yotpo-widget-referral-widget .yotpo-center-container.yotpo-center-container { 4775 height: 626px; 4776 } 4777 /* Don't force the copy-code text white â keep it readable (BP text color) 4778 against the widget's light surface. */ 4779 .yotpo-widget-referral-widget .yotpo-copy-text-button .yotpo-copy-text.yotpo-copy-text { 4780 color: var(--bp-color-text) !important; 4781 } 4782 4783 /* ============================================================ 4784 Cart-flyout (quick-add drawer) Add-to-bag button â match the PDP CTA. 4785 The drawer's buy button is redistributed into .bp-qd__cta-slot, OUTSIDE 4786 .product-information, so the PDP button rules (bp-pdp-styles) never reach 4787 it â it came out mis-sized / stretched with no bag icon (QA: Amber). 4788 Mirror the PDP spec: 17px / -0.17px / 500, filled black, 20px bag icon, 4789 hover inverts. Icon = shared assets/bp-bag-icon.svg (white); hover uses 4790 filter:brightness(0) to flip it black on the transparent button. 4791 ============================================================ */ 4792 dialog.quick-add-modal.bp-qd add-to-cart-component button, 4793 dialog.quick-add-modal.bp-qd button[name="add"], 4794 dialog.quick-add-modal.bp-qd .buy-buttons button[type="submit"] { 4795 width: 100%; 4796 background: var(--bp-color-text, #171609) !important; 4797 color: var(--bp-color-cta-text, #FDFFFA) !important; 4798 border: 1px solid var(--bp-color-text, #171609) !important; 4799 border-radius: 0 !important; 4800 padding: 16px 24px !important; 4801 font-family: var(--bp-font-body) !important; 4802 font-size: 17px !important; 4803 font-weight: 500 !important; 4804 line-height: normal !important; 4805 letter-spacing: -0.17px !important; 4806 text-transform: none !important; 4807 display: inline-flex !important; 4808 align-items: center !important; 4809 justify-content: center !important; 4810 gap: 10px !important; 4811 } 4812 dialog.quick-add-modal.bp-qd add-to-cart-component button .svg-wrapper.add-to-cart-icon, 4813 dialog.quick-add-modal.bp-qd add-to-cart-component button .add-to-cart-icon, 4814 dialog.quick-add-modal.bp-qd button[name="add"] .svg-wrapper.add-to-cart-icon, 4815 dialog.quick-add-modal.bp-qd button[name="add"] .add-to-cart-icon { 4816 display: none !important; 4817 } 4818 dialog.quick-add-modal.bp-qd add-to-cart-component button::after, 4819 dialog.quick-add-modal.bp-qd button[name="add"]::after, 4820 dialog.quick-add-modal.bp-qd .buy-buttons button[type="submit"]::after { 4821 content: '' !important; 4822 display: inline-block !important; 4823 flex: 0 0 20px !important; 4824 width: 20px !important; 4825 height: 20px !important; 4826 background-repeat: no-repeat; 4827 background-position: center; 4828 background-size: contain; 4829 background-image: url(//www.bostonproper.com/cdn/shop/t/1516/assets/bp-bag-icon.svg?v=5174825450042497821790192827); 4830 } 4831 dialog.quick-add-modal.bp-qd add-to-cart-component button:hover, 4832 dialog.quick-add-modal.bp-qd button[name="add"]:hover, 4833 dialog.quick-add-modal.bp-qd .buy-buttons button[type="submit"]:hover, 4834 dialog.quick-add-modal.bp-qd add-to-cart-component button:hover .add-to-cart-text, 4835 dialog.quick-add-modal.bp-qd add-to-cart-component button:hover .add-to-cart-text *, 4836 dialog.quick-add-modal.bp-qd button[name="add"]:hover .add-to-cart-text, 4837 dialog.quick-add-modal.bp-qd button[name="add"]:hover .add-to-cart-text * { 4838 background: transparent !important; 4839 color: var(--bp-color-text, #171609) !important; 4840 } 4841 dialog.quick-add-modal.bp-qd add-to-cart-component button:hover::after, 4842 dialog.quick-add-modal.bp-qd button[name="add"]:hover::after, 4843 dialog.quick-add-modal.bp-qd .buy-buttons button[type="submit"]:hover::after { 4844 filter: brightness(0); 4845 } 4846 4847 /* ============================================================ 4848 Cart Shop Pay Installments logo â black (QA: Amber). Shopify's 4849 native installments banner (the payment_terms filter in the 4850 Horizon snippet cart-summary.liquid) injects a purple Shop Pay
4851 wordmark as an img with id shoppay-installments-icon. BP wants it 4852 black in the cart. filter:brightness(0) flattens the artwork to 4853 solid black while preserving its transparency (same trick used on 4854 the cart-flyout bag icon above). Scoped to .cart-totals__installments 4855 so only the cart surfaces (drawer + cart page) are recoloured, not 4856 any other Shop Pay mark. 4857 ============================================================ */ 4858 .cart-totals__installments #shoppay-installments-icon { 4859 filter: brightness(0) !important; 4860 } 4861 4862 /* ============================================================ 4863 PLP Back-nav restore veil 4864 bp-bloomreach.js adds html.bp-plp-restoring while a saved scroll 4865 position is restored on a full-reload Back (PDP â Back â PLP), so the 4866 shopper sees a brief loader instead of the grid painting at the TOP and 4867 then jumping to their spot. Removed the instant the scroll lands (JS, 4868 with a safety timeout). A bfcache Back never sets it, so that stays 4869 instant. pointer-events:none so a real scroll/tap still passes through 4870 and cancels the restore. Global (targets <html>) so it covers both the 4871 /collections and /search PLPs, whose grid CSS lives in separate scoped 4872 stylesheets. 4873 ============================================================ */ 4874 .bp-plp-restore-veil { 4875 position: fixed; 4876 inset: 0; 4877 z-index: 2147483000; 4878 background: var(--bp-color-bg-page, #FEFFFA); 4879 display: flex; 4880 align-items: center; 4881 justify-content: center; 4882 pointer-events: none; 4883 opacity: 1; 4884 transition: opacity 0.4s ease; 4885 } 4886 /* Kill smooth-scroll while we pin the restore offset â Safari will 4887 otherwise animate (and lose) competing scrollTo calls. */ 4888 html.bp-plp-restoring { 4889 scroll-behavior: auto !important; 4890 } 4891 html.bp-plp-restoring body { 4892 scroll-behavior: auto !important; 4893 } 4894 /* JS adds .is-out to fade the veil to 0, then removes the element once 4895 faded â so it disappears SMOOTHLY, not "de golpe". */ 4896 .bp-plp-restore-veil.is-out { opacity: 0; } 4897 .bp-plp-restore-veil__spin { 4898 width: 34px; 4899 height: 34px; 4900 border-radius: 50%; 4901 border: 3px solid rgba(23, 22, 9, 0.15); 4902 border-top-color: var(--bp-color-text, #171609); 4903 animation: bpPlpRestoreSpin 0.7s linear infinite; 4904 } 4905 @media (prefers-reduced-motion: reduce) { 4906 .bp-plp-restore-veil { transition: none; } 4907 .bp-plp-restore-veil__spin { animation: none; } 4908 } 4909 @keyframes bpPlpRestoreSpin { to { transform: rotate(360deg); } } 4910 4911 /* ============================================================ 4912 PDP title de-flicker 4913 Each colourway is a separate product whose Shopify title carries the 4914 colour name; snippets/bp-pdp-title-color.liquid strips it (the colour is 4915 already shown by the swatch). Server-side stripping isn't possible â the 4916 title is a Text block bound to a dynamic source â so hide the title 4917 until the snippet strips it and marks it [data-bp-title-ready], so the full 4918 "â¦Colour" title never flashes first. visibility:hidden keeps its box (no 4919 CLS). A pure-CSS animation reveals it after 1.2s as a fail-safe, so it can 4920 never get stuck hidden if the JS doesn't run. 4921 ============================================================ */ 4922 .product-information h1:not([data-bp-title-ready]), 4923 .product-details h1:not([data-bp-title-ready]) { 4924 visibility: hidden; 4925 animation: bpTitleRevealSafety 0s linear 1.2s forwards; 4926 } 4927 @keyframes bpTitleRevealSafety { to { visibility: visible; } } 4928</style> 4929<link rel="stylesheet" href="//www.bostonproper.com/cdn/shop/t/1516/assets/bp-fonts-deferred.css?v=138496893836640374981790192827" media="print" onload="this.media='all'"> 4930 <noscript><link rel="stylesheet" href="//www.bostonproper.com/cdn/shop/t/1516/assets/bp-fonts-deferred.css?v=138496893836640374981790192827"></noscript>
4930<script src="//www.bostonproper.com/cdn/shop/t/1516/assets/bp-preorder-dates.js?v=90299843317653306041790192965" defer></script>
4930<style id="dg-consent-custom-style"> 4931 :host(.dg-consent-banner) {--dg-primary-font: var(--bp-font-body, 'Messina Sans VF', system-ui, sans-serif); 4932 --dg-consent-background-border: #ffffff; 4933 --consent-border-radius: 0;--dg-heading-font-size: 20px; 4934 --dg-heading-font-weight: 500;--dg-explanation-font-size: 15px; 4935 --dg-explanation-font-weight: 400;--dg-policy-option-heading-size: 15px; 4936 --dg-policy-option-heading-weight: 500; 4937 --dg-policy-option-description-font-size: 15px; 4938 --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 */ 4939 --dg-policy-option-essential-label-font-color: #666; 4940 --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; 4941 --dg-button-background: var(--bp-color-text, #171609) !important; 4942 --dg-button-border: none !important; 4943 --dg-button-radius: 0 !important;letter-spacing: 0.25px !important; 4944 font-family: var(--bp-font-body, 'Messina Sans VF', system-ui, sans-serif) !important; 4945 }:host(.dg-consent-banner) * { 4946 letter-spacing: 0.25px !important; 4947 font-family: var(--bp-font-body, 'Messina Sans VF', system-ui, sans-serif) !important; 4948 } 4949 4950 :host(.dg-consent-banner) .dg-app { 4951 max-width: 501px !important; 4952 } 4953 4954 :host(.dg-consent-banner) h1.dg-header { 4955 border-bottom: none !important; 4956 line-height: 28px !important; 4957 } 4958 4959 :host(.dg-consent-banner) .dg-header-close { 4960 position: absolute !important; 4961 top: 12px !important; 4962 right: 12px !important; 4963 width: 18px !important; 4964 height: 18px !important; 4965 padding: 4px !important; 4966 } 4967 4968 :host(.dg-consent-banner) .dg-header-close svg { 4969 display: none !important; 4970 }:host(.dg-consent-banner) .dg-header-close::before { 4971 content: url("//www.bostonproper.com/cdn/shop/t/1516/assets/icon-close.svg?v=127645775129621355101790192827") !important; 4972 position: absolute !important; 4973 top: 0 !important; 4974 right: 0 !important; 4975 bottom: 0 !important; 4976 left: 0 !important; 4977 margin: auto !important; 4978 width: 18px !important; 4979 height: 18px !important; 4980 } 4981 4982 :host(.dg-consent-banner) .dg-main-content-explanation { 4983 padding-top: 0 !important; 4984 line-height: 20px !important; 4985 } 4986 4987 :host(.dg-consent-banner) .dg-main-actions { 4988 border-color: transparent !important; 4989 } 4990 4991 :host(.dg-consent-banner) .dg-main-content-policies { 4992 border-top: 1px solid #999 !important; 4993 margin: 0 32px !important; 4994 padding: 0 !important; 4995 } 4996 4997 :host(.dg-consent-banner) .dg-slider.essential-label { 4998 font-style: italic !important; 4999 font-size: 15px !important; 5000 } 5001 5002 :host(.dg-consent-banner) .dg-main-actions button { 5003 text-transform: uppercase !important; 5004 font-size: 15px !important; 5005 font-weight: 500 !important; 5006 } 5007 5008 :host(.dg-consent-banner) .dg-button.essential_only { 5009 display: none !important; 5010 visibility: hidden !important; 5011 } 5012 5013 .dg-main-content-policy-option-description p { 5014 margin-top: 0 !important; 5015 } 5016 5017 .dg-main-content-declaration { 5018 padding: 0 !important; 5019 } 5020 5021 :host(.dg-consent-banner) ._48mA0q_buttonUnstyled { 5022 color: #000000 !important; 5023 } 5024</style> 5025
5026<script> 5027 // Consent bridge â Atlas parity (site-datagrail-style-and-logs.liquid). 5028 // DataGrail calls back with the customer's cookie preferences; we hand 5029 // them to Shopify so its pixels/managed scripts honour the choice. 5030 window.dgEvent = window.dgEvent || []; 5031 5032 function bpSyncReceivePrefs(dgEventData) { 5033 const cookiePreferences = 5034 dgEventData && dgEventData.consentPreferences && dgEventData.consentPreferences.cookieOptions; 5035 // No preferences payload â nothing to sync. Bail rather than 5036 // asserting consent the customer never gave. 5037 if (!cookiePreferences || !cookiePreferences.find) return; 5038 5039 const enabled = (key) => { 5040 const opt = cookiePreferences.find((item) => item && item.gtm_key === key); 5041 return opt ? opt.isEnabled : false; 5042 }; 5043 5044 window.Shopify.loadFeatures( 5045 [{ name: 'consent-tracking-api', version: '0.1' }], 5046 (error) => { 5047 if (error) { 5048 console.error('[bp-datagrail] Shopify Customer Privacy API failed to load', error); 5049 return; 5050 } 5051 window.Shopify.customerPrivacy.setTrackingConsent( 5052 { 5053 preferences: true, 5054 analytics: enabled('dg-category-performance'), 5055 marketing: enabled('dg-category-marketing'), 5056 sale_of_data: enabled('dg-category-marketing') 5057 }, 5058 (arg) => { 5059 if (window.Shopify && window.Shopify.designMode) { 5060 console.log('[bp-datagrail] consent captured', arg); 5061 } 5062 } 5063 ); 5064 } 5065 ); 5066 } 5067 5068 window.dgEvent.push({ event: 'preference_callback', params: bpSyncReceivePrefs }); 5069</script>
vendor: 1 bytes, line 5069
5069
5070<script> 5071 window.shop = { 5072 url: "https:\/\/www.bostonproper.com", 5073 template: "blog", 5074 environment: "production", 5075 theme: (typeof Shopify !== 'undefined' && Shopify.theme) ? Shopify.theme : null, 5076 themeSettings: { 5077 amplience_cdn_base_url: "https:\/\/media.bostonproper.com" 5078 }, 5079 br: { 5080 host: "https:\/\/core.dxpapi.com\/api\/v1\/core\/", 5081 suggestHost: "https:\/\/suggest.dxpapi.com\/api\/v2\/suggest\/", 5082 accountId: "8261", 5083 domainKey: "bostonproper", 5084 authKey: "xv7ok1fkm5gve1ms" 5085 }, 5086 badges: { 5087 bestseller: { 5088 enabled: true, 5089 label: "Best Seller" 5090 }, 5091 trending: { 5092 enabled: true, 5093 label: "Trending" 5094 } 5095 }, 5096 methods: {} 5097 }; 5098</script>
5098<script> 5099 window.bpColorSiblings = (function () { 5100 // Storefront token: the theme setting wins, but we fall back to the 5101 // known-good public token (recovered from Atlas's live theme.min.js 5102 // and verified against the Storefront API) so the GraphQL path works 5103 // even when config/settings_data.json isn't synced to the theme by 5104 // Shopify's GitHub integration. This is a PUBLIC unauthenticated 5105 // Storefront token â already exposed in Atlas's live JS â so it's 5106 // safe to embed client-side. NB: the older 23797⦠in Atlas's 5107 // .env.example is a stale placeholder and returns UNAUTHORIZED. 5108 var TOKEN = "04534ca2c4aa793f02c0c735d5d6160c"; 5109 var AMPLIENCE = "https:\/\/media.bostonproper.com"; 5110 var API_VERSION = '2024-07'; 5111 5112 function apiUrl() { 5113 var root = (window.Shopify && Shopify.routes && Shopify.routes.root) ? Shopify.routes.root : '/'; 5114 return root + 'api/' + API_VERSION + '/graphql.json'; 5115 } 5116 5117 function swatchUrl(style) { 5118 if (!style) return ''; 5119 return AMPLIENCE + '/i/bostonproper/' + style + '_2?$poiswatch$&img404=' + style + '_1'; 5120 } 5121 5122 /* Batched fetch. handles: array of product handles. Resolves to 5123 { handle: { available, style, swatchUrl, goLiveDate, price, compareAt, discount, promo } | null }. 5124 null = the colour is listed in bp_stylecolorlist but no product 5125 exists at that handle (drop the swatch). Rejects on transport / 5126 API error so callers can fall back to the legacy per-sibling path. */ 5127 function fetchSiblings(handles) { 5128 if (!handles || !handles.length) return Promise.resolve({}); 5129 if (!TOKEN) return Promise.reject(new Error('bpColorSiblings: no storefront token configured')); 5130 var aliasToHandle = {}; 5131 var parts = handles.map(function (h, i) { 5132 var alias = 'p' + i; 5133 aliasToHandle[alias] = h; 5134 return alias + ': product(handle: ' + JSON.stringify(h) + ') {' + 5135 ' availableForSale' + 5136 ' tags' + 5137 ' style: metafield(namespace: "BP_ProductAttributes", key: "bp_style") { value }' + 5138 ' goLive: metafield(namespace: "BP_ProductAttributes", key: "bp_golivedate") { value }' + 5139 ' colorList: metafield(namespace: "BP_ProductAttributes", key: "bp_stylecolorlist") { value }' + 5140 ' promo: metafield(namespace: "discounts", key: "discount_message") { value }' + 5141 ' priceRange { minVariantPrice { amount } }' + 5142 ' compareAtPriceRange { minVariantPrice { amount } }' + 5143 ' }'; 5144 }); 5145 5146 return fetch(apiUrl(), { 5147 method: 'POST', 5148 headers: { 5149 'Content-Type': 'application/json', 5150 'Accept': 'application/json', 5151 'X-Shopify-Storefront-Access-Token': TOKEN 5152 }, 5153 body: JSON.stringify({ query: '{' + parts.join(' ') + '}' }) 5154 }).then(function (r) { 5155 if (!r.ok) throw new Error('storefront HTTP ' + r.status); 5156 return r.json(); 5157 }).then(function (res) { 5158 var data = res && res.data; 5159 if (!data) throw new Error('storefront: no data'); 5160 var out = {}; 5161 Object.keys(aliasToHandle).forEach(function (alias) { 5162 var handle = aliasToHandle[alias]; 5163 var p = data[alias]; 5164 if (!p) { out[handle] = null; return; } 5165 var style = (p.style && p.style.value) ? p.style.value : ''; 5166 var price = (p.priceRange && p.priceRange.minVariantPrice) ? parseFloat(p.priceRange.minVariantPrice.amount) : null; 5167 var compareAt = (p.compareAtPriceRange && p.compareAtPriceRange.minVariantPrice) ? parseFloat(p.compareAtPriceRange.minVariantPrice.amount) : null; 5168 var discount = 0; 5169 if (price != null && compareAt != null && compareAt > price) { 5170 discount = Math.round(((compareAt - price) / compareAt) * 100); 5171 } 5172 var tags = Array.isArray(p.tags) ? p.tags : []; 5173 out[handle] = { 5174 available: p.availableForSale === true, 5175 style: style, 5176 swatchUrl: swatchUrl(style), 5177 goLiveDate: (p.goLive && p.goLive.value) ? p.goLive.value : '', 5178 // Sibling's own bp_stylecolorlist â the raw material for the PDP 5179 // swatch block's canonical-family union crawl. Each colour's list 5180 // drifts, so callers UNION them to reconstruct the full family. 5181 colorList: (p.colorList && p.colorList.value) ? p.colorList.value : '', 5182 price: price, 5183 compareAt: compareAt, 5184 discount: discount, 5185 // INV5/INV7 colour-family flag â the swatch row shows only for these 5186 // (matches the PDP + Liquid card gate), so bp-card-hydrate can hide 5187 // lone swatches on non-family products. 5188 isInv: tags.some(function (t) { return /INV5|INV7/i.test(t); }), 5189 // Red sale/promo line (Shopify-native discounts.discount_message, 5190 // same field the PDP + Liquid card read). PLP cards are BR-rendered 5191 // with no promo, so bp-card-hydrate injects it from here. 5192 promo: (p.promo && p.promo.value) ? p.promo.value : '' 5193 }; 5194 }); 5195 return out; 5196 }); 5197 } 5198 5199 /* Group-tag family discovery â the ROBUST family source. 5200 5201 The composed-handle path (fetchSiblings + hydrateRoot's crawl) derives each 5202 sibling's handle as `master + '-' + handleize(colourName)`. That breaks on 5203 BAD DATA where a product's handle token doesn't match its Colour name / 5204 bp_stylecolorlist entry â e.g. 2DO2220 whose handle ends `-black` but whose 5205 Colour option is "Luxe Links" and whose list is "Blue Bell, Luxe Links". 5206 From the blue PDP the composed black handle resolves to `â¦-luxe-links` 5207 (does NOT exist; the real handle is `â¦-black`), so the black sibling is 5208 unreachable and the swatch disappears with no way back (Critical 2DO2220). 5209 5210 Every colourway of a family shares a GROUP TAG (`YGroup_*`, also 5211 `INV5_*`/`nvgroup_*`). Querying Storefront by that tag returns the REAL 5212 siblings with their REAL handles + Colour-option names regardless of any 5213 name/handle/list drift â so every colour is reachable from every colourway. 5214
5215 `tag` is the product's ACTUAL YGroup_* tag string, read verbatim from Liquid 5216 (its format is inconsistent across families: `YGroup_2DO22` bare code vs. 5217 `YGroup_2BK45 Marilyn Cowl-Neck Charmeuse Blouse` code+name), so we pass it 5218 through as a search phrase unchanged. 5219 5220 Resolves to { realHandle: { handle, color, available, style, swatchUrl, 5221 goLiveDate, discount, colorList, price, compareAt, promo, isInv } } â the 5222 same shape hydrateRoot's crawl consumes from fetchSiblings, plus `color` 5223 (the Colour option value) so callers can build nameByHandle from REAL 5224 handles instead of composed ones. Rejects on transport/API error so callers 5225 can fall back to the composed-handle crawl. */ 5226 function fetchByGroup(tag) { 5227 if (!tag) return Promise.resolve({}); 5228 if (!TOKEN) return Promise.reject(new Error('bpColorSiblings: no storefront token configured')); 5229 // Mirror the verified probe: tag:'<value>' phrase match. Escape any single 5230 // quote in the tag value so the search phrase stays well-formed. 5231 var q = "tag:'" + String(tag).replace(/'/g, "\\'") + "'"; 5232 // first:100 covers large families (e.g. Marilyn = 24 colourways) in one 5233 // round-trip; families don't approach that ceiling in practice. 5234 var query = 'query($q:String!){products(first:100,query:$q){nodes{' + 5235 ' handle' + 5236 ' availableForSale' + 5237 ' tags' + 5238 ' options(first: 10) { name values }' + 5239 ' style: metafield(namespace: "BP_ProductAttributes", key: "bp_style") { value }' + 5240 ' goLive: metafield(namespace: "BP_ProductAttributes", key: "bp_golivedate") { value }' + 5241 ' colorList: metafield(namespace: "BP_ProductAttributes", key: "bp_stylecolorlist") { value }' + 5242 ' promo: metafield(namespace: "discounts", key: "discount_message") { value }' + 5243 ' priceRange { minVariantPrice { amount } }' + 5244 ' compareAtPriceRange { minVariantPrice { amount } }' + 5245 ' }}}'; 5246 return fetch(apiUrl(), { 5247 method: 'POST', 5248 headers: { 5249 'Content-Type': 'application/json', 5250 'Accept': 'application/json', 5251 'X-Shopify-Storefront-Access-Token': TOKEN 5252 }, 5253 body: JSON.stringify({ query: query, variables: { q: q } }) 5254 }).then(function (r) { 5255 if (!r.ok) throw new Error('storefront HTTP ' + r.status); 5256 return r.json(); 5257 }).then(function (res) { 5258 var nodes = res && res.data && res.data.products && res.data.products.nodes; 5259 if (!Array.isArray(nodes)) throw new Error('storefront: no group products'); 5260 var out = {}; 5261 nodes.forEach(function (p) { 5262 if (!p || !p.handle) return; 5263 var style = (p.style && p.style.value) ? p.style.value : ''; 5264 var price = (p.priceRange && p.priceRange.minVariantPrice) ? parseFloat(p.priceRange.minVariantPrice.amount) : null; 5265 var compareAt = (p.compareAtPriceRange && p.compareAtPriceRange.minVariantPrice) ? parseFloat(p.compareAtPriceRange.minVariantPrice.amount) : null; 5266 var discount = 0; 5267 if (price != null && compareAt != null && compareAt > price) { 5268 discount = Math.round(((compareAt - price) / compareAt) * 100); 5269 } 5270 // Colour option value â each sibling is ONE colourway, so its "Color" 5271 // (or "Colour") option carries the single real Colour name. This is the 5272 // authoritative colour label, immune to handle/list drift. 5273 var color = ''; 5274 var opts = Array.isArray(p.options) ? p.options : []; 5275 for (var i = 0; i < opts.length; i++) { 5276 var nm = (opts[i] && opts[i].name || '').toLowerCase(); 5277 if (nm === 'color' || nm === 'colour') { 5278 color = (opts[i].values && opts[i].values[0]) || ''; 5279 break; 5280 } 5281 } 5282 var tags = Array.isArray(p.tags) ? p.tags : []; 5283 out[p.handle] = { 5284 handle: p.handle, 5285 color: color, 5286 available: p.availableForSale === true, 5287 style: style, 5288 swatchUrl: swatchUrl(style), 5289 goLiveDate: (p.goLive && p.goLive.value) ? p.goLive.value : '', 5290 colorList: (p.colorList && p.colorList.value) ? p.colorList.value : '', 5291 price: price, 5292 compareAt: compareAt, 5293 discount: discount, 5294 isInv: tags.some(function (t) { return /INV5|INV7/i.test(t); }), 5295 promo: (p.promo && p.promo.value) ? p.promo.value : '' 5296 }; 5297 }); 5298 return out; 5299 }); 5300 } 5301 5302 /* Batched live-inventory lookup for GA4 item_stock_qty. `variantIds` is an 5303 array of numeric variant ids (from cart.js line.variant_id) or gids. 5304 Resolves to { numericVariantId: quantityAvailable }. Uses the Storefront 5305 `quantityAvailable` field â requires the token's 5306 `unauthenticated_read_product_inventory` scope; if it's missing or the 5307 variant doesn't track inventory, that entry is simply omitted so callers 5308 leave item_stock_qty blank (graceful, never throws). */ 5309 function fetchInventory(variantIds) { 5310 var ids = (variantIds || []) 5311 .filter(Boolean) 5312 .map(function (v) { 5313 var s = String(v); 5314 return s.indexOf('gid://') === 0 ? s : 'gid://shopify/ProductVariant/' + s; 5315 }); 5316 if (!ids.length || !TOKEN) return Promise.resolve({}); 5317 // qty + price + compareAtPrice per variant. price/compareAtPrice feed the 5318 // GA4 sale fields (item_category3 "Sale Price", item_original_price, 5319 // item_sale_discount) on cart events, which have no compare-at in cart.js. 5320 var query = 'query($ids:[ID!]!){nodes(ids:$ids){... on ProductVariant{id quantityAvailable price{amount} compareAtPrice{amount}}}}'; 5321 return fetch(apiUrl(), { 5322 method: 'POST', 5323 headers: { 5324 'Content-Type': 'application/json', 5325 'Accept': 'application/json', 5326 'X-Shopify-Storefront-Access-Token': TOKEN 5327 }, 5328 body: JSON.stringify({ query: query, variables: { ids: ids } }) 5329 }).then(function (r) { 5330 return r.ok ? r.json() : null; 5331 }).then(function (res) { 5332 var out = {}; 5333 var nodes = res && res.data && res.data.nodes; 5334 if (Array.isArray(nodes)) {
5335 nodes.forEach(function (n) { 5336 if (n && n.id) { 5337 out[n.id.replace(/^gid:\/\/shopify\/ProductVariant\//, '')] = { 5338 qty: (n.quantityAvailable != null) ? n.quantityAvailable : null, 5339 price: (n.price && n.price.amount != null) ? parseFloat(n.price.amount) : null, 5340 compareAt: (n.compareAtPrice && n.compareAtPrice.amount != null) ? parseFloat(n.compareAtPrice.amount) : null 5341 }; 5342 } 5343 }); 5344 } 5345 return out; 5346 }).catch(function () { return {}; }); 5347 } 5348 5349 /* On-demand GA4 track enrichment for BR cards, which carry no variant id / 5350 department / inventory. Accepts a single handle OR an array (batched, 5351 aliased â one request for a whole PLP grid). Resolves to a map 5352 { handle: { variantId, department, quantityAvailable } } so callers fill 5353 item_shopify_variant + item_category + item_stock_qty. Never throws. */ 5354 function fetchTrackData(handles) { 5355 var list = (Array.isArray(handles) ? handles : [handles]).filter(Boolean); 5356 // dedupe 5357 list = list.filter(function (h, i) { return list.indexOf(h) === i; }); 5358 if (!list.length || !TOKEN) return Promise.resolve({}); 5359 var aliasToHandle = {}; 5360 var parts = list.map(function (h, i) { 5361 var a = 't' + i; 5362 aliasToHandle[a] = h; 5363 return a + ': product(handle: ' + JSON.stringify(h) + ') {' + 5364 ' variants(first: 1) { nodes { id quantityAvailable selectedOptions { name value } } }' + 5365 ' dept: metafield(namespace: "BP_ProductAttributes", key: "bp_department") { value }' + 5366 ' }'; 5367 }); 5368 return fetch(apiUrl(), { 5369 method: 'POST', 5370 headers: { 5371 'Content-Type': 'application/json', 5372 'Accept': 'application/json', 5373 'X-Shopify-Storefront-Access-Token': TOKEN 5374 }, 5375 body: JSON.stringify({ query: '{' + parts.join(' ') + '}' }) 5376 }).then(function (r) { 5377 return r.ok ? r.json() : null; 5378 }).then(function (res) { 5379 var out = {}; 5380 var data = res && res.data; 5381 if (data) { 5382 Object.keys(aliasToHandle).forEach(function (a) { 5383 var p = data[a]; 5384 if (!p) return; 5385 var v = p.variants && p.variants.nodes && p.variants.nodes[0]; 5386 // Colour (option "Color") + size (option "Size") from the first 5387 // variant, so GA4 cards can fill item_category4 (colour) / 5388 // item_category5 (size). Size is the first variant's = the smallest 5389 // (matches the product id), per the GA4 QA. 5390 var so = (v && v.selectedOptions) || []; 5391 var color = '', size = ''; 5392 so.forEach(function (o) { 5393 var n = (o && o.name || '').toLowerCase(); 5394 if (n === 'color' || n === 'colour') color = o.value; 5395 else if (n === 'size') size = o.value; 5396 }); 5397 out[aliasToHandle[a]] = { 5398 variantId: (v && v.id) ? v.id.replace(/^gid:\/\/shopify\/ProductVariant\//, '') : '', 5399 quantityAvailable: (v && v.quantityAvailable != null) ? v.quantityAvailable : null, 5400 department: (p.dept && p.dept.value) || '', 5401 color: color, 5402 size: size 5403 }; 5404 }); 5405 } 5406 return out; 5407 }).catch(function () { return {}; }); 5408 } 5409 5410 /* ââ Canonical colour-family hydrator (shared: PDP swatch block + the 5411 quick-add / quick-view drawer) ââââââââââââââââââââââââââââââââââââââ 5412 Rebuilds the drift-free colour family for ONE [data-bp-colors] root via 5413 a bounded UNION crawl of every sibling's bp_stylecolorlist, then renders 5414 in canonical bp_style-ascending order. Because no single colour's own 5415 list is authoritative (each drifts), the union is identical on every 5416 colourway â so the swatch set + order never changes as the shopper 5417 switches colour. 5418 5419 Reads ALL its config from the root's own DOM + this module's AMPLIENCE 5420 base, so it works on any root: the PDP (where blocks/bp-color-siblings's 5421 inline script tag calls it) AND the drawer (where the morphed block's 5422 inline script tag NEVER executes â Horizon's morph only re-runs 5423 .shopify-app-block script[src], not theme-block inline scripts â so the
5424 drawer controller invokes this same shared function instead of forking 5425 the logic). See blocks/bp-color-siblings.liquid (PDP) and 5426 sections/bp-quick-drawer.liquid hydrateColorSiblings (drawer) for the two 5427 callers. Idempotent per root element. */ 5428 function hydrateRoot(root, opts) { 5429 opts = opts || {}; 5430 if (!root || root.__bpColorsHydrated) return; 5431 root.__bpColorsHydrated = true; 5432 var ul = root.querySelector('.bp-colors__swatches'); 5433 if (!ul) return; 5434 var labelName = root.querySelector('[data-bp-active-color]'); 5435 var activeItem = ul.querySelector('.bp-colors__item.is-active'); 5436 5437 var INV5 = root.getAttribute('data-bp-inv5-handle') || ''; 5438 var GROUP_TAG = root.getAttribute('data-bp-group-tag') || ''; 5439 var CURRENT_HANDLE = root.getAttribute('data-bp-current-handle') || ''; 5440 var CURRENT_COLOR = (activeItem && activeItem.getAttribute('data-bp-color-name')) 5441 || (labelName && (labelName.textContent || '').replace(/^\s+|\s+$/g, '')) || ''; 5442 var CURRENT_STYLE = (activeItem && activeItem.getAttribute('data-bp-color-style')) || ''; 5443 var QV = opts.qv || ''; 5444 5445 function handleize(s) { 5446 return String(s || '').toLowerCase().replace(/^\s+|\s+$/g, '') 5447 .replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, ''); 5448 } 5449 function composeHandle(name) { return INV5 + '-' + handleize(name); } 5450 function poiswatch(style) { 5451 return AMPLIENCE + '/i/bostonproper/' + style + '_2?$poiswatch$&img404=' + style + '_1'; 5452 } 5453 function styleFromImage(src) { 5454 if (!src) return ''; 5455 var file = src.split('/').pop().split('?')[0]; 5456 var m = file.match(/^([A-Za-z0-9]+)_/); 5457 return m ? m[1] : ''; 5458 } 5459 // Parse bp_golivedate robustly across formats so a backend/feed format 5460 // change can't break the go-live window. Handles the current US 5461 // M/D/YYYY, ISO (YYYY-MM-DD / full ISO datetime), and epoch (seconds or 5462 // milliseconds). `new Date()` alone mis-reads epoch-seconds (as ms) and 5463 // is locale-dependent on M/D/YYYY, so we normalize first. 5464 function parseGoLive(v) { 5465 if (v == null || v === '') return null; 5466 var s = String(v).trim(); 5467 if (/^\d+$/.test(s)) { 5468 var n = Number(s); 5469 if (!isFinite(n)) return null; 5470 return new Date(n < 1e12 ? n * 1000 : n); // <1e12 â seconds 5471 } 5472 var m = s.match(/^(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})$/); // M/D/YYYY 5473 if (m) return new Date(Number(m[3]), Number(m[1]) - 1, Number(m[2])); 5474 var d = new Date(s); // ISO (YYYY-MM-DD / full ISO) + anything else 5475 return isNaN(d.getTime()) ? null : d; 5476 } 5477 function withinGoLiveWindow(goLiveDate) { 5478 var d = parseGoLive(goLiveDate); 5479 if (!d || isNaN(d.getTime())) return false; 5480 var now = new Date(); 5481 if (d > now) return true; 5482 var days = Math.round((now.getTime() - d.getTime()) / 86400000); 5483 return days <= 45; 5484 } 5485 function paintDiscount(item, pct) { 5486 if (pct > 0 && !item.querySelector('[data-bp-color-discount]')) { 5487 var badge = document.createElement('span'); 5488 badge.className = 'bp-colors__discount'; 5489 badge.dataset.bpColorDiscount = ''; 5490 badge.setAttribute('aria-label', pct + '% off'); 5491 badge.textContent = '-' + pct + '%'; 5492 item.appendChild(badge); 5493 } 5494 } 5495 function wireName(item) { 5496 if (item.dataset.bpNameWired) return; 5497 item.dataset.bpNameWired = '1'; 5498 var show = function () { if (labelName && item.dataset.bpColorName) labelName.textContent = item.dataset.bpColorName; }; 5499 var reset = function () { if (labelName) labelName.textContent = CURRENT_COLOR; }; 5500 item.addEventListener('mouseenter', show); 5501 item.addEventListener('mouseleave', reset); 5502 item.addEventListener('focusin', show); 5503 item.addEventListener('focusout', reset); 5504 } 5505 function swatchOf(item) { return item.querySelector('[data-bp-swatch]'); } 5506 function paintCrop(item, style) { 5507 if (!style) return; 5508 var sw = swatchOf(item); 5509 if (sw && !sw.style.backgroundImage) sw.style.backgroundImage = "url('" + poiswatch(style) + "')"; 5510 item.dataset.bpColorStyle = style; 5511 } 5512 5513 var nameByHandle = {}; 5514 Array.prototype.forEach.call(ul.querySelectorAll('.bp-colors__item'), function (li) { 5515 var h = li.dataset.bpColorHandle; 5516 if (h && !(h in nameByHandle)) nameByHandle[h] = li.dataset.bpColorName || ''; 5517 }); 5518 if (CURRENT_HANDLE) nameByHandle[CURRENT_HANDLE] = CURRENT_COLOR; 5519 5520 var fetched = {}; // handle -> info | null (null = no product at that handle) 5521 5522 function unionFromFetched() {
5523 Object.keys(fetched).forEach(function (h) { 5524 var info = fetched[h]; 5525 if (info && info.colorList) { 5526 info.colorList.split(',').forEach(function (raw) { 5527 var name = raw.replace(/^\s+|\s+$/g, ''); 5528 if (!name) return; 5529 var sh = composeHandle(name); 5530 if (!(sh in nameByHandle)) nameByHandle[sh] = name; 5531 }); 5532 } 5533 }); 5534 } 5535 5536 /* PRIMARY family source: the group tag. Returns the REAL siblings with 5537 REAL handles + Colour-option names, so nameByHandle is the true family 5538 and every colour is reachable from every colourway â no composed-handle 5539 guessing. We pre-populate `fetched` from the same response (it carries 5540 style/available/goLive/discount/colorList) so render() needs no extra 5541 round-trip, and we DELIBERATELY skip the colorListâcomposeHandle union 5542 here: on bad-data families (2DO2220) that union would re-introduce the 5543 bogus composed handles this path exists to avoid. Resolves true on 5544 success, false when the group query yields nothing (caller falls back to 5545 the composed-handle crawl). */ 5546 function groupCrawl() { 5547 return fetchByGroup(GROUP_TAG).then(function (byHandle) { 5548 var handles = Object.keys(byHandle || {}); 5549 if (!handles.length) return false; 5550 handles.forEach(function (h) { 5551 fetched[h] = byHandle[h]; 5552 if (byHandle[h] && !(h in nameByHandle)) nameByHandle[h] = byHandle[h].color || ''; 5553 }); 5554 // Keep the current colourway's server-rendered label to avoid a flash; 5555 // only fill from the group colour when the seed had none. 5556 if (CURRENT_HANDLE) nameByHandle[CURRENT_HANDLE] = CURRENT_COLOR || nameByHandle[CURRENT_HANDLE] || ''; 5557 return true; 5558 }); 5559 } 5560 5561 function crawl() { 5562 var MAX_ROUNDS = 3; 5563 var round = 0; 5564 function nextBatch() { 5565 var toFetch = Object.keys(nameByHandle).filter(function (h) { return !(h in fetched); }); 5566 if (!toFetch.length || round >= MAX_ROUNDS) return Promise.resolve(); 5567 round++; 5568 return fetchSiblings(toFetch).then(function (byHandle) {
5569 toFetch.forEach(function (h) { fetched[h] = byHandle[h] || null; }); 5570 unionFromFetched(); 5571 return nextBatch(); 5572 }); 5573 } 5574 return nextBatch(); 5575 } 5576 5577 function makeItem(handle, name) { 5578 var li = document.createElement('li'); 5579 li.className = 'bp-colors__item bp-colors__item--pending'; 5580 li.setAttribute('data-bp-color-name', name || ''); 5581 li.setAttribute('data-bp-color-handle', handle); 5582 li.setAttribute('data-bp-color-style', ''); 5583 var a = document.createElement('a'); 5584 a.className = 'bp-colors__swatch'; 5585 a.href = '/products/' + handle + QV; 5586 a.setAttribute('data-bp-swatch', ''); 5587 a.setAttribute('aria-label', name || ''); 5588 li.appendChild(a); 5589 return li; 5590 } 5591 5592 // Reconcile the whole row to canonical order in ONE pass, then reveal. 5593 // Every item stays hidden (--pending) while the crawl runs, so moving 5594 // nodes into sorted position causes NO visible movement; a single reveal 5595 // at the end drops each swatch straight into its final place. Canonical 5596 // order = ascending bp_style code (the merchandised sequence), identical 5597 // on every colourway. 5598 function render() { 5599 var existing = {}; 5600 Array.prototype.forEach.call(ul.querySelectorAll('.bp-colors__item'), function (li) { 5601 if (li.dataset.bpColorHandle) existing[li.dataset.bpColorHandle] = li; 5602 }); 5603 var entries = Object.keys(nameByHandle).map(function (h) { 5604 var info = fetched[h]; 5605 var isCurrent = (h === CURRENT_HANDLE); 5606 var visible; 5607 if (isCurrent) visible = true; 5608 else if (!info) visible = false; 5609 else if (info.available) visible = true; 5610 else visible = withinGoLiveWindow(info.goLiveDate); 5611 var li = existing[h]; 5612 var style = (info && info.style) ? info.style 5613 : ((li && li.dataset.bpColorStyle) ? li.dataset.bpColorStyle : (isCurrent ? CURRENT_STYLE : '')); 5614 return { h: h, info: info, isCurrent: isCurrent, visible: visible, style: style || '', li: li }; 5615 }); 5616 entries.sort(function (a, b) { 5617 if (a.style !== b.style) return a.style < b.style ? -1 : 1; 5618 return a.h < b.h ? -1 : (a.h > b.h ? 1 : 0); 5619 }); 5620 entries.forEach(function (e) { 5621 if (e.visible && !e.li) { e.li = makeItem(e.h, nameByHandle[e.h]); existing[e.h] = e.li; } 5622 if (!e.li) return; 5623 if (e.visible) { 5624 paintCrop(e.li, e.style); 5625 if (e.info) paintDiscount(e.li, e.info.discount); 5626 if (!e.isCurrent) wireName(e.li); 5627 } else { 5628 e.li.classList.add('bp-colors__item--pending'); 5629 } 5630 ul.appendChild(e.li); 5631 }); 5632 entries.forEach(function (e) { 5633 if (e.visible && e.li) e.li.classList.remove('bp-colors__item--pending'); 5634 }); 5635 } 5636 5637 function paintActive() { 5638 var active = ul.querySelector('.bp-colors__item.is-active'); 5639 if (!active) return; 5640 var sw = swatchOf(active); 5641 if (!sw || sw.style.backgroundImage) return; 5642 var info = fetched[CURRENT_HANDLE]; 5643 var style = (info && info.style) ? info.style : CURRENT_STYLE; 5644 if (style) { sw.style.backgroundImage = "url('" + poiswatch(style) + "')"; active.dataset.bpColorStyle = style; } 5645 } 5646 function revealActive() { 5647 var active = ul.querySelector('.bp-colors__item.is-active'); 5648 if (active) active.classList.remove('bp-colors__item--pending'); 5649 paintActive(); 5650 } 5651 5652 // Fallback (Storefront token/API unavailable): reveal in-stock seed items 5653 // and paint their crop from /products/{handle}.js filenames. Can't build 5654 // the union without metafields, so it degrades to the seed list only. 5655 function legacyFallback() { 5656 Array.prototype.forEach.call(ul.querySelectorAll('.bp-colors__item:not(.is-active)'), function (item) { 5657 var handle = item.dataset.bpColorHandle; 5658 if (!handle) return; 5659 wireName(item); 5660 var sw = swatchOf(item); 5661 var style = item.dataset.bpColorStyle || ''; 5662 fetch('/products/' + handle + '.js', { credentials: 'same-origin' }) 5663 .then(function (r) { return r.ok ? r.json() : null; }) 5664 .then(function (data) { 5665 if (!data || data.available === false) { item.classList.add('bp-colors__item--pending'); return; } 5666 if (!style && data.featured_image) style = styleFromImage(data.featured_image); 5667 if (!style) { item.classList.add('bp-colors__item--pending'); return; } 5668 if (sw && !sw.style.backgroundImage) { sw.style.backgroundImage = "url('" + poiswatch(style) + "')"; item.dataset.bpColorStyle = style; } 5669 if (data.compare_at_price && data.price && data.compare_at_price > data.price) { 5670 paintDiscount(item, Math.round(((data.compare_at_price - data.price) / data.compare_at_price) * 100)); 5671 } 5672 item.classList.remove('bp-colors__item--pending'); 5673 }) 5674 .catch(function () { item.classList.add('bp-colors__item--pending'); }); 5675 }); 5676 } 5677 5678 if (TOKEN) { 5679 // Hide EVERY item (incl. the active swatch) up front so the single 5680 // ordered reveal after the crawl has zero visible reflow. 5681 Array.prototype.forEach.call(ul.querySelectorAll('.bp-colors__item'), function (li) { 5682 li.classList.add('bp-colors__item--pending'); 5683 }); 5684 // Prefer group-tag discovery (drift-proof). Fall back to the composed- 5685 // handle union crawl when there's no group tag or the group query is 5686 // empty/errors, then to the legacy per-sibling .js path. 5687 var primary; 5688 if (GROUP_TAG) { 5689 primary = groupCrawl() 5690 .then(function (ok) { return ok ? true : crawl(); }) 5691 .catch(function () { return crawl(); }); 5692 } else { 5693 primary = crawl(); 5694 } 5695 primary 5696 .then(function () { render(); }) 5697 .catch(function () { revealActive(); legacyFallback(); }); 5698 } else { 5699 legacyFallback(); 5700 paintActive(); 5701 } 5702 } 5703 5704 return { 5705 fetch: fetchSiblings, 5706 fetchByGroup: fetchByGroup, 5707 fetchInventory: fetchInventory, 5708 fetchTrackData: fetchTrackData, 5709 swatchUrl: swatchUrl, 5710 hydrateRoot: hydrateRoot, 5711 amplience: AMPLIENCE 5712 }; 5713 })(); 5714</script>
5714<script> 5715 window.bpColorSwatches = (function () { 5716 var TOKEN = "04534ca2c4aa793f02c0c735d5d6160c"; 5717 var API_VERSION = '2024-07'; 5718 var CACHE_KEY = 'bp_color_swatches_v1'; 5719 var map = {}; 5720 var ready = false; 5721 5722 function apiUrl() { 5723 var root = (window.Shopify && Shopify.routes && Shopify.routes.root) ? Shopify.routes.root : '/'; 5724 return root + 'api/' + API_VERSION + '/graphql.json'; 5725 } 5726 // MUST match bp-bloomreach.js handleize() so facet-value lookups line up: 5727 // lowercase, non-alphanumeric runs -> '-', trim leading/trailing dashes. 5728 function key(name) { 5729 return String(name == null ? '' : name) 5730 .toLowerCase().trim() 5731 .replace(/[^a-z0-9]+/g, '-') 5732 .replace(/^-+|-+$/g, ''); 5733 } 5734 function get(name) { return map[key(name)] || ''; } 5735 5736 // 1) hydrate synchronously from cache (removes the first-paint race on 5737 // every PLP view after the first in a session). 5738 try { 5739 var cached = sessionStorage.getItem(CACHE_KEY); 5740 if (cached) { map = JSON.parse(cached) || {}; ready = true; } 5741 } catch (_) {} 5742 5743 // 2) fetch fresh (paginated) and refresh the cache. 5744 function page(after) { 5745 var q = '{ metaobjects(type: "product_color_swatches", first: 250' + 5746 (after ? ', after: ' + JSON.stringify(after) : '') + 5747 ') { pageInfo { hasNextPage endCursor } edges { node { fields { key value } } } } }'; 5748 return fetch(apiUrl(), { 5749 method: 'POST', 5750 headers: { 5751 'Content-Type': 'application/json', 5752 'Accept': 'application/json', 5753 'X-Shopify-Storefront-Access-Token': TOKEN 5754 }, 5755 body: JSON.stringify({ query: q }) 5756 }).then(function (r) { 5757 if (!r.ok) throw new Error('storefront HTTP ' + r.status); 5758 return r.json(); 5759 }); 5760 } 5761 function load() { 5762 if (!TOKEN) return; 5763 var acc = {}; 5764 function walk(after) { 5765 return page(after).then(function (res) { 5766 var mo = res && res.data && res.data.metaobjects; 5767 if (!mo) return; 5768 (mo.edges || []).forEach(function (e) { 5769 var f = {}; 5770 (e.node.fields || []).forEach(function (x) { f[x.key] = x.value; }); 5771 // Prefer an optional `css_background` TEXT field (holds a full CSS 5772 // background â a hex OR a linear-gradient for a shimmer), falling 5773 // back to the existing `css_color` Color field (single hex only â 5774 // a Color metafield can't store a gradient). Applied via 5775 // `background:` so either renders. Add a single-line text field 5776 // named `css_background` to the metaobject to enable gradients. 5777 var val = f.css_background || f.css_color; 5778 if (f.name && val) acc[key(f.name)] = val; 5779 }); 5780 if (mo.pageInfo && mo.pageInfo.hasNextPage) return walk(mo.pageInfo.endCursor); 5781 }); 5782 } 5783 walk(null).then(function () { 5784 if (!Object.keys(acc).length) return; // empty response â keep cache/fallback 5785 map = acc; 5786 ready = true; 5787 try { sessionStorage.setItem(CACHE_KEY, JSON.stringify(acc)); } catch (_) {} 5788 try { window.dispatchEvent(new CustomEvent('bp:color-swatches-ready')); } catch (_) {} 5789 }).catch(function () { /* keep cache; fall back to raw CSS colour names */ }); 5790 } 5791 load(); 5792 5793 return { get: get, key: key, isReady: function () { return ready; } }; 5794 })(); 5795</script>
vendor: 1 bytes, line 5795
5795
5796<script type="application/ld+json"> 5797{ 5798 "@context": "https://schema.org", 5799 "@graph": [ 5800 { 5801 "@type": "Organization", 5802 "@id": "https:\/\/www.bostonproper.com\/#organization", 5803 "name": "Boston Proper", 5804 "url": "https:\/\/www.bostonproper.com\/", 5805 "logo": "https:\/\/www.bostonproper.com\/cdn\/shop\/files\/BOS-Logotype-Charcoal_1.png?v=1785187523\u0026width=500", 5806 "description": "Shop women's dresses, statement tops, polished pants, shoes, accessories, and travel-ready styles designed to fit beautifully and own every room. ", 5807 "parentOrganization": { 5808 "@type": "Organization", 5809 "name": "Brentwood Associates" 5810 }, 5811 "founder": { "@type": "Person", "name": "Sheryl Clark" }, 5812 "foundingDate": "1992", 5813 "sameAs": [ 5814 "https:\/\/www.facebook.com\/bostonproper", 5815 "https:\/\/www.instagram.com\/bostonproperofficial\/", 5816 "https:\/\/www.pinterest.com\/bostonproper\/", 5817 "https:\/\/www.youtube.com\/@bostonproper", 5818 "https:\/\/x.com\/bostonproper", 5819 "https:\/\/www.tiktok.com\/@bostonproperofficial", 5820 "https:\/\/www.bostonproper.com\/pages\/about-us" 5821 ], 5822 "contactPoint": [ 5823 { 5824 "@type": "ContactPoint", 5825 "telephone": "+1-800-243-4300", 5826 "contactType": "customer service", 5827 "contactOption": "TollFree", 5828 "areaServed": "US", 5829 "availableLanguage": "en" 5830 } 5831 ], 5832 "hasMerchantReturnPolicy": { 5833 "@type": "MerchantReturnPolicy", 5834 "applicableCountry": "US", 5835 "returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow", 5836 "merchantReturnDays": 30, 5837 "returnMethod": "https://schema.org/ReturnByMail", 5838 "returnFees": "https://schema.org/ReturnShippingFees", 5839 "returnShippingFeesAmount": { 5840 "@type": "MonetaryAmount", 5841 "value": "6.95", 5842 "currency": "USD" 5843 } 5844 } 5845 }, 5846 { 5847 "@type": "WebSite", 5848 "@id": "https:\/\/www.bostonproper.com\/#website", 5849 "url": "https:\/\/www.bostonproper.com\/", 5850 "name": "Boston Proper", 5851 "publisher": { "@id": "https:\/\/www.bostonproper.com\/#organization" }, 5852 "inLanguage": "en-US", 5853 "potentialAction": { 5854 "@type": "SearchAction", 5855 "target": { 5856 "@type": "EntryPoint", 5857 "urlTemplate": "https://www.bostonproper.com/search?q={search_term_string}" 5858 }, 5859 "query-input": "required name=search_term_string" 5860 } 5861 } 5862 ] 5863} 5864</script>
vendor: 1 bytes, line 5864
5864
5865<script> 5866 (function () { 5867 // ----- Customer + order state (Liquid-emitted, no extra fetch) ----- 5868 window.__customer_id__ = ""; 5869 window.__customer_type__ = "new"; 5870 window.__orders_count__ = 0; 5871 5872 // ----- Plain-text PII (Enhanced Conversions / vendor pixels) ----- 5873 // Nested-object shape + key names match Atlas's ga4_globals.js.liquid 5874 // (email / phone_number / first_name / last_name / street / city / 5875 // state / zip_code / country) so the GTM-NS3X79G container variables 5876 // resolve. 5877 // Absent fields are emitted as `undefined` (not ''), matching Atlas's 5878 // ga4_globals.js.liquid and __user_hashed_data__ below: a field that 5879 // does not exist should read undefined, never an empty string. 5880 window.__enhanced_conversion_data__ = { 5881 email: undefined, 5882 phone_number: undefined, 5883 first_name: undefined, 5884 last_name: undefined, 5885 street: undefined, 5886 city: undefined, 5887 state: undefined, 5888 zip_code: undefined, 5889 country: undefined 5890 }; 5891 5892 // ----- SHA-256 hashed PII for GA4 Enhanced Conversions ----- 5893 // Hashed SERVER-SIDE via Liquid `| sha256` (exactly like Atlas), so 5894 // it's available SYNCHRONOUSLY at the first event push. The previous 5895 // client-side SubtleCrypto version resolved async, so early events 5896 // (view_item / page_loaded) shipped empty hashes. undefined when 5897 // absent (Atlas parity â never ''). 5898 window.__user_hashed_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 // ----- user_details (spec: localStorage gtm_user_data backup) ----- 5911 // The GA4/GTM analytics team's spec: every event's user_details is 5912 // built from the logged-in customer (Liquid globals above) with the 5913 // checkout-captured localStorage `gtm_user_data` key as a BACKUP for 5914 // guests. Plain text â enhanced_conversion_data; SHA-256(plain) â 5915 // user_hashed_data (hashed client-side here, since the localStorage 5916 // backup has no server-side hashes). Built ONCE and cached in 5917 // window.__bp_user_details__ so per-event pushes stay synchronous; 5918 // bpUserDetailsSync() is the interim shape used before the async 5919 // hashing settles (page_loaded fires at DOMContentLoaded). 5920 // 5921 // Shape follows the spec exactly: user_id is the (future) Peak id, 5922 // null until that integration lands; the Shopify customer id now 5923 // lives on customer_id. NOTE: the GTM-NS3X79G container must be 5924 // remapped to read customer_id for GA4 User-ID (it previously read 5925 // user_id). 5926 function bpGtmUserData() { 5927 try { return JSON.parse(localStorage.getItem('gtm_user_data')) || null; } 5928 catch (_) { return null; } 5929 } 5930 5931 // First non-empty of the args (null/undefined/'' are "empty"). 5932 function bpCoalesce() { 5933 for (var i = 0; i < arguments.length; i++) { 5934 var v = arguments[i]; 5935 if (v != null && v !== '') return v; 5936 } 5937 return null; 5938 } 5939 5940 function bpUserDetailsSync() { 5941 var ls = bpGtmUserData() || {}; 5942 var ecd = window.__enhanced_conversion_data__ || {}; 5943 // gtm_user_data field names â enhanced_conversion_data key names. 5944 var lsm = { 5945 email: ls.em, phone_number: ls.ph, first_name: ls.fn, 5946 last_name: ls.ln, street: ls.street, city: ls.ct, 5947 state: ls.st, zip_code: ls.zp, country: ls.country 5948 }; 5949 var loggedIn = !!(window.__customer_id__ && String(window.__customer_id__) !== ''); 5950 // Logged-in â Liquid customer is authoritative, localStorage backfills. 5951 // Guest â localStorage (checkout capture) is authoritative. 5952 var primary = loggedIn ? ecd : lsm; 5953 var backup = loggedIn ? lsm : ecd; 5954 function P(k) { return bpCoalesce(primary[k], backup[k]); } 5955 5956 var ordersCount = loggedIn 5957 ? bpCoalesce(window.__orders_count__, ls.ordersCount) 5958 : bpCoalesce(ls.ordersCount, window.__orders_count__); 5959 if (ordersCount != null) ordersCount = Number(ordersCount); 5960 var customerId = bpCoalesce(window.__customer_id__, ls.userId); 5961 5962 return { 5963 log_state: customerId ? 'Logged In' : 'Logged Out', 5964 user_id: null, // Peak/Shopify user id â wired later 5965 customer_id: customerId, 5966 customer_type: (ordersCount != null && ordersCount >= 1) ? 'returning' : 'new', 5967 orders_count: ordersCount, 5968 is_first_order: ordersCount != null ? (ordersCount < 1) : null, 5969 enhanced_conversion_data: { 5970 email: P('email'), 5971 phone_number: P('phone_number'), 5972 first_name: P('first_name'), 5973 last_name: P('last_name'), 5974 street: P('street'), 5975 city: P('city'), 5976 state: P('state'), 5977 zip_code: P('zip_code'), 5978 country: P('country') 5979 }, 5980 // Interim: Liquid server-side hashes (logged-in) until the async 5981 // client-side hash of the merged plain text overwrites this. 5982 user_hashed_data: window.__user_hashed_data__ || {} 5983 }; 5984 } 5985 5986 // SHA-256 â lowercase hex (spec: trim + lowercase normalization). 5987 function bpSha256(value) { 5988 if (value == null || value === '') return Promise.resolve(null);
5989 try { 5990 var norm = String(value).trim().toLowerCase(); 5991 var data = new TextEncoder().encode(norm); 5992 return crypto.subtle.digest('SHA-256', data).then(function (buf) { 5993 var arr = Array.prototype.slice.call(new Uint8Array(buf)); 5994 return arr.map(function (b) { return ('0' + b.toString(16)).slice(-2); }).join(''); 5995 }); 5996 } catch (_) { return Promise.resolve(null); } 5997 } 5998 5999 function bpBuildUserDetails() { 6000 var ud = bpUserDetailsSync(); 6001 var e = ud.enhanced_conversion_data; 6002 var keys = ['email','phone_number','first_name','last_name','street','city','state','zip_code','country']; 6003 return Promise.all(keys.map(function (k) { return bpSha256(e[k]); })) 6004 .then(function (hashes) { 6005 var hashed = {}; 6006 keys.forEach(function (k, i) { hashed[k] = hashes[i]; }); 6007 ud.user_hashed_data = hashed; 6008 return ud; 6009 }); 6010 } 6011 6012 window.bpUserDetailsSync = bpUserDetailsSync; 6013 window.__bp_user_details__ = null; // populated async, read synchronously by events 6014 try { 6015 if (window.crypto && window.crypto.subtle && window.TextEncoder) { 6016 bpBuildUserDetails().then(function (ud) { window.__bp_user_details__ = ud; }); 6017 } 6018 } catch (_) { /* insecure context / no subtle â sync fallback covers it */ } 6019 6020 // ----- First-touch attribution (session-scoped) ----- 6021 // Persists the FIRST page of the user's session so every later 6022 // event can attribute back to landing context. Mirrors Atlas's 6023 // sessionStorage usage in ga4.js.liquid. 6024 try { 6025 var STORAGE_KEY = 'bp_first_touch'; 6026 var stored = sessionStorage.getItem(STORAGE_KEY); 6027 if (stored) { 6028 window.__first_touch__ = JSON.parse(stored); 6029 } else { 6030 window.__first_touch__ = { 6031 page: window.location.pathname, 6032 full_url: window.location.href, 6033 template: "blog", 6034 referrer: document.referrer || '', 6035 timestamp: Date.now() 6036 }; 6037 sessionStorage.setItem(STORAGE_KEY, JSON.stringify(window.__first_touch__)); 6038 } 6039 } catch (_) { 6040 window.__first_touch__ = { 6041 page: window.location.pathname, 6042 template: "blog" 6043 }; 6044 } 6045 6046 // ----- Global DataLayer config â debug flag + shared shape ----- 6047 window.__DL__ = window.__DL__ || { 6048 debug: false, 6049 cart: null, // populated by view_cart / cart change events 6050 lastEvent: null // last event name pushed (for dedupe / tests) 6051 }; 6052 6053 // ----- Ensure dataLayer exists even if GTM hasn't booted yet ----- 6054 window.dataLayer = window.dataLayer || []; 6055 })(); 6056</script>
vendor: 1 bytes, line 6056
6056
6057<script>window.__pageType__ = "blog";</script>
6057<script src="//www.bostonproper.com/cdn/shop/t/1516/assets/bp-track-gtm.js?v=183060181947548063931790192827" defer></script>
6057 6058
6058<script src="//www.bostonproper.com/cdn/shop/t/1516/assets/bp-track-page.js?v=89286407019962503341790192827" defer></script>
6058 6059
6059<script src="//www.bostonproper.com/cdn/shop/t/1516/assets/bp-track-cards.js?v=119320205335911998891790192827" defer></script>
6059<script src="//www.bostonproper.com/cdn/shop/t/1516/assets/bp-badges.js?v=45136502598786020341790192827" defer></script>
6059<script src="//www.bostonproper.com/cdn/shop/t/1516/assets/bp-card-hydrate.js?v=169242559010489351881790192827" defer></script>
6059<script src="//www.bostonproper.com/cdn/shop/t/1516/assets/bp-line-item-props.js?v=113126442776160060221790192827" defer></script>
6059<script> 6060 (function () { 6061 'use strict'; 6062 if (window.__bpTrackCartWired) return; 6063 window.__bpTrackCartWired = true; 6064 6065 var lastCartSnapshot = null; // for remove diff detection 6066 6067 function snapshotCart(cart) { 6068 if (!cart || !cart.items) return null; 6069 var map = {}; 6070 cart.items.forEach(function (line) { 6071 map[String(line.id || line.key)] = { 6072 key: line.key, 6073 id: line.id, 6074 variant_id: line.variant_id || line.id, // â item_shopify_variant 6075 product_id: line.product_id, 6076 product_title: line.product_title || line.title, 6077 vendor: line.vendor, 6078 product_type: line.product_type, 6079 sku: line.sku, 6080 price: line.price, 6081 quantity: line.quantity, 6082 handle: line.handle, 6083 url: line.url, 6084 featured_image: line.featured_image, 6085 image: line.image, 6086 options_with_values: line.options_with_values || [] 6087 }; 6088 }); 6089 return map; 6090 } 6091 6092 function detectRemovedLines(prev, next) { 6093 if (!prev) return []; 6094 var removed = []; 6095 Object.keys(prev).forEach(function (k) { 6096 if (!next || !next[k]) { 6097 removed.push(prev[k]); 6098 } else if (next[k].quantity < prev[k].quantity) { 6099 var line = Object.assign({}, prev[k]); 6100 line.quantity = prev[k].quantity - next[k].quantity; 6101 removed.push(line); 6102 } 6103 }); 6104 return removed; 6105 } 6106 6107 function detectAddedLines(prev, next) { 6108 if (!next) return []; 6109 var added = []; 6110 Object.keys(next).forEach(function (k) { 6111 if (!prev || !prev[k]) { 6112 added.push(next[k]); 6113 } else if (next[k].quantity > prev[k].quantity) { 6114 var line = Object.assign({}, next[k]); 6115 line.quantity = next[k].quantity - prev[k].quantity; 6116 added.push(line); 6117 } 6118 }); 6119 return added; 6120 } 6121 6122 // Where a cart mutation happened: the /cart page ("Cart") vs the 6123 // slide-out flyout drawer ("Cart Flyout"). Used for in-cart qty 6124 // changes + removals. 6125 function cartMutationLocation() { 6126 // The visible SURFACE wins over the path: if the flyout drawer is open, 6127 // a qty change / removal is "Cart Flyout" even on the /cart page (QA â 6128 // a flyout remove was reporting "Cart" because the path check beat the 6129 // actual surface). 6130 var dlg = document.querySelector('[data-bp-cart-dialog]'); 6131 if (dlg && dlg.open) return 'Cart Flyout'; 6132 var p = window.location.pathname; 6133 if (p === '/cart' || p.indexOf('/cart?') === 0) return 'Cart'; 6134 return 'Cart Flyout'; 6135 } 6136 6137 // Where an INITIAL add-to-cart happened. When a Quickview drawer is the 6138 // source, attribute to the SAME surface the view_item used: "Quickview" 6139 // for the PLP quickview, "Cart Quickview" for the cart flyout / cart-page 6140 // upsell (complete-the-look) modal. window.__bpQuickviewLoc is set on open 6141 // by bp-track-cards.js (fireQuickview / bpTrackCartQuickview); reading it 6142 // here â instead of hardcoding "Quickview" â makes the add_to_cart 6143 // event_location/item_list_id/location_id match the view_item, so GA4 can 6144 // compute an Add-to-Cart Rate for Cart Quickview and tell it apart from the 6145 // PLP Quickview (GA4 QA). Falls back to "Quickview" if the surface is 6146 // somehow unset. Otherwise let add_to_cart resolve from the path (PDP). 6147 function initialAddLocation() { 6148 return window.__bpQuickviewActive ? (window.__bpQuickviewLoc || 'Quickview') : undefined; 6149 } 6150 6151 // Normalize a cart-line snapshot into the (variant, product) tuple 6152 // bpTrack.add_to_cart expects, then fire it with the given location. 6153 function fireAddLine(line, location) { 6154 if (!window.bpTrack || !window.bpTrack.add_to_cart) return; 6155 var product = { 6156 id: line.product_id, 6157 title: line.product_title, 6158 vendor: line.vendor, 6159 product_type: line.product_type, 6160 handle: line.handle, 6161 url: line.url, 6162 // cart.js gives featured_image as an object; fall back to the
6163 // legacy line.image string. Feeds the Klaviyo Added to Cart 6164 // ImageURL / URL / Categories (GA4 items[] don't read these). 6165 featured_image: (line.featured_image && line.featured_image.url) || line.image || '' 6166 }; 6167 var variant = { 6168 id: line.variant_id || line.id, // â item_shopify_variant 6169 sku: line.sku, 6170 price: line.price, 6171 compare_at_price: null, 6172 // A line in the cart is purchasable â "In Stock". Without this, 6173 // _itemFromProduct defaults undefined-available to "Out of Stock". 6174 available: true, 6175 option1: line.options_with_values && line.options_with_values[0] && line.options_with_values[0].value, 6176 option2: line.options_with_values && line.options_with_values[1] && line.options_with_values[1].value, 6177 product_id: line.product_id 6178 }; 6179 window.bpTrack.add_to_cart(variant, product, true, location, line.product_id); 6180 } 6181 6182 // Initial add-to-cart (product:added / cart:update) â diff for ADDED 6183 // lines only and fire add_to_cart with the source-surface location. 6184 function fireAddedToCart(cart, location) { 6185 var next = snapshotCart(cart); 6186 if (lastCartSnapshot) { 6187 detectAddedLines(lastCartSnapshot, next).forEach(function (line) { 6188 fireAddLine(line, location); 6189 }); 6190 } 6191 lastCartSnapshot = next; 6192 } 6193 6194 // In-cart mutation (cart:updated from the qty stepper / remove) â diff 6195 // BOTH directions against the SAME prior snapshot so a qty increase 6196 // fires add_to_cart ("Cart Flyout"/"Cart") and a decrease/remove fires 6197 // remove_from_cart. Computed before the snapshot is replaced so the two 6198 // diffs don't race each other. 6199 function fireCartMutation(cart) { 6200 var next = snapshotCart(cart); 6201 var loc = cartMutationLocation(); 6202 if (lastCartSnapshot) { 6203 detectRemovedLines(lastCartSnapshot, next).forEach(function (line) { 6204 if (window.bpTrack && window.bpTrack.remove_from_cart) { 6205 window.bpTrack.remove_from_cart(line, loc); 6206 } 6207 }); 6208 detectAddedLines(lastCartSnapshot, next).forEach(function (line) { 6209 fireAddLine(line, loc); 6210 }); 6211 } 6212 lastCartSnapshot = next; 6213 } 6214 6215 function fireViewCart(location) { 6216 if (window.bpTrack && window.bpTrack.view_cart) { 6217 window.bpTrack.view_cart(location); 6218 } 6219 } 6220 6221 document.addEventListener('DOMContentLoaded', function () { 6222 // Seed snapshot from the initial /cart.js (so the first remove 6223 // detected by the diff has a baseline to compare against). 6224 fetch('/cart.js', { credentials: 'same-origin' }) 6225 .then(function (r) { return r.json(); }) 6226 .then(function (cart) { lastCartSnapshot = snapshotCart(cart); }) 6227 .catch(function () { /* silent */ }); 6228 6229 // bp:cart-drawer:opened â view_cart from the flyout ("Cart Flyout"). 6230 // NOTE: do NOT clear __bpQuickviewActive here. A Quickview add opens the 6231 // cart drawer, so clearing on drawer-open wiped the "Quickview" 6232 // attribution before the add_to_cart (from product:added) could read it 6233 // â the QA "Quickview ATC reports Site Browse" bug. The quick-add modal's 6234 // own `close` event + the 30s safety timeout (bp-track-cards.js) clear it, 6235 // and later in-cart qty edits use cartMutationLocation(), not this flag. 6236 document.addEventListener('bp:cart-drawer:opened', function () { 6237 fireViewCart('Cart Flyout'); 6238 }); 6239 6240 // cart:updated comes from bpCartChange (the qty stepper / remove) â 6241 // diff BOTH directions: qty up â add_to_cart, qty down/remove â 6242 // remove_from_cart, both located "Cart"/"Cart Flyout". 6243 document.addEventListener('cart:updated', function (e) { 6244 if (e && e.detail && e.detail.cart) { 6245 fireCartMutation(e.detail.cart); 6246 } 6247 }); 6248 6249 // product:added (Horizon / bp-cart-drawer / bp-swym) + 6250 // cart:update (Horizon stock event) â fired on PDP, quick-add, 6251 // wishlistâcart, and any other ATC path. Diff the cart against 6252 // the last snapshot to detect ADDED lines and fire add_to_cart 6253 // for each one. Universal coverage; per-source helpers can fire 6254 // add_to_cart ahead of this if they have richer attribution 6255 // (the GA4 events will deduplicate on event_id at the GTM side 6256 // if that ever becomes an issue). 6257 document.addEventListener('product:added', function (e) { 6258 var loc = initialAddLocation(); 6259 if (e && e.detail && e.detail.cart) { 6260 fireAddedToCart(e.detail.cart, loc); 6261 } else { 6262 fetch('/cart.js', { credentials: 'same-origin' }) 6263 .then(function (r) { return r.json(); }) 6264 .then(function (cart) { fireAddedToCart(cart, loc); }) 6265 .catch(function () {}); 6266 } 6267 }); 6268 document.addEventListener('cart:update', function () { 6269 var loc = initialAddLocation(); 6270 fetch('/cart.js', { credentials: 'same-origin' }) 6271 .then(function (r) { return r.json(); }) 6272 .then(function (cart) { fireAddedToCart(cart, loc); }) 6273 .catch(function () {}); 6274 }); 6275 6276 // On the /cart page load, fire view_cart immediately too ("Cart"). 6277 if (window.location.pathname === '/cart' || window.location.pathname.indexOf('/cart?') === 0) { 6278 fireViewCart('Cart'); 6279 } 6280 }); 6281 })(); 6282</script>
vendor: 1 bytes, line 6282
6282
6283<script> 6284 (function () { 6285 var suppressUntil = 0; // colour-swap synthetic re-select window (ms epoch) 6286 6287 // Resolve the option's display name for a picker control. 6288 function sizeOptionName(el) { 6289 var fs = el.closest ? el.closest('fieldset') : null; 6290 if (fs) { 6291 var pfx = fs.querySelector('.variant-option__swatch-prefix') || fs.querySelector('legend'); 6292 if (pfx) return (pfx.textContent || '').trim(); 6293 } 6294 var nm = el.getAttribute ? el.getAttribute('name') : ''; 6295 var m = nm && nm.match(/options\[(.+?)\]/); 6296 if (m) return m[1]; 6297 if (el.id) { 6298 var lbl = document.querySelector('label[for="' + el.id + '"]'); 6299 if (lbl) return (lbl.textContent || '').trim(); 6300 } 6301 return ''; 6302 } 6303 6304 document.addEventListener('change', function (e) { 6305 var el = e.target; 6306 if (!el || !el.closest) return; 6307 var picker = el.closest('variant-picker'); 6308 if (!picker) return; // only variant pickers 6309 if (el.tagName !== 'SELECT' && el.type !== 'radio') return; 6310 if (el.type === 'radio' && !el.checked) return; 6311 if (!/size/i.test(sizeOptionName(el))) return; // SIZE option only 6312 var val = el.value; 6313 if (!val) return; 6314 // Colour-swap synthetic re-select â baseline it, don't report it. 6315 if (Date.now() < suppressUntil) { picker.__bpSize = val; return; } 6316 if (val === picker.__bpSize) return; // per-picker dedup / no-op 6317 picker.__bpSize = val; 6318 if (window.bpTrack && window.bpTrack.size_change) { 6319 window.bpTrack.size_change(val); // location auto (page type) 6320 } 6321 }, true); 6322 6323 // A colour swap re-selects the shopper's size on the swapped-in product via 6324 // SYNTHETIC change events â suppress briefly so it isn't a "size change". 6325 document.addEventListener('bp:pdp:swapped', function () { 6326 suppressUntil = Date.now() + 500; 6327 }); 6328 })(); 6329</script>
vendor: 1 bytes, line 6329
6329
6330<script> 6331 (function () { 6332 'use strict'; 6333 if (window.__bpTrackWishlistWired) return; 6334 window.__bpTrackWishlistWired = true; 6335 6336 function fire(eventName, line) { 6337 if (!window.bpTrack || !window.bpTrack[eventName] || !line) return; 6338 6339 // `line` is the `cartItemData` object dispatched by every save path 6340 // (bp-swym-helpers handleSaveForLater + the two PDP heart blocks). Its 6341 // field names are NOT the cart-line names the old code read 6342 // (product_id / sku / price / compare_at_price / options_with_values â 6343 // none of which exist here, which is why item_id / value / color / size / 6344 // stock / both Shopify ids all came back empty). The real shape is: 6345 // id â Shopify PARENT (product) id 6346 // variant_id â Shopify VARIANT id 6347 // variant_sku â full SKU (drives item_id inv7 / item_variant / item_parent_id inv5) 6348 // variant_price â selling price (cents; _itemFromProduct /100s it) 6349 // variant_compare_at_price â original / compare-at price 6350 // variant_title â "Color / Size" (option1 / option2) 6351 var price = parseFloat(line.variant_price); 6352 var compare = parseFloat(line.variant_compare_at_price); 6353 // variant_title is "<Color> / <Size>" (BP option1 / option2) â split so 6354 // item_category4 (Color) + item_category5 (Size) populate. 6355 var opts = String(line.variant_title || '').split(' / '); 6356 var color = (opts[0] || '').trim(); 6357 var size = (opts[1] || '').trim(); 6358 6359 var product = { 6360 id: line.id, // â item_shopify_id (parent product id) 6361 title: line.title, 6362 handle: line.handle, 6363 url: line.handle ? '/products/' + line.handle : '', 6364 metafields: { BP_ProductAttributes: { bp_department: '' } }, 6365 selected_variant: { 6366 id: line.variant_id, // â item_shopify_variant (variant id) 6367 sku: line.variant_sku || '', // â item_id (inv7) / item_variant / item_parent_id (inv5) 6368 price: isNaN(price) ? 0 : price, // â price + event_details.value (selling price) 6369 compare_at_price: isNaN(compare) ? null : compare, // â item_original_price when > selling price 6370 option1: color || null, // â item_category4 (Color) 6371 option2: size || null, // â item_category5 (Size) 6372 // A saved variant is a real, purchasable variant â "In Stock" (same 6373 // as cart-sourced events); _pushWithInventory fills item_stock_qty 6374 // from the live Storefront lookup. 6375 available: true, 6376 product_id: line.id 6377 } 6378 }; 6379 // eventLocation omitted on purpose â the helper resolves the Page Type 6380 // from the path (Product Detail / Site Browse / Homepage / Cart / â¦), 6381 // the same event_location scheme every other BP event uses. 6382 window.bpTrack[eventName](product); 6383 } 6384 6385 document.addEventListener('wishlist:item-saved', function (e) { 6386 var line = e && e.detail && e.detail.item; 6387 fire('add_to_wishlist', line); 6388 }); 6389 6390 document.addEventListener('wishlist:item-removed', function (e) { 6391 var line = e && e.detail && e.detail.item; 6392 fire('remove_from_wishlist', line); 6393 }); 6394 })(); 6395</script>
vendor: 1 bytes, line 6395
6395
6396<script> 6397 (function () { 6398 'use strict'; 6399 if (window.__bpTrackAccountWired) return; 6400 window.__bpTrackAccountWired = true; 6401 6402 function isLoginForm(form) { 6403 var action = form.getAttribute('action') || ''; 6404 var inner = form.querySelector('input[name="customer[email]"]'); 6405 var pwd = form.querySelector('input[name="customer[password]"]'); 6406 return /\/account\/login/.test(action) && inner && pwd; 6407 } 6408 6409 function isRegisterForm(form) { 6410 var action = form.getAttribute('action') || ''; 6411 var first = form.querySelector('input[name="customer[first_name]"]'); 6412 var email = form.querySelector('input[name="customer[email]"]'); 6413 var pwd = form.querySelector('input[name="customer[password]"]'); 6414 return /\/account/.test(action) && !!first && !!email && !!pwd; 6415 } 6416 6417 function isNewsletterForm(form) { 6418 var action = form.getAttribute('action') || ''; 6419 var typeAttr = form.getAttribute('id') || ''; 6420 var contact = form.querySelector('input[name="form_type"][value="customer"], input[name="contact[tags]"]'); 6421 return /\/contact/.test(action) && !!contact; 6422 } 6423 6424 document.addEventListener('submit', function (e) { 6425 var form = e.target; 6426 if (!(form instanceof HTMLFormElement)) return; 6427 6428 try { 6429 if (isLoginForm(form)) { 6430 // Atlas's flag pattern â bp-track-page.js reads + fires 6431 // bpTrack.login() on the next pageview. 6432 localStorage.setItem('login_GA4', 'true'); 6433 } 6434 if (isRegisterForm(form)) { 6435 // Fire sign_up immediately â Shopify-customer flow 6436 // typically posts and stays on the same response page 6437 // when registration succeeds (no GET redirect). 6438 if (window.bpTrack && window.bpTrack.sign_up) { 6439 window.bpTrack.sign_up('email'); 6440 } 6441 } 6442 if (isNewsletterForm(form)) { 6443 // Legacy Atlas-shape event (no GA4 standard counterpart) 6444 // for marketing's existing GTM tags. 6445 window.dataLayer = window.dataLayer || []; 6446 window.dataLayer.push({ event: 'Newsletter Subscription' }); 6447 // Also fire GA4 sign_up with method='newsletter' for the 6448 // standard ecommerce stream. 6449 if (window.bpTrack && window.bpTrack.sign_up) { 6450 window.bpTrack.sign_up('newsletter'); 6451 } 6452 } 6453 } catch (_) { /* analytics never blocks form submit */ } 6454 }, true); 6455 })(); 6456</script>
vendor: 1 bytes, line 6456
6456
6457<script> 6458 (function () { 6459 'use strict'; 6460 6461 const LOCAL_STORAGE_KEY = 'save-for-later-items'; 6462 const AMPLIENCE_BASE = 6463 (window.shop && window.shop.themeSettings && window.shop.themeSettings.amplience_cdn_base_url) || 6464 "https:\/\/media.bostonproper.com"; 6465 6466 // ---------- Customer / wishlist id ---------- 6467 function getCustomerId() { 6468 try { 6469 return (window.ShopifyAnalytics && 6470 window.ShopifyAnalytics.meta && 6471 window.ShopifyAnalytics.meta.page && 6472 window.ShopifyAnalytics.meta.page.customerId) || 'guest'; 6473 } catch (_) { 6474 return 'guest'; 6475 } 6476 } 6477 6478 // ---------- Storage layer: in-memory cache + localStorage mirror ---------- 6479 // 6480 // The wishlist needs to keep working even when localStorage is full 6481 // (third-party apps on this domain â Klaviyo, Yotpo cache, 6482 // BlackCrow, GTM dataLayer â routinely fill the 5MB per-origin 6483 // budget). The in-memory cache becomes the source of truth for the 6484 // session; localStorage is a write-through mirror so the state 6485 // survives a reload when it can fit. 6486 // 6487 // The Swym server-side wishlist is the cross-session source of 6488 // truth â checkWishlistSync() pulls from there on `wishlistloaded` 6489 // and seeds both layers, so an in-memory-only session is recovered 6490 // on the next visit. 6491 6492 let memoryState = null; // { [customerId]: { items, count } } 6493 let lsAvailable = true; // false after a quota failure this session 6494 const MAX_ITEMS_PER_CUSTOMER = 50; 6495 6496 function readLocalStorageRaw() { 6497 try { 6498 const raw = window.localStorage.getItem(LOCAL_STORAGE_KEY); 6499 return raw ? JSON.parse(raw) : null; 6500 } catch (_) { return null; } 6501 } 6502 6503 function isQuotaError(err) { 6504 if (!err) return false; 6505 return err.name === 'QuotaExceededError' || 6506 err.code === 22 || 6507 err.code === 1014 || 6508 /quota/i.test(String(err.message || err)); 6509 } 6510 6511 function tryWrite(data) { 6512 try { 6513 window.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(data)); 6514 return null; 6515 } catch (e) { return e; } 6516 } 6517 6518 // Diagnostic â when localStorage is full, name the offender so we 6519 // can target a fix in a follow-up (clear the right vendor cache, 6520 // ask the app to roll over, etc.). Logged once per session. 6521 let quotaDiagLogged = false; 6522 function logQuotaDiagnostics() { 6523 if (quotaDiagLogged) return; 6524 quotaDiagLogged = true; 6525 try { 6526 const sizes = []; 6527 for (let i = 0; i < window.localStorage.length; i++) { 6528 const k = window.localStorage.key(i); 6529 const v = window.localStorage.getItem(k) || ''; 6530 sizes.push({ key: k, kb: Math.round((k.length + v.length) / 1024) }); 6531 } 6532 sizes.sort((a, b) => b.kb - a.kb); 6533 const top = sizes.slice(0, 5).map((s) => `${s.key} (${s.kb}KB)`).join(', '); 6534 console.warn('[bp-swym] localStorage full. Top 5 keys: ' + top); 6535 } catch (_) {} 6536 } 6537 6538 function getSavedItemsLocalStorage() { 6539 // Memory wins when present (set by any successful seed / write). 6540 if (memoryState) return JSON.parse(JSON.stringify(memoryState)); 6541 const fromLs = readLocalStorageRaw(); 6542 if (fromLs) memoryState = JSON.parse(JSON.stringify(fromLs)); 6543 return fromLs; 6544 } 6545 6546 // Cascade of size-reduction strategies. Each step mutates `data` 6547 // in-place and returns the most recent write error (or null on success). 6548 // 1. Try as-is. 6549 // 2. Drop `image` from every saved item (largest field â a CDN 6550 // URL adds 100-300 bytes per row; the saved drawer can 6551 // re-derive the image from the product handle on demand). 6552 // 3. Cap each customer's items at MAX_ITEMS_PER_CUSTOMER, oldest 6553 // first. 6554 // 4. Drop the orphan "guest" bucket when a logged-in customerId 6555 // bucket also exists (after-login carryover). 6556 function storeSavedItemsLocalStorage(data) { 6557 if (!data) return; 6558 6559 // Memory state ALWAYS updates â that's the in-session source of 6560 // truth so the drawer, bubble, and PDP heart always reflect the 6561 // latest save, even when localStorage rejects the write. 6562 memoryState = JSON.parse(JSON.stringify(data)); 6563 6564 let err = null; 6565 if (lsAvailable) {
6566 err = tryWrite(data); 6567 6568 if (err && isQuotaError(err)) { 6569 // Strategy 2 â strip images. 6570 Object.keys(data).forEach((cid) => { 6571 const items = (data[cid] && data[cid].items) || []; 6572 items.forEach((it) => { delete it.image; }); 6573 }); 6574 err = tryWrite(data); 6575 } 6576 6577 if (err && isQuotaError(err)) { 6578 // Strategy 3 â cap item count. 6579 Object.keys(data).forEach((cid) => { 6580 const bucket = data[cid] || {}; 6581 const items = bucket.items || []; 6582 if (items.length > MAX_ITEMS_PER_CUSTOMER) { 6583 bucket.items = items.slice(items.length - MAX_ITEMS_PER_CUSTOMER); 6584 bucket.count = bucket.items.length; 6585 data[cid] = bucket; 6586 } 6587 }); 6588 err = tryWrite(data); 6589 } 6590 6591 if (err && isQuotaError(err)) { 6592 // Strategy 4 â drop the orphan "guest" bucket if a real 6593 // customerId bucket exists. 6594 const keys = Object.keys(data); 6595 if (keys.length > 1 && data.guest) { 6596 delete data.guest; 6597 err = tryWrite(data); 6598 } 6599 } 6600 } 6601 6602 if (err) { 6603 if (isQuotaError(err)) { 6604 lsAvailable = false; 6605 logQuotaDiagnostics(); 6606 } else { 6607 console.warn('[bp-swym] storage write failed', err); 6608 } 6609 // Fall through â fire the change events anyway so UI updates 6610 // from the memory state. 6611 } 6612 6613 // ALWAYS dispatch â memory has the new state. Without this, 6614 // saving an item when localStorage is full leaves the drawer + 6615 // bubble stale (the user thinks the click didn't register). 6616 document.dispatchEvent(new CustomEvent('wishlist:updated', { detail: { wishlist: memoryState } })); 6617 document.dispatchEvent(new CustomEvent('bp:saved:updated')); 6618 } 6619 function getLocalWishlist() { 6620 const all = getSavedItemsLocalStorage(); 6621 const customerId = getCustomerId(); 6622 return (all && all[customerId]) || { items: [], count: 0 }; 6623 } 6624 6625 // ---------- Cart helpers (Atlas's updateCart + updateCartElements) ---------- 6626 async function updateCart(payload, action) { 6627 const map = { UPDATE: 'cart/update.js', CHANGE: 'cart/change.js', ADD: 'cart/add.js', REMOVE: 'cart/remove.js' }; 6628 const endpoint = map[action]; 6629 if (!endpoint) throw new Error('updateCart: unknown action ' + action); 6630 const root = (window.Shopify && window.Shopify.routes && window.Shopify.routes.root) || '/'; 6631 const res = await fetch(root + endpoint, { 6632 method: 'POST', 6633 headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, 6634 body: JSON.stringify(payload), 6635 credentials: 'same-origin' 6636 }); 6637 if (!res.ok) { 6638 // Shopify returns a JSON body on 4xx with the actual reason 6639 // ("You can only add N of that item...", "The product is sold 6640 // out", etc.). Surface it â a bare "HTTP 422" tells the shopper 6641 // and the next dev nothing, and Move-to-Bag now shows this. 6642 let description = ''; 6643 try { 6644 const body = await res.json(); 6645 description = body.description || body.message || ''; 6646 } catch (_) { /* non-JSON error body */ } 6647 const err = new Error(action + ' HTTP ' + res.status + (description ? ': ' + description : '')); 6648 err.status = res.status; 6649 err.description = description; 6650 throw err; 6651 } 6652 return res.json(); 6653 } 6654 function updateCartElements(cart) { 6655 document.dispatchEvent(new CustomEvent('cart:change', { detail: { cart } })); 6656 document.dispatchEvent(new CustomEvent('cart:updated', { detail: { cart } })); // BP drawer listens here 6657 document.dispatchEvent(new CustomEvent('product:added', { detail: { cart } })); 6658 } 6659 6660 // ---------- Swym proxy fetch ---------- 6661 async function getWishlist() { 6662 if (typeof window.SWGetExpressWishlistId !== 'function') return null; 6663 const wishlistId = window.SWGetExpressWishlistId(); 6664 if (wishlistId === 0 || wishlistId == null) return null; 6665 const customerId = getCustomerId(); 6666 const path = customerId && customerId !== 'guest' 6667 ? `/a/wishlist?type=api&customerid=${encodeURIComponent(customerId)}&version=1` 6668 : `/a/wishlist?type=api&wishlistid=${encodeURIComponent(wishlistId)}&version=1`;
6669 try { 6670 const res = await fetch(path, { credentials: 'same-origin' }); 6671 if (!res.ok) return null; 6672 return await res.json(); 6673 } catch (e) { 6674 console.warn('[bp-swym] proxy fetch failed', e); 6675 return null; 6676 } 6677 } 6678 6679 // ---------- Save the cart line to wishlist ---------- 6680 // Mirror of Atlas's handleSaveForLater(e, product) â `product` is 6681 // the cart line item (BP cart drawer passes a structured object). 6682 async function handleSaveForLater(e, product) { 6683 if (e && typeof e.preventDefault === 'function') e.preventDefault(); 6684 if (!product) return; 6685 6686 const customerId = getCustomerId(); 6687 const isCollectiveProduct = 6688 Array.isArray(product.tags) && 6689 (product.tags.indexOf('Shopify Collective') >= 0 || product.tags.indexOf('Collective') >= 0); 6690 6691 // Snapshot matches Atlas's cartItemData shape verbatim. 6692 const sku = (product.sku || product.variant_sku || '').toString(); 6693 const skuPrefix = sku.slice(0, 7); 6694 const cartItemData = { 6695 id: (product.product_id != null ? product.product_id : product.id) + '', 6696 handle: product.handle || '', 6697 variant_price: (product.variant_price != null 6698 ? product.variant_price 6699 : (product.variant && product.variant.price)) + '', 6700 variant_compare_at_price: (product.variant_compare_at_price != null 6701 ? product.variant_compare_at_price 6702 : (product.variant && product.variant.compareAtPrice)) + '', 6703 variant_title: (product.variant_title 6704 || (product.variant && product.variant.title) 6705 || '') + '', 6706 variant_id: (product.variant_id != null 6707 ? product.variant_id 6708 : (product.variant && product.variant.id)) + '', 6709 title: product.title || '', 6710 image: 6711 isCollectiveProduct || !skuPrefix 6712 ? (product.image || '') 6713 : `${AMPLIENCE_BASE}/s/bostonproper/${skuPrefix}_SET/1?fmt=auto&w=484`, 6714 quantity: ((product.quantity != null ? product.quantity : 1) + ''), 6715 variant_sku: sku, 6716 // Client save timestamp â the saved drawer sorts newest-first by this, 6717 // so a fresh save stays on top regardless of the mirror/Swym array 6718 // order (QA 7/27, Dragana: item landed at the bottom in-session). 6719 savedAt: Date.now() 6720 }; 6721 6722 const lineKey = product.line_key || product.key || (e && e.target && (function () { 6723 const li = e.target.closest('[data-bp-cart-line], [data-line-key], .cart-item'); 6724 return li && (li.dataset.lineKey || li.getAttribute('data-line-key')); 6725 })()); 6726 6727 // 1) Add to Swym (silent if app not loaded). 6728 try { 6729 if (typeof window.AddToSmartWishlist === 'function') { 6730 window.AddToSmartWishlist(cartItemData.id, cartItemData.variant_id); 6731 } 6732 } catch (err) { console.warn('[bp-swym] AddToSmartWishlist failed', err); } 6733 6734 // 2) Remove from cart. 6735 let cart = null; 6736 if (lineKey) { 6737 try { 6738 cart = await updateCart({ id: lineKey, quantity: 0 }, 'CHANGE'); 6739 updateCartElements(cart); 6740 } catch (err) { console.warn('[bp-swym] cart change failed', err); } 6741 } 6742 6743 // 3) Update local mirror. 6744 const all = getSavedItemsLocalStorage() || {}; 6745 const current = all[customerId] || { items: [], count: 0 }; 6746 // Prepend (newest first) so the optimistic in-session order matches the 6747 // order after reload (the saved list renders newest-first). Appending put 6748 // a fresh save at the BOTTOM in-session but the TOP after refresh 6749 // (QA 7/22, Dragana). 6750 const nextItems = [cartItemData].concat( 6751 current.items.filter((it) => it.variant_id !== cartItemData.variant_id) 6752 ); 6753 all[customerId] = { ...current, items: nextItems, count: nextItems.length }; 6754 storeSavedItemsLocalStorage(all); 6755 // Record the authoritative newest-first order (Swym-proof). 6756 stampSavedOrder(cartItemData.variant_id); 6757 6758 document.dispatchEvent(new CustomEvent('wishlist:item-saved', { detail: { item: cartItemData } })); 6759 return cart; 6760 } 6761 6762 // ---------- Remove from Swym + local mirror ---------- 6763 function removeWishlistItem(productId, variantId) { 6764 const customerId = getCustomerId(); 6765 const all = getSavedItemsLocalStorage() || {}; 6766 const current = all[customerId] || { items: [], count: 0 }; 6767 const removed = current.items.find((it) => String(it.variant_id) === String(variantId)) || null; 6768 const nextItems = current.items.filter((it) => String(it.variant_id) !== String(variantId)); 6769 all[customerId] = { ...current, items: nextItems, count: nextItems.length }; 6770 storeSavedItemsLocalStorage(all); 6771 clearSavedOrder(variantId); 6772
6773 try { 6774 if (typeof window.RemoveFromSmartWishlist === 'function') { 6775 window.RemoveFromSmartWishlist(productId, variantId); 6776 } 6777 } catch (err) { console.warn('[bp-swym] RemoveFromSmartWishlist failed', err); } 6778 6779 // Dispatched so analytics (bp-track-wishlist) can fire GA4 6780 // remove_from_wishlist. Detail carries the removed cart-line- 6781 // shaped object so the listener has enough to build the 6782 // GA4 items[] entry. 6783 if (removed) { 6784 document.dispatchEvent(new CustomEvent('wishlist:item-removed', { detail: { item: removed } })); 6785 } 6786 } 6787 6788 // ---------- Build BP Line Item Properties for Move-to-Bag ---------- 6789 // Port of Atlas's updateLineItemProperties() â preserves the LIPs 6790 // BP uses on every cart line so they survive the save/restore. 6791 function updateLineItemProperties(variant, inventoryAvailable) { 6792 const props = {}; 6793 try { 6794 const attrs = (variant && variant.BP_ProductAttributes) || {}; 6795 // Atlas reads both spellings (updateLineItemProperties.js:41-45); 6796 // existing ERP values aren't being converted, so a product 6797 // written at either spelling has to keep working. 6798 const catalogId = attrs.BP_CurrentEventID || attrs.bp_currenteventid; 6799 if (catalogId) props._catalog_id = catalogId; 6800 const priceStatus = attrs.BP_PriceStatus || attrs.bp_pricestatus; 6801 if (priceStatus) props._price_status = priceStatus; 6802 6803 const hasFinalSale = attrs.has_final_sale === 'yes'; 6804 if (hasFinalSale) props._final_sale = 'yes'; 6805 6806 // Pre-order date. Match the value union Atlas accepts rather 6807 // than case-sensitive 'T' â Atlas's React paths lower-case 6808 // first (ProductMain.js:67), so variants stored as "t"/"true"/ 6809 // "yes"/"1" are live pre-orders today and must stay that way. 6810 const rawPreorder = variant && variant.bp_preorder 6811 ? (variant.bp_preorder.value !== undefined ? variant.bp_preorder.value : variant.bp_preorder) 6812 : ''; 6813 const isPreorder = rawPreorder === true || 6814 ['t', 'true', 'yes', '1'].includes(String(rawPreorder).toLowerCase().trim()); 6815 const rawShipDate = variant && variant.expectedShipDate_Inbound && variant.expectedShipDate_Inbound[0] 6816 ? variant.expectedShipDate_Inbound[0].value 6817 : (variant && variant.expectedShipDate && variant.expectedShipDate.value); 6818 if (isPreorder && rawShipDate) { 6819 // No +13 offset â Atlas shows the raw DC-arrival date with only 6820 // weekend/holiday skipping applied (dateHelpers.skipWeekendsHol); 6821 // the earlier +13 here made a restored-from-save item's LIP ~2 6822 // weeks later than the cart's live recompute. Prefer the shared 6823 // window.bpPreorder helper (the Atlas-verbatim port used by the 6824 // PDP + cart) so all surfaces agree; fall back to a local 6825 // weekend-skip if it hasn't loaded. 6826 try { 6827 let formatted = null; 6828 if (window.bpPreorder && window.bpPreorder.formatDate) { 6829 formatted = window.bpPreorder.formatDate(rawShipDate); 6830 } else { 6831 const d = new Date(rawShipDate); 6832 if (!isNaN(d.getTime()) && d >= new Date()) { 6833 const day = d.getDay(); 6834 if (day === 6) d.setDate(d.getDate() + 2); 6835 else if (day === 0) d.setDate(d.getDate() + 1); 6836 formatted = d.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: '2-digit' }); 6837 } 6838 } 6839 if (formatted) props._expected_ship_date = formatted; 6840 } catch (_) {} 6841 } 6842 } catch (e) { console.warn('[bp-swym] LIP build failed', e); } 6843 return props; 6844 } 6845 6846 // ---------- Move saved item back to the cart ---------- 6847 // Throws if the line could not be added. Callers MUST let that 6848 // propagate to the UI: the saved entry is the only record of the 6849 // item, so a swallowed failure loses it (see the ordering note 6850 // below). 6851 async function handleMoveToBag(id, variantId, quantity, isWishlistItemProductLevel, item, variant) { 6852 // Fetch master product to validate inventory + carry BP attrs. 6853 let inventoryAvailable = 0; 6854 let resolvedVariant = variant || {}; 6855 // The id we actually post to /cart/add.js. Starts as the saved 6856 // variant_id but is replaced by the resolved variant below â 6857 // a product-level save (isWishlistItemProductLevel: variant_id 6858 // === product_id, no variant ever chosen) stores a PRODUCT id 6859 // here, and /cart/add.js 422s on those every time. 6860 let addVariantId = variantId;
6861 try { 6862 if (item && item.handle) { 6863 const res = await fetch(`/products/${item.handle}.js`, { credentials: 'same-origin' }); 6864 if (res.ok) { 6865 const product = await res.json(); 6866 const variants = product.variants || []; 6867 // Exact variant first; otherwise fall back to a sellable 6868 // one (product-level saves, or a variant retired since it 6869 // was saved). Prefer `available` over variants[0] so we 6870 // don't resolve straight onto a sold-out variant. 6871 let v = variants.find((vv) => String(vv.id) === String(variantId)); 6872 if (!v) v = variants.find((vv) => vv.available) || variants[0]; 6873 if (v) { 6874 addVariantId = v.id; 6875 inventoryAvailable = (v.inventory_quantity != null) ? v.inventory_quantity : 0; 6876 resolvedVariant = { ...v, ...resolvedVariant }; 6877 // BP_ProductAttributes (Atlas pulls from getMasterProduct's colorProduct.BP_ProductAttributes) 6878 const tags = product.tags || []; 6879 const hasFinalSale = tags.some((t) => String(t).toLowerCase().trim() === 'final sale'); 6880 resolvedVariant.BP_ProductAttributes = Object.assign( 6881 {}, 6882 resolvedVariant.BP_ProductAttributes || {}, 6883 { has_final_sale: hasFinalSale ? 'yes' : 'no' } 6884 ); 6885 } 6886 } 6887 } 6888 } catch (err) { /* non-fatal â push to cart with the saved id */ } 6889 6890 let properties = updateLineItemProperties(resolvedVariant, inventoryAvailable) || {}; 6891 // The metafield-derived LIPs (_catalog_id, _price_status, _final_sale, 6892 // _compare_at_price, _price) can't be computed client-side â they aren't 6893 // on the /products/<handle>.js variant JSON. Pull them from the canonical 6894 // ?view=lips endpoint so Move-to-Bag carries the SAME LIPs as add-to-cart 6895 // (QA 7/16 â they were missing). Then the saved line's own stored 6896 // properties win, preserving whatever LIP state it had when saved. 6897 if (window.bpLips && item && item.handle) { 6898 try { 6899 const canonical = await window.bpLips.forVariant(item.handle, addVariantId); 6900 if (canonical) properties = Object.assign({}, canonical, properties); 6901 } catch (_) { /* keep the computed set */ } 6902 } 6903 if (item && item.properties && Object.keys(item.properties).length) { 6904 properties = Object.assign(properties, item.properties); 6905 } 6906 const itemToAdd = { 6907 id: addVariantId, 6908 quantity: quantity != null ? quantity : 1 6909 }; 6910 if (Object.keys(properties).length) itemToAdd.properties = properties; 6911 6912 // Add FIRST, and let a failure throw. 6913 // 6914 // This used to remove from the wishlist optimistically and then 6915 // swallow any add error in a console.warn. That combination is 6916 // unrecoverable data loss rather than a cosmetic bug: the saved 6917 // entry is the item's only record, so any 422 (sold out, retired 6918 // variant, product-level id) silently destroyed it â the item 6919 // vanished from Saved for Later and never reached the cart. There 6920 // is nothing to be optimistic about here; the wishlist row costs 6921 // nothing to keep for the extra round trip. 6922 const cart = await updateCart({ items: [itemToAdd] }, 'ADD'); 6923 updateCartElements(cart); 6924 6925 // Only now that the line is really in the cart is it safe to drop 6926 // the save. Remove by the SAVED variantId (what the local mirror 6927 // and Swym are keyed on), not the resolved addVariantId â those 6928 // differ for product-level saves. 6929 if (isWishlistItemProductLevel) removeWishlistItem(id, id); 6930 else removeWishlistItem(id, variantId); 6931 6932 document.dispatchEvent(new CustomEvent('wishlist:item-saved')); 6933 return cart; 6934 } 6935 6936 // ---------- Sync local mirror with Swym ---------- 6937 // Readiness signal for consumers (the saved drawer): flips true the first 6938 // time checkWishlistSync reconciles against a real Swym response. Lets the 6939 // drawer WAIT for Swym and show a loading state instead of rendering 6940 // localStorage first and flashing when Swym replaces it. If Swym never 6941 // responds the consumer falls back to localStorage on its own timeout. 6942 let swymSynced = false;
6943 function isSynced() { return swymSynced; } 6944 function markSynced() { 6945 if (swymSynced) return; 6946 swymSynced = true; 6947 document.dispatchEvent(new CustomEvent('bp:saved:synced')); 6948 } 6949 6950 async function checkWishlistSync() { 6951 const local = getLocalWishlist(); 6952 let remote = null; 6953 try { remote = await getWishlist(); } catch (_) { remote = null; } 6954 if (!remote) return; // Swym not ready yet â a later `wishlistloaded` retries. 6955 const customerId = getCustomerId(); 6956 const all = getSavedItemsLocalStorage() || {}; 6957 // If counts differ, remote is the source of truth â EXCEPT when the 6958 // remote reads empty while local has items. Swym's API returns count 0 6959 // before it finishes hydrating the customer's wishlist, and treating that 6960 // as truth overwrote the local mirror with nothing: the saved drawer 6961 // showed the items on open, then blanked to "empty" and stayed empty until 6962 // a reopen re-synced. Keep local in that case (a genuine cross-device 6963 // clear is far rarer than this hydration race, and local edits already 6964 // update the mirror directly). 6965 if ((remote.count || 0) === 0 && (local.count || 0) > 0) { 6966 all[customerId] = local; 6967 storeSavedItemsLocalStorage(all); 6968 markSynced(); 6969 return; 6970 } 6971 if ((remote.count || 0) !== (local.count || 0)) { 6972 // Carry the client save timestamps over from the local mirror so a 6973 // freshly-saved item keeps sorting to the top even after the server 6974 // (whose item order lags/varies) becomes source of truth â otherwise 6975 // the sort key is lost and the item drops down the list (QA 7/27). 6976 const localByVariant = {}; 6977 (local.items || []).forEach((it) => { if (it && it.savedAt) localByVariant[String(it.variant_id)] = it.savedAt; }); 6978 const remoteItems = (remote.items || []).map((it) => { 6979 const ts = localByVariant[String(it.variant_id)]; 6980 return (ts && !it.savedAt) ? Object.assign({}, it, { savedAt: ts }) : it; 6981 }); 6982 all[customerId] = Object.assign({}, remote, { items: remoteItems }); 6983 storeSavedItemsLocalStorage(all); 6984 } else { 6985 // Counts match â keep the merged shape so newly-saved local 6986 // items remain even if Swym has caught up. 6987 all[customerId] = local; 6988 storeSavedItemsLocalStorage(all); 6989 } 6990 markSynced(); 6991 } 6992 6993 // ---------- Swym ready bridge (Atlas: wishlist-load-event.js) ---------- 6994 const WishlistLoadedEvent = new Event('wishlistloaded'); 6995 window.SWCallbackWishlistButtonLoaded = function () { 6996 window.dispatchEvent(WishlistLoadedEvent); 6997 }; 6998 // When Swym is ready, sync. Also try once after DOM ready in case 6999 // Swym already loaded. 7000 window.addEventListener('wishlistloaded', checkWishlistSync); 7001 document.addEventListener('DOMContentLoaded', () => { 7002 // Defer a tick so other listeners attach first. 7003 setTimeout(checkWishlistSync, 50); 7004 }); 7005 7006 // ---------- Cross-context cache invalidation ---------- 7007 // getLocalWishlist prefers the in-memory `memoryState` over localStorage 7008 // for speed. When ANOTHER same-origin document writes the shared key â 7009 // e.g. a save made inside the Publitas digital-catalog quickview iframe â 7010 // THIS window's memoryState is stale, so the saved drawer + top-nav count 7011 // didn't update until a reload (QA 7/27, Dragana). Re-seed memoryState from 7012 // localStorage so consumers read the fresh state. 7013 function reloadFromStorage() { 7014 const fresh = readLocalStorageRaw(); 7015 if (fresh) memoryState = fresh; 7016 return fresh; 7017 } 7018 // A localStorage write in a different same-origin document (the quickview 7019 // iframe) fires `storage` HERE (never in the writing document). Re-seed and 7020 // notify the drawer / bubble to re-render live. 7021 window.addEventListener('storage', (e) => { 7022 if (!e || e.key !== LOCAL_STORAGE_KEY) return; 7023 reloadFromStorage(); 7024 document.dispatchEvent(new CustomEvent('bp:saved:updated')); 7025 document.dispatchEvent(new CustomEvent('wishlist:updated')); 7026 }); 7027
7028 // ---------- Save-order map (Swym-proof newest-first ordering) ---------- 7029 // Per-item `savedAt` isn't reliable for "newest on top": Swym's async sync 7030 // rewrites the item objects (dropping our timestamp) and reorders them, so 7031 // a fresh save kept landing at the bottom. Keep an authoritative 7032 // variant_id â timestamp map in a SEPARATE localStorage key Swym never 7033 // manages; the saved drawer sorts by it. Survives every Swym sync/reorder. 7034 const ORDER_KEY = 'bp.saved_order'; 7035 function getSavedOrder() { 7036 try { return JSON.parse(window.localStorage.getItem(ORDER_KEY) || '{}') || {}; } 7037 catch (_) { return {}; } 7038 } 7039 function stampSavedOrder(variantId) { 7040 if (variantId == null || variantId === '') return; 7041 try { 7042 const m = getSavedOrder(); 7043 m[String(variantId)] = Date.now(); 7044 window.localStorage.setItem(ORDER_KEY, JSON.stringify(m)); 7045 } catch (_) { /* storage full â ordering falls back to savedAt */ } 7046 } 7047 function clearSavedOrder(variantId) { 7048 try { 7049 const m = getSavedOrder(); 7050 if (delete m[String(variantId)]) window.localStorage.setItem(ORDER_KEY, JSON.stringify(m)); 7051 } catch (_) {} 7052 } 7053 7054 // ---------- Expose globals (Atlas parity) ---------- 7055 window.bpSavedForLater = { 7056 LOCAL_STORAGE_KEY: LOCAL_STORAGE_KEY, 7057 getSavedItemsLocalStorage: getSavedItemsLocalStorage, 7058 storeSavedItemsLocalStorage: storeSavedItemsLocalStorage, 7059 getLocalWishlist: getLocalWishlist, 7060 getWishlist: getWishlist, 7061 removeWishlistItem: removeWishlistItem, 7062 updateLineItemProperties: updateLineItemProperties, 7063 checkWishlistSync: checkWishlistSync, 7064 isSynced: isSynced, 7065 reloadFromStorage: reloadFromStorage, 7066 getCustomerId: getCustomerId, 7067 getSavedOrder: getSavedOrder, 7068 stampSavedOrder: stampSavedOrder, 7069 clearSavedOrder: clearSavedOrder 7070 }; 7071 window.handleSaveForLater = handleSaveForLater; 7072 window.handleMoveToBag = handleMoveToBag; 7073 })(); 7074</script>
vendor: 1 bytes, line 7074
7074
7075<script 7076 src="https://cdn-widgetsrepository.yotpo.com/v1/loader/l9OjGj5YqKVR9PFonEHJc4ms9HXq9RV8dOWnI8LL?languageCode=en" 7077 async 7078 ></script>
7078<script> 7079(function () { 7080 if (window.__bpYotpoStarsQvNav) return; 7081 window.__bpYotpoStarsQvNav = true; 7082 7083 var MODAL_SEL = 'dialog.quick-add-modal, .quick-add-modal, #quick-add-modal-content, .quick-add-modal__content'; 7084 var DEBUG = false; // flip via window.bpYotpoQvNavDebug = true 7085 function log() { 7086 if (!DEBUG && !window.bpYotpoQvNavDebug) return; 7087 var args = ['[bp-yotpo-qv-nav]'].concat(Array.prototype.slice.call(arguments)); 7088 console.log.apply(console, args); 7089 } 7090 7091 function navigateFromHost(host, e) { 7092 var url = host.getAttribute('data-bp-product-url'); 7093 if (!url) { 7094 log('no data-bp-product-url on host', host); 7095 return false; 7096 } 7097 if (e) { 7098 e.preventDefault(); 7099 e.stopPropagation(); 7100 if (e.stopImmediatePropagation) e.stopImmediatePropagation(); 7101 } 7102 log('navigating â', url + '#bp-pdp-reviews'); 7103 window.location.href = url + '#bp-pdp-reviews'; 7104 return true; 7105 } 7106 7107 // 1) Document-level delegated fallback (capture phase). Handles the 7108 // case where Yotpo's own handlers haven't yet stopped propagation. 7109 ['pointerdown', 'mousedown', 'click'].forEach(function (evt) { 7110 document.addEventListener(evt, function (e) { 7111 var host = e.target.closest && e.target.closest('.bp-yotpo-stars'); 7112 if (!host) return; 7113 if (!host.closest(MODAL_SEL)) return; 7114 if (evt === 'click') navigateFromHost(host, e); 7115 }, true); 7116 }); 7117 7118 // 2) Direct-attach listener on any `.bp-yotpo-stars` that shows up 7119 // inside the drawer â belt-and-suspenders in case Yotpo's Vue 7120 // stops propagation before it reaches document. A MutationObserver 7121 // watches the whole drawer subtree; when the widget hydrates it 7122 // also gets the same click handler. 7123 function wireDrawerStars(root) { 7124 root.querySelectorAll('.bp-yotpo-stars').forEach(function (host) { 7125 if (host.__bpYotpoQvWired) return; 7126 host.__bpYotpoQvWired = true; 7127 host.style.cursor = 'pointer'; 7128 host.addEventListener('click', function (e) { navigateFromHost(host, e); }, true); 7129 // Yotpo's own summary sometimes eats the click â also listen on 7130 // pointerdown/mousedown which fire earlier in the event sequence. 7131 host.addEventListener('mousedown', function () { log('mousedown on stars'); }, true); 7132 log('wired stars host', host); 7133 }); 7134 } 7135 7136 function observeAll() { 7137 document.querySelectorAll(MODAL_SEL).forEach(function (drawer) { 7138 if (drawer.__bpYotpoQvObserved) return; 7139 drawer.__bpYotpoQvObserved = true; 7140 wireDrawerStars(drawer); 7141 var mo = new MutationObserver(function () { wireDrawerStars(drawer); }); 7142 mo.observe(drawer, { childList: true, subtree: true }); 7143 log('observing drawer', drawer); 7144 }); 7145 } 7146 7147 if (document.readyState === 'loading') { 7148 document.addEventListener('DOMContentLoaded', observeAll); 7149 } else { 7150 observeAll(); 7151 } 7152 // Drawers might mount after initial load â watch the body for the 7153 // dialog itself appearing. 7154 new MutationObserver(observeAll).observe(document.documentElement, { childList: true, subtree: true }); 7155})(); 7156</script>
vendor: 1 bytes, line 7156
7156
7157<script> 7158 !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)}}}}(); 7159</script>
7159<script> 7160 (function () { 7161 'use strict'; 7162 var ACCOUNT = "\/account"; 7163 var HASH = '#k-hub'; 7164 7165 function hubHref(href) { 7166 href = String(href || ''); 7167 if (href.indexOf(HASH) !== -1) return href; 7168 return href.split('#')[0] + HASH; 7169 } 7170 7171 // Open the hub WITHOUT navigating. Klaviyo's onsite runtime opens 7172 // Customer Hub by intercepting clicks on `#k-hub` anchors (it calls 7173 // preventDefault, so the page never navigates). A programmatic 7174 // `location.assign('/account#k-hub')` is NOT a click, so Klaviyo 7175 // can't intercept it â the browser really does load /account (a 7176 // "not found" under the new customer-accounts setup) and only then 7177 // does the hub open on the hash. Instead, synthesize a real click 7178 // on a bare `#k-hub` anchor: Klaviyo's delegated handler catches it 7179 // and slides the hub in place. If the hub isn't Live, a bare 7180 // `#k-hub` just sets the current-page hash â no navigation, no 7181 // not-found page (unlike the old /account#k-hub assign). 7182 function openHub() { 7183 var a = document.createElement('a'); 7184 a.setAttribute('href', HASH); 7185 a.setAttribute('aria-hidden', 'true'); 7186 a.style.cssText = 'position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);'; 7187 (document.body || document.documentElement).appendChild(a); 7188 a.click(); 7189 setTimeout(function () { if (a.parentNode) a.parentNode.removeChild(a); }, 0); 7190 } 7191 7192 // Rewrite standalone account anchors (mobile nav, footer, etc.) â 7193 // the same rewrite Klaviyo does automatically on standard themes. 7194 function rewriteAnchors() { 7195 var links = document.querySelectorAll( 7196 'a[href="' + ACCOUNT + '"], a[href^="' + ACCOUNT + '?"], a[href$="/account"], a[href*="/account?"]' 7197 ); 7198 for (var i = 0; i < links.length; i++) { 7199 var a = links[i]; 7200 if (a.__kHub || a.hasAttribute('data-k-hub-ignore')) continue; 7201 a.setAttribute('href', hubHref(a.getAttribute('href'))); 7202 a.__kHub = 1; 7203 } 7204 } 7205 7206 // The desktop header account control is a <shopify-account> web 7207 // component with no plain /account anchor for Klaviyo to rewrite. 7208 // Intercept clicks on it (capture phase, so we beat the component's 7209 // own navigation handler) and open the hub in place via openHub(). 7210 // When Customer Hub is Live, Klaviyo slides the hub in; otherwise 7211 // the bare `#k-hub` hash is a no-op â the icon simply does nothing 7212 // rather than navigating to a not-found account page. 7213 document.addEventListener('click', function (e) { 7214 var scope = e.target.closest && e.target.closest('shopify-account, .account-button'); 7215 if (!scope || scope.hasAttribute('data-k-hub-ignore')) return; 7216 // If the click is already on a #k-hub anchor, let it through. 7217 var a = e.target.closest('a[href]'); 7218 if (a && a.getAttribute('href').indexOf(HASH) !== -1) return; 7219 e.preventDefault(); 7220 e.stopPropagation(); 7221 openHub(); 7222 }, true); 7223 7224 // Rewrite now and again as Horizon hydrates / injects account links 7225 // (short-lived â the anchors settle early). 7226 rewriteAnchors(); 7227 var runs = 0; 7228 var timer = setInterval(function () { 7229 rewriteAnchors(); 7230 if (++runs >= 6) clearInterval(timer); // ~3s of catch-up 7231 }, 500); 7232 window.addEventListener('load', rewriteAnchors); 7233 })(); 7234 </script>
7234<script src="//www.bostonproper.com/cdn/shop/t/1516/assets/bp-stl-drawer.js?v=94264581757947261801790192827" defer></script>
7234 7235
7235<script src="//www.bostonproper.com/cdn/shop/t/1516/assets/bp-mega-hover.js?v=154014205721503400101790192827" defer></script>
7235 7236 7237 7238 7239 7240 7241 7242
7242<script> 7243 (function (w, d, s, l, i) { 7244 w[l] = w[l] || []; 7245 w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' }); 7246 var f = d.getElementsByTagName(s)[0], 7247 j = d.createElement(s), 7248 dl = l != 'dataLayer' ? '&l=' + l : ''; 7249 j.async = true; 7250 j.src = 7251 'https://sst.bostonproper.com/gtm.js?id=' + 7252 i + 7253 dl + 7254 '>m_auth=288FkNoOr_QXQEJ-WPHnww>m_preview=env-1>m_cookies_win=x'; 7255 f.parentNode.insertBefore(j, f); 7256 })(window, document, 'script', 'dataLayer', 'GTM-NS3X79G'); 7257 </script>
7257<script id="customizer-settings" type="application/json"> 7258 { 7259 "final_sale_message": "Final Sale" 7260 } 7261 </script>
7261 7262 7263
7263<script>window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.start');</script>
7263<meta name="facebook-domain-verification" content="9a5visacrvjynl4zpb4ys6j4byfwwp"> 7264<meta id="shopify-digital-wallet" name="shopify-digital-wallet" content="/52960723110/digital_wallets/dialog"> 7265<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"> 7266<link rel="ucp" href="/.well-known/ucp" version="2026-08-25"><link rel="alternate" type="application/atom+xml" title="Feed" href="/blogs/styleedit.atom" /> 7267<link rel="next" href="/blogs/styleedit?page=2">
7268<script async="async" src="/checkouts/internal/preloads.js?locale=en-US&default_configuration_id=8857419942"></script>
7268 7269<link rel="preconnect" href="https://shop.app" crossorigin="anonymous">
7270<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 7270
7270
7271<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 7271
7271
7272<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 7272
7272
7273<script>var Shopify = Shopify || {}; 7274Shopify.shop = "bostonproper.myshopify.com"; 7275Shopify.locale = "en"; 7276Shopify.currency = {"active":"USD","rate":"1.0"}; 7277Shopify.country = "US"; 7278Shopify.theme = {"name":"Fall Home 2 | Wear-Now 9\/24 | V2.0.11 ","id":197929926822,"schema_name":"Horizon","schema_version":"3.5.0","theme_store_id":null,"role":"main"}; 7279Shopify.theme.handle = "null"; 7280Shopify.theme.style = {"id":null,"handle":null}; 7281Shopify.cdnHost = "www.bostonproper.com/cdn"; 7282Shopify.routes = Shopify.routes || {}; 7283Shopify.routes.root = "/"; 7284Shopify.shopJsCdnBaseUrl = "https://cdn.shopify.com/shopifycloud/shop-js"; 7285Shopify.SignInWithShop = Shopify.SignInWithShop || {}; 7286Shopify.SignInWithShop.User = Shopify.SignInWithShop.User || {}; 7287Shopify.SignInWithShop.User.recognized = false;</script>
vendor: 1 bytes, line 7287
7287
7288<script type="module">!function(o){(o.Shopify=o.Shopify||{}).modules=!0}(window);</script>
vendor: 1 bytes, line 7288
7288
7289<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 7289
7289
7290<script> 7291 window.ShopifyPay = window.ShopifyPay || {}; 7292 window.ShopifyPay.apiHost = "shop.app\/pay"; 7293 window.ShopifyPay.redirectState = null; 7294</script>
vendor: 1 bytes, line 7294
7294
7295<script> 7296 window.Shopify = window.Shopify || {}; 7297 window.Shopify.SignInWithShop = window.Shopify.SignInWithShop || {}; 7298 window.Shopify.SignInWithShop.assetMetrics = { sampleRate: 0.25 }; 7299 window.Shopify.SignInWithShop.eligible = true; 7300</script>
vendor: 1 bytes, line 7300
7300
7301<script id="shop-js-analytics" type="application/json">{"pageType":"blog"}</script>
vendor: 1 bytes, line 7301
7301
7302<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 7302
7302
7303<script type="module"> 7304 await import("https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.init-shop-cart-sync.en.esm.js"); 7305 7306 window.Shopify.SignInWithShop?.initShopCartSync?.({"fedCMEnabled":true,"windoidEnabled":true}); 7307 7308</script>
vendor: 1 bytes, line 7308
7308
7309<script> 7310 window.Shopify = window.Shopify || {}; 7311 if (!window.Shopify.featureAssets) window.Shopify.featureAssets = {}; 7312 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"]}; 7313</script>
vendor: 1 bytes, line 7313
7313
7314<script>(function() { 7315 var isLoaded = false; 7316 function asyncLoad() { 7317 if (isLoaded) return; 7318 isLoaded = true; 7319 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"]; 7320 for (var i = 0; i < urls.length; i++) { 7321 var s = document.createElement('script'); 7322 s.type = 'text/javascript'; 7323 s.async = true; 7324 s.src = urls[i]; 7325 var x = document.getElementsByTagName('script')[0]; 7326 x.parentNode.insertBefore(s, x); 7327 } 7328 }; 7329 if(window.attachEvent) { 7330 window.attachEvent('onload', asyncLoad); 7331 } else { 7332 window.addEventListener('load', asyncLoad, false); 7333 } 7334})();</script>
vendor: 1 bytes, line 7334
7334
7335<script id="__st">var __st={"a":52960723110,"offset":-14400,"reqid":"c9758f03-eb56-425e-8c7b-c1be7ef20e39-1790361970","pageurl":"www.bostonproper.com\/blogs\/styleedit","s":"blogs-82989514918","u":"f455bbc6f9ba","p":"blog","rtyp":"blog","rid":82989514918};</script>
vendor: 1 bytes, line 7335
7335
7336<script>window.ShopifyPaypalV4VisibilityTracking = true;</script>
vendor: 1 bytes, line 7336
7336
7337<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 7337
7337
7338<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 7338
7338
7339<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>
7339<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 7339
7339
7340<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 7340
7340
7341<script> 7342 window.Shopify = window.Shopify || {}; 7343 window.Shopify.MCP = window.Shopify.MCP || {}; 7344 window.Shopify.MCP.enabled = true; 7345 window.Shopify.MCP.shop = "bostonproper.myshopify.com"; 7346 window.Shopify.MCP.mcpEndpoint = "https:\/\/www.bostonproper.com\/api\/mcp"; 7347 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"]}}]; 7348</script>
vendor: 1 bytes, line 7348
7348
7349<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=");})(); 7350</script>
vendor: 1 bytes, line 7350
7350
7351<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)}}; 7352</script>
vendor: 1 bytes, line 7352
7352
7353<script data-source-attribution="shopify.dynamic_checkout.buyer_consent"> 7354 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); 7355</script>
vendor: 1 bytes, line 7355
7355
7356<script data-source-attribution="shopify.dynamic_checkout.cart.bootstrap">document.addEventListener("DOMContentLoaded",(function(){function t(){return document.querySelector("shopify-accelerated-checkout-cart, shopify-accelerated-checkout")}if(t())Shopify.PaymentButton.init();else{new MutationObserver((function(e,n){t()&&(Shopify.PaymentButton.init(),n.disconnect())})).observe(document.body,{childList:!0,subtree:!0})}})); 7357</script>
vendor: 1 bytes, line 7357
7357
7358<script integrity="sha256-/LA1C2Bx6899fYCos0FS9qLj2opaGFm7AXrTUvBEb4s=" data-source-attribution="shopify.remote_product_tracking" data-shopify-remote-tracking="{"publisher_shop_id":52960723110,"theme_id":197929926822,"theme_published":true,"theme_store_id":0,"placement":"collection","event_data":{"handle":"styleedit","page_type":"blog"},"recommendations_tracking_enabled":true}" defer="defer" src="//www.bostonproper.com/cdn/shopifycloud/storefront/assets/storefront/remote_product_tracking-91d95044.js" crossorigin="anonymous"></script>
7358 7359<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"> 7360<style id="shopify-accelerated-checkout-cart"> 7361 #shopify-buyer-consent { 7362 margin-top: 1em; 7363 display: inline-block; 7364 width: 100%; 7365} 7366 7367#shopify-buyer-consent.hidden { 7368 display: none; 7369} 7370 7371#shopify-subscription-policy-button { 7372 background: none; 7373 border: none; 7374 padding: 0; 7375 text-decoration: underline; 7376 font-size: inherit; 7377 cursor: pointer; 7378} 7379 7380#shopify-subscription-policy-button::before { 7381 box-shadow: none; 7382} 7383 7384 </style> 7385<link rel="stylesheet" media="screen" href="//www.bostonproper.com/cdn/shop/t/1516/compiled_assets/styles.css?v=19732329664960895141790192971">
7386<script id="sections-script" data-sections="bp-blog,bp-footer-main,bp-quick-drawer" defer="defer" src="//www.bostonproper.com/cdn/shop/t/1516/compiled_assets/scripts.js?v=142284309545595811851790192972"></script>
vendor: 1 bytes, line 7386
7386
7387<script id="snippets-script" data-snippets="bp-search-drawer,bp-card-swatches" defer="defer" src="//www.bostonproper.com/cdn/shop/t/1516/compiled_assets/snippet-scripts.js?v=66079492489357529931790192968"></script>
vendor: 1 bytes, line 7387
7387
7388<script id="shopify-cfh-end">window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.end');</script>
7388 7389 <!-- BEGIN app block: shopify://apps/black-crow-ai-that-delivers/blocks/blackcrow_ai_script/3e73f597-cb71-47a1-8a06-0c931482ecd2 --> 7390
7391<script type="text/javascript" async src="https://shopify-init.blackcrow.ai/js/core/bostonproper.js?shop=bostonproper.myshopify.com&tagSrc=ShopifyThemeAppExtension"></script>
7391 7392 7393 7394<!-- END app block --><!-- BEGIN app block: shopify://apps/pc97pbn58-opensend/blocks/opensend/019d6301-977a-74bc-a568-af824856dc19 -->
7395<script type='text/javascript'> 7396!function(s) { 7397 let o = s.createElement('script'), u = s.getElementsByTagName('script')[0]; 7398 o.src = 'https://cdn.aggle.net/oir/oir.min.js'; 7399 o.async = !0, o.setAttribute('oirtyp', '48b1feaa'), o.setAttribute('oirid', 'P7C25MF72'); 7400 u.parentNode.insertBefore(o, u); 7401}(document); 7402</script>
7402 7403
7404<script type='text/javascript'> 7405 { 7406 const cleanObj = (value) => { 7407 if (Array.isArray(value)) { 7408 const cleanedArray = value.map(cleanObj).filter((v) => v !== undefined); 7409 return cleanedArray.length ? cleanedArray : undefined; 7410 } 7411 if (value && typeof value === "object") { 7412 const cleanedObject = Object.entries(value).reduce((acc, [key, val]) => { 7413 const cleanedValue = cleanObj(val); 7414 if (cleanedValue !== undefined && cleanedValue !== null && cleanedValue !== "") { 7415 acc[key] = cleanedValue; 7416 } 7417 return acc; 7418 }, {}); 7419 return Object.keys(cleanedObject).length ? cleanedObject : undefined; 7420 } 7421 if (value === null || value === undefined || value === "") { 7422 return undefined; 7423 } 7424 return value; 7425 }; 7426 const getCustomer = () => ({ 7427 shopifyCustomerId: "", 7428 email: "", 7429 phone: "", 7430 first_name: null, 7431 last_name: null, 7432 lifetime_value: null, 7433 order_count: null, 7434 address: { 7435 street: null, 7436 city: null, 7437 state: null, 7438 stateCode: null, 7439 postalCode: "", 7440 country: "", 7441 province: "", 7442 countryCode: "", 7443 } 7444 }); 7445 7446 } 7447</script>
7447 7448 7449 7450<!-- END app block --><!-- BEGIN app block: shopify://apps/microsoft-clarity/blocks/brandAgents_js/31c3d126-8116-4b4a-8ba1-baeda7c4aeea --> 7451 7452 7453
7454<script type="text/javascript"> 7455 (function(d){ 7456 var s = d.createElement('script'); 7457 s.async = true; 7458 s.src = "https://adsagentclientafd-b7hqhjdrf3fpeqh2.b01.azurefd.net/frontendInjection.js"; 7459 var firstScript = d.getElementsByTagName('script')[0]; 7460 firstScript.parentNode.insertBefore(s, firstScript); 7461 })(document); 7462</script>
7462 7463 7464 7465 7466<!-- END app block --><!-- BEGIN app block: shopify://apps/yotpo-loyalty-rewards/blocks/loader-app-embed-block/2f9660df-5018-4e02-9868-ee1fb88d6ccd --> 7467
7467<script src="https://cdn-widgetsrepository.yotpo.com/v1/loader/K13MR0xh3osOG6J13_kFIw" async></script>
7467 7468 7469 7470 7471
7471<script src="https://cdn-loyalty.yotpo.com/loader/K13MR0xh3osOG6J13_kFIw.js?shop=www.bostonproper.com" async></script>
7471 7472 7473 7474<!-- END app block --><!-- BEGIN app block: shopify://apps/microsoft-clarity/blocks/clarity_js/31c3d126-8116-4b4a-8ba1-baeda7c4aeea -->
7475<script type="text/javascript"> 7476 (function (c, l, a, r, i, t, y) { 7477 c[a] = c[a] || function () { (c[a].q = c[a].q || []).push(arguments); }; 7478 t = l.createElement(r); t.async = 1; t.src = "https://www.clarity.ms/tag/" + i + "?ref=shopify"; 7479 y = l.getElementsByTagName(r)[0]; y.parentNode.insertBefore(t, y); 7480 7481 c.Shopify.loadFeatures([{ name: "consent-tracking-api", version: "0.1" }], error => { 7482 if (error) { 7483 console.error("Error loading Shopify features:", error); 7484 return; 7485 } 7486 7487 c[a]('consentv2', { 7488 ad_Storage: c.Shopify.customerPrivacy.marketingAllowed() ? "granted" : "denied", 7489 analytics_Storage: c.Shopify.customerPrivacy.analyticsProcessingAllowed() ? "granted" : "denied", 7490 source: 101, 7491 }); 7492 }); 7493 7494 l.addEventListener("visitorConsentCollected", function (e) { 7495 c[a]('consentv2', { 7496 ad_Storage: e.detail.marketingAllowed ? "granted" : "denied", 7497 analytics_Storage: e.detail.analyticsAllowed ? "granted" : "denied", 7498 source: 101, 7499 }); 7500 }); 7501 })(window, document, "clarity", "script", "v94zgzk99z"); 7502</script>
7502 7503 7504 7505 7506<!-- END app block --><!-- BEGIN app block: shopify://apps/klaviyo-email-marketing-sms/blocks/klaviyo-onsite-embed/2632fe16-c075-4321-a88b-50b567f42507 --> 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519
7519<script async src="https://static.klaviyo.com/onsite/js/VZrTML/klaviyo.js?company_id=VZrTML"></script>
7519 7520
7520<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>
7520 7521 7522 7523 7524 7525 7526 7527
7527<script> 7528 window.klaviyoReviewsProductDesignMode = false 7529 </script>
7529 7530 7531 7532 7533 <!-- BEGIN app snippet: customer-hub-data -->
7533<script> 7534 if (!window.customerHub) { 7535 window.customerHub = {}; 7536 } 7537 window.customerHub.storefrontRoutes = { 7538 login: "https://www.bostonproper.com/customer_authentication/redirect?locale=en®ion_country=US?return_url=%2F%23k-hub", 7539 register: "https://shopify.com/52960723110/account?locale=en&buyer_flags=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJib3N0b25wcm9wZXIubXlzaG9waWZ5LmNvbSIsImZsYWdzIjpbXSwiZXhwIjoxNzkwOTY2NzcwLCJuYmYiOjE3OTAzNjE5NzB9.T1sLJDK8iWrH3PmwMcI538Ixc5nGXnKf3jVul24n0dA?return_url=%2F%23k-hub", 7540 logout: "/account/logout", 7541 profile: "/account", 7542 addresses: "/account/addresses", 7543 }; 7544 7545 window.customerHub.userId = null; 7546 7547 window.customerHub.storeDomain = "bostonproper.myshopify.com"; 7548 7549 7550 7551 7552 window.customerHub.storeLocale = { 7553 currentLanguage: 'en', 7554 currentCountry: 'US', 7555 availableLanguages: [ 7556 7557 { 7558 iso_code: 'en', 7559 endonym_name: 'English' 7560 } 7561 7562 ], 7563 availableCountries: [ 7564 7565 { 7566 iso_code: 'CA', 7567 name: 'Canada', 7568 currency_code: 'CAD' 7569 }, 7570 7571 { 7572 iso_code: 'US', 7573 name: 'United States', 7574 currency_code: 'USD' 7575 } 7576 7577 ] 7578 }; 7579 7580</script>
7580 7581<!-- END app snippet --> 7582 7583 7584 7585 <!-- BEGIN app snippet: customer-hub-replace-links -->
7586<script> 7587 function replaceAccountLinks() { 7588 const selector = 7589 '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'; 7590 const accountLinksNodes = document.querySelectorAll(selector); 7591 for (const node of accountLinksNodes) { 7592 const ignore = node.dataset.kHubIgnore !== undefined && node.dataset.kHubIgnore !== 'false'; 7593 if (!ignore) { 7594 // Any login links to Shopify's account system, point them at the customer hub instead. 7595 node.href = '#k-hub'; 7596 /** 7597 * 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. 7598 * However, since clicking the k-hub link doesn't trigger a page load, the page gets stuck on a blank screen. 7599 * Luckily, these themes usually have a className you can add to links to skip the transition. 7600 * Let's hope that all such themes are consistent/copy each other and just proactively add those classNames when we replace the link. 7601 **/ 7602 node.classList.add('no-transition', 'js-no-transition'); 7603 } 7604 } 7605 } 7606 7607 7608 if (document.readyState === 'complete') { 7609 replaceAccountLinks(); 7610 } else { 7611 const controller = new AbortController(); 7612 document.addEventListener( 7613 'readystatechange', 7614 () => { 7615 replaceAccountLinks(); // try to replace links both during `interactive` state and `complete` state 7616 if (document.readyState === 'complete') { 7617 // readystatechange can fire with "complete" multiple times per page load, so make sure we're not duplicating effort 7618 // by removing the listener afterwards. 7619 controller.abort(); 7620 } 7621 }, 7622 { signal: controller.signal }, 7623 ); 7624 } 7625 7626</script>
7626 7627<!-- END app snippet --> 7628 7629 7630 7631 7632 7633<!-- END app block --><!-- BEGIN app block: shopify://apps/ab-tasty/blocks/abtasty-tag/50439cd8-89e0-4240-838a-2948c07c763d --> 7634 7635
7635<script 7636 type="text/javascript" 7637 src="https://try.abtasty.com/443033f8f050ee927ac9047efa5db622.js" 7638 ></script>
7638 7639 7640
7640<script type="text/javascript"> 7641 // This waits for all the external ressources (including ABTasty tag) to load before executing the callback function. 7642 window.addEventListener('load', function () { 7643 if(!window.ABTasty) { 7644 // AB Tasty tag is not loaded so exit. 7645 return 7646 } 7647 7648 if (window.ABTasty.eventState?.['consentValid']?.status === 'complete') { 7649 updateShopifyDataForWebPixel(); 7650 } else { 7651 window.addEventListener('abtasty_consentValid', () => { 7652 updateShopifyDataForWebPixel(); 7653 }); 7654 } 7655 7656 7657 async function waitForVisitorId(maxRetries = 5, delayMs = 500) { 7658 for (let i = 0; i < maxRetries; i++) { 7659 const visitorId = ABTasty.api.v1.getValue('visitorId') 7660 if (visitorId) { 7661 return visitorId; 7662 } 7663 await new Promise(resolve => setTimeout(resolve, delayMs)); 7664 } 7665 return null; 7666 } 7667 7668 7669 async function updateShopifyDataForWebPixel() { 7670 const STORAGE_KEY = 'ABTastyShopify'; 7671 const consentReady = ABTasty.consentReady; 7672 const shouldHandleSubdomain = "false" === "true"; 7673 7674 if(!consentReady) { 7675 if(shouldHandleSubdomain) { 7676 await cookieStore.delete(STORAGE_KEY); 7677 } 7678 return localStorage.removeItem(STORAGE_KEY); 7679 } 7680 7681 const visitorId = await waitForVisitorId(5, 500); 7682 7683 if (!visitorId) { 7684 console.error('[AB Tasty] Unable to get AB Tasty visitorID after 5 retry'); 7685 return; 7686 } 7687 7688 const ABTastyData = { 7689 identifier: "443033f8f050ee927ac9047efa5db622", 7690 campaigns: ABTasty.getCampaignHistory(), 7691 visitorId: visitorId, 7692 accountId: ABTasty.getAccountSettings().id, 7693 consent: ABTasty.consentReady, 7694 }; 7695 7696 if (shouldHandleSubdomain) { 7697 await cookieStore.set({ 7698 name: STORAGE_KEY, 7699 value: JSON.stringify(ABTastyData), 7700 expires: Date.now() + 1 * 24 * 60 * 60 * 1000, // 1 day 7701 domain: window.location.hostname, 7702 }); 7703 } 7704 localStorage.setItem(STORAGE_KEY, JSON.stringify(ABTastyData)); 7705 } 7706 }); 7707 </script>
7707 7708 7709 7710 7711 7712 7713<!-- END app block --><!-- BEGIN app block: shopify://apps/bloomreach-loomi/blocks/unified-tracking-script/019beafc-b2ba-790d-9ed1-850d869fc572 --> 7714 7715 7716 7717 7718 7719 7720 7721 7722 <!-- BEGIN app snippet: bloomreach-analytics-publish -->
7722<script> 7723 /** 7724 * Publishes an event to Shopify.analytics with retry logic. 7725 * Waits for Shopify.analytics to become available before publishing. 7726 * 7727 * @param {string} eventName - The name of the event to publish 7728 * @param {object} eventData - The data payload for the event 7729 */ 7730 window.bloomreachPublishEvent = function(eventName, eventData) { 7731 const maxAttempts = 100; // Max 10 seconds (100 * 100ms) 7732 let attempts = 0; 7733 7734 function tryPublish() { 7735 if (typeof Shopify !== "undefined" && Shopify.analytics && typeof Shopify.analytics.publish === "function") { 7736 Shopify.analytics.publish(eventName, eventData); 7737 } else if (attempts < maxAttempts) { 7738 attempts++; 7739 setTimeout(tryPublish, 100); 7740 } else { 7741 console.error('[Bloomreach Unified Tracking] Shopify.analytics object is not available'); 7742 } 7743 } 7744 tryPublish(); 7745 }; 7746</script>
7746 7747<!-- END app snippet --> 7748 <!-- BEGIN app snippet: bloomreach-consent-gate -->
7748<script> 7749 (function() { 7750 const LOG_PREFIX = '[Bloomreach Unified Tracking]'; 7751 const POLL_INTERVAL_MS = 100; 7752 const MAX_POLL_ATTEMPTS = 100; 7753 let trackingInitialized = false; 7754 let consentListenerRegistered = false; 7755 7756 function isBloomreachTrackingConsentGranted() { 7757 const privacy = window.Shopify && window.Shopify.customerPrivacy; 7758 if (!privacy) { 7759 return false; 7760 } 7761 return typeof privacy.analyticsProcessingAllowed === 'function' 7762 && typeof privacy.marketingAllowed === 'function' 7763 && typeof privacy.saleOfDataAllowed === 'function' 7764 && privacy.analyticsProcessingAllowed() 7765 && privacy.marketingAllowed() 7766 && privacy.saleOfDataAllowed(); 7767 } 7768 7769 function waitForCustomerPrivacy(onReady, onTimeout) { 7770 let attempts = 0; 7771 7772 function tryLoadPrivacyApi() { 7773 if (typeof window.Shopify === 'undefined' 7774 || typeof window.Shopify.loadFeatures !== 'function') { 7775 if (attempts < MAX_POLL_ATTEMPTS) { 7776 attempts++; 7777 setTimeout(tryLoadPrivacyApi, POLL_INTERVAL_MS); 7778 return; 7779 } 7780 if (onTimeout) { 7781 onTimeout(); 7782 } 7783 return; 7784 } 7785 7786 window.Shopify.loadFeatures( 7787 [{ name: 'consent-tracking-api', version: '0.1' }], 7788 function(error) { 7789 if (error) { 7790 if (onTimeout) { 7791 onTimeout(); 7792 } 7793 return; 7794 } 7795 onReady(); 7796 }, 7797 ); 7798 } 7799 7800 tryLoadPrivacyApi(); 7801 } 7802 7803 function tryInitialize(initializeFn, config) { 7804 if (trackingInitialized) { 7805 return; 7806 } 7807 if (!isBloomreachTrackingConsentGranted()) { 7808 return; 7809 } 7810 if (typeof window.initializeDiscoveryCookie === 'function') { 7811 window.initializeDiscoveryCookie(); 7812 } 7813 trackingInitialized = true; 7814 initializeFn(config); 7815 } 7816 7817 window.runWhenBloomreachTrackingAllowed = function(startFn, config, loadFn) { 7818 if (typeof loadFn === 'function') { 7819 loadFn(config); 7820 } 7821 7822 function onPrivacyApiReady() { 7823 tryInitialize(startFn, config); 7824 7825 if (!consentListenerRegistered) { 7826 consentListenerRegistered = true; 7827 document.addEventListener('visitorConsentCollected', function() { 7828 tryInitialize(startFn, config); 7829 }); 7830 } 7831 } 7832 7833 function onPrivacyApiUnavailable() { 7834 console.error(LOG_PREFIX + ' Customer Privacy API unavailable'); 7835 } 7836 7837 waitForCustomerPrivacy(onPrivacyApiReady, onPrivacyApiUnavailable); 7838 }; 7839 })(); 7840</script>
7840 7841<!-- END app snippet -->
7842<script> 7843 window.bloomreachPublishEvent("bre.domain_key", { 7844 domain_key: "bostonproper" 7845 }); 7846 </script>
7846<script> 7847 // Publish localization data to the web pixel extension 7848 window.bloomreachPublishEvent("bre.localization", { 7849 country: "US", 7850 language: "en" 7851 }); 7852 7853 7854 window.bloomreachPublishEvent("bre.feature_flags", {}); 7855 window.bloomreachPublishEvent("bre.discovery_config", { 7856 test_data: false, 7857 debug: false 7858 }); 7859 </script>
7859 7860 7861 7862 7863 7864 <!-- BEGIN app snippet: bloomreach-br-uid-2-cookie -->
7864<script> 7865 (function() { 7866 const BR_UID_2_COOKIE_NAME = '_br_uid_2'; 7867 const BR_UID_2_VERSION = 'app'; 7868 const BR_UID_2_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 365 * 2; 7869 7870 function decodeBrUid2CookieValue(value) { 7871 try { 7872 return decodeURIComponent(value); 7873 } catch (error) { 7874 return value; 7875 } 7876 } 7877 7878 function generateBrUid2Uid() { 7879 return String(Math.round(Math.random() * 10e12)); 7880 } 7881 7882 function formatBrUid2CookieValue(uid, version, timestamp, hitCount) { 7883 return 'uid=' + uid + ':v=' + version + ':ts=' + timestamp + ':hc=' + hitCount; 7884 } 7885 7886 function generateBrUid2CookieValue(hitCount) { 7887 return formatBrUid2CookieValue( 7888 generateBrUid2Uid(), 7889 BR_UID_2_VERSION, 7890 Date.now(), 7891 hitCount 7892 ); 7893 } 7894 7895 function parseBrUid2CookieValue(value) { 7896 const segments = decodeBrUid2CookieValue(value).split(':'); 7897 let uid; 7898 let version; 7899 let timestamp; 7900 let hitCount; 7901 7902 for (let i = 0; i < segments.length; i++) { 7903 const segment = segments[i]; 7904 if (segment.indexOf('uid=') === 0) { 7905 uid = segment.slice(4); 7906 } else if (segment.indexOf('v=') === 0) { 7907 version = segment.slice(2); 7908 } else if (segment.indexOf('ts=') === 0) { 7909 timestamp = parseInt(segment.slice(3), 10); 7910 } else if (segment.indexOf('hc=') === 0) { 7911 hitCount = parseInt(segment.slice(3), 10); 7912 } 7913 } 7914 7915 if (!uid || !version || isNaN(timestamp) || isNaN(hitCount) || hitCount < 0) { 7916 return null; 7917 } 7918 7919 return { 7920 uid: uid, 7921 version: version, 7922 timestamp: timestamp, 7923 hitCount: hitCount 7924 }; 7925 } 7926 7927 function getBrUid2CookieValue() { 7928 const cookiePrefix = BR_UID_2_COOKIE_NAME + '='; 7929 const cookies = document.cookie.split('; '); 7930 7931 for (let i = 0; i < cookies.length; i++) { 7932 if (cookies[i].indexOf(cookiePrefix) === 0) { 7933 return decodeBrUid2CookieValue(cookies[i].substring(cookiePrefix.length)); 7934 } 7935 } 7936 7937 return null; 7938 } 7939 7940 function getBaseDomain(host) { 7941 if (!host) { 7942 return ''; 7943 } 7944 const parts = host.split('.'); 7945 const length = parts.length; 7946 7947 // Handle cases like 'localhost', 'example.com', '192.168.1.1' 7948 if (length <= 2 || /^\d+\.\d+\.\d+\.\d+$/.test(host)) { 7949 return host; 7950 } 7951 7952 return parts[length - 1].length <= 2 && parts[length - 2].length <= 3 7953 ? parts.slice(-3).join('.') 7954 : parts.slice(-2).join('.'); 7955 } 7956 7957 function buildBrUid2CookieString(value, domain) { 7958 const cookieParts = [ 7959 BR_UID_2_COOKIE_NAME + '=' + encodeURIComponent(value), 7960 'path=/', 7961 'max-age=' + BR_UID_2_COOKIE_MAX_AGE_SECONDS, 7962 'SameSite=Lax' 7963 ]; 7964 7965 if (domain) { 7966 cookieParts.push('domain=' + domain); 7967 } 7968 7969 return cookieParts.join('; '); 7970 } 7971 7972 function setBrUid2CookieValue(value) { 7973 const baseDomain = getBaseDomain(location.hostname); 7974 7975 document.cookie = buildBrUid2CookieString(value, baseDomain); 7976 7977 if (getBrUid2CookieValue() !== value) { 7978 document.cookie = buildBrUid2CookieString(value, null); 7979 } 7980 } 7981 7982 function ensureBrUid2Cookie() { 7983 const existingValue = getBrUid2CookieValue(); 7984 7985 if (existingValue) { 7986 const parsed = parseBrUid2CookieValue(existingValue); 7987 if (parsed) { 7988 return existingValue; 7989 } 7990 } 7991 7992 const createdValue = generateBrUid2CookieValue(1); 7993 setBrUid2CookieValue(createdValue); 7994 return createdValue; 7995 } 7996 7997 window.initializeDiscoveryCookie = function() { 7998 const discoveryCookie = ensureBrUid2Cookie(); 7999 if (typeof window.bloomreachPublishEvent === 'function') { 8000 window.bloomreachPublishEvent('bre.discovery_cookie', { cookie: discoveryCookie }); 8001 } 8002 }; 8003 })(); 8004</script>
8004 8005<!-- END app snippet --> 8006 8007 8008 8009
8009<script> 8010 const trackingConfig = { 8011 brweb: { 8012 target: "https:\/\/us3-api.eng.bloomreach.com", 8013 stream_id: "d042b089-6e20-44b6-82b8-7bd75742c4a8", 8014 data_layer: true, 8015 8016 track: { 8017 default_properties: { 8018 customer_locale: "en-US" 8019 } 8020 8021 }, 8022 customConfigRaw: "" 8023 }, 8024 customer: { 8025 8026 }, 8027 metadata: { 8028 domain_key: "bostonproper" 8029 8030 8031 }, 8032 deferredEvents: [ 8033 8034 8035 ] 8036 }; 8037 8038 function buildBrwebInitConfig(config) { 8039 const brwebBaseConfig = Object.assign({}, config.brweb); 8040 const customConfigRaw = brwebBaseConfig.customConfigRaw; 8041 delete brwebBaseConfig.customConfigRaw; 8042 8043 let customConfigOverrides = {}; 8044 try { 8045 if (customConfigRaw && customConfigRaw.trim() !== '') { 8046 customConfigOverrides = JSON.parse(customConfigRaw); 8047 } 8048 } catch (e) { 8049 console.error('[Bloomreach Unified Tracking] Invalid JSON in Custom Configuration, ignoring: ' + e.message); 8050 } 8051 8052 return Object.assign({}, brwebBaseConfig, customConfigOverrides); 8053 } 8054 8055 function loadBloomreachSdk(config) { 8056 const brwebInitConfig = buildBrwebInitConfig(config); 8057 8058 !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<new 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
8058h((e=>n[e]=i[e])),e[t].initialize(n)}}(o,t,r)}(document,"brweb","script","webxpClient",window, brwebInitConfig); 8059 8060 window.exponea = brweb; 8061 } 8062 8063 function startBloomreachTracking(config) { 8064 window.dataLayer = window.dataLayer || []; 8065 8066 function subscribeCookieListener(dataLayer) { 8067 dataLayer.forEach(processDatalayerEvent); 8068 8069 const originalPush = dataLayer.push; 8070 dataLayer.push = function() { 8071 originalPush.apply(dataLayer, arguments); 8072 Array.from(arguments).forEach(processDatalayerEvent); 8073 }; 8074 } 8075 8076 function processDatalayerEvent(event) { 8077 if (event.event === "bre.cookie") { 8078 Shopify.analytics.publish("bre.cookie", event); 8079 } 8080 } 8081 8082 subscribeCookieListener(window.dataLayer); 8083 8084 function getCookie(cname) { 8085 var name = cname + "="; 8086 var ca = document.cookie.split(';'); 8087 var cookie = undefined; 8088 for (var i = 0; i < ca.length; i++) { 8089 var c = ca[i]; 8090 while (c.charAt(0) == ' ') { 8091 c = c.substring(1); 8092 } 8093 if (c.indexOf(name) == 0) { 8094 cookie = c.substring(name.length, c.length); 8095 break; 8096 } 8097 } 8098 cookie = decodeURIComponent(cookie); 8099 cookie = cookie.split('?')[0]; 8100 return cookie; 8101 } 8102 8103 var customer = Object.assign({}, config.customer); 8104 var cart_id = getCookie('cart'); 8105 if (cart_id) customer.cart_id = cart_id; 8106 8107 exponea.start({ 8108 customer: customer 8109 }); 8110 8111 if (config.metadata) { 8112 exponea.metadata(config.metadata); 8113 } 8114 8115 /** 8116 * Quick View Tracking 8117 * Listens for clicks on native Shopify quick-add-component elements. 8118 * Only tracks when clicking a button[type="button"] (opens modal). 8119 * Ignores button[type="submit"] (direct add to cart). 8120 */ 8121 (function() { 8122 document.addEventListener('click', function(event) { 8123 const quickAddComponent = event.target.closest('quick-add-component'); 8124 if (!quickAddComponent) return; 8125 8126 const clickedButton = event.target.closest('button'); 8127 if (!clickedButton || clickedButton.type !== 'button') return; 8128 8129 const productForm = quickAddComponent.querySelector('product-form-component'); 8130 const productId = productForm?.getAttribute('data-product-id'); 8131 if (!productId) return; 8132 8133 const variantInput = quickAddComponent.querySelector('input[name="id"]'); 8134 window.bloomreachPublishEvent('bre.quick_view', { 8135 product_id: productId, 8136 title: quickAddComponent.getAttribute('data-product-title') || '', 8137 variant_id: variantInput?.value || '' 8138 }); 8139 }); 8140 })(); 8141 8142 config.deferredEvents.forEach(function(event) { 8143 window.bloomreachPublishEvent(event.name, event.data); 8144 }); 8145 } 8146 8147 runWhenBloomreachTrackingAllowed(startBloomreachTracking, trackingConfig, loadBloomreachSdk); 8148 </script>
8148 8149 8150<!-- END app block --><link href="https://monorail-edge.shopifysvc.com" rel="dns-prefetch">
8151<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: "blog"};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 8151
8151
8152<script> 8153 window.__TREKKIE_SHIM_QUEUE = window.__TREKKIE_SHIM_QUEUE || []; 8154</script>
vendor: 1 bytes, line 8154
8154
8155<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}
8155).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: ["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":"281f5176d59c18052a7f231c2196b454","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"]}
8155,"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":"59063c86dca90ebaa562063a0c13be50","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":[]},"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"]}
8155,"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"}
8155,{"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":[],"products":[{"id":"15399681392806","handle":"leopard-print-skirt-brown-multi","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56779671077030","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15399681360038","handle":"metallic-zebra-printed-dress-tan-multi","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56779670782118","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15366923452582","handle":"mock-neck-intarsia-flare-sleeve-tunic-west-side-paisley","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56658234933414","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15336227864742","handle":"knit-suede-drape-front-jacket-stone","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56545549123750","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15336227831974","handle":"knit-suede-drape-front-jacket-blue","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56545548927142","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15325066035366","handle":"modern-capri-trouser-sesame","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56510704353446","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15323390738598","handle":"modern-single-button-blazer-sesame","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56505725419686","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15321518801062","handle":"ultimate-ponte-crest-button-capri-black","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56499190923430","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15321518768294","handle":"denim-capri-medium-wash","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56499190595750","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]}
8155,{"id":"15321518702758","handle":"boston-proper-best-era-yet-t-shirt-pure-white","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56499190202534","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15300355555494","handle":"printed-woven-back-denim-jacket-cheetah-gems","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56437744271526","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15298631631014","handle":"essential-printed-cami-tiny-midnight-dot","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56433081155750","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15298631598246","handle":"print-handkerchief-hem-dress-cheetah-gems","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56433080959142","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15292963324070","handle":"printed-lurex-lace-up-tunic-golden-status","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56404613333158","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15288328126630","handle":"pickletini-x-boston-proper-amelia-zip-skort-charcoal-pink","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56393535848614","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15288328028326","handle":"pickletini-x-boston-proper-tricia-zip-sweater-blushing-pink","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56393535324326","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15288328093862","handle":"pickletini-x-boston-proper-lucia-bk-pleated-skort-blushing-pink","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56393535684774","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15288327995558","handle":"pickletini-x-boston-proper-tricia-zip-sweater-charcoal","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56393535160486","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15288327962790","handle":"pickletini-x-boston-proper-angie-mid-top-pink-green-multi","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56393534996646","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15288327930022","handle":"pickletini-x-boston-proper-lily-trim-dress-pink-green-multi","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56393534832806","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15288327897254","handle":"pickletini-x-boston-proper-ada-legging-pink-green-multi","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56393534668966","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15288327864486","handle":"pickletini-x-boston-proper-willow-cross-over-bra-pink-green-multi","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56393534505126","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]}
8155,{"id":"15288327831718","handle":"pickletini-x-boston-proper-carti-skort-pink-green-multi","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56393534341286","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15287636263078","handle":"long-layered-pearl-choker-necklace-white","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56391350517926","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15283310133414","handle":"boston-proper-logo-drawstring-bag-off-white-black","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56363332632742","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15279958425766","handle":"printed-maxi-slip-dress-chic-cheetah","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56349968203942","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15278453457062","handle":"faux-leather-belted-high-neck-dress-proper-black","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56344418123942","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15278453424294","handle":"sophia-button-up-charmeuse-blouse-windsor-wine","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56344417796262","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15276327010470","handle":"puff-sleeve-marled-cardigan-gold-multi","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56338751193254","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15275804360870","handle":"fringe-chain-detail-handbag-black","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56336898490534","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15275804328102","handle":"brushed-twill-long-sleeve-shirt-jacket-hazelnut","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56336898293926","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15275804295334","handle":"crepe-mixed-media-embellished-jacket-thrush","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56336898097318","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15274612228262","handle":"all-over-beaded-square-neck-sheath-dress-blue","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56330008101030","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15274612195494","handle":"denim-ruched-cap-sleeve-shirt-dark-rinse","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56330007904422","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15272525234342","handle":"stone-statement-belt-cognac","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56321623031974","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15272525201574","handle":"gold-detail-buckle-belt-black","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56321622868134","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]}
8155,{"id":"15272525168806","handle":"gold-detail-buckle-belt-olive-night","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56321622704294","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15270286557350","handle":"victoria-charmeuse-chic-drama-sleeve-shirt-gray","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56312120967334","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15269635457190","handle":"pearl-cord-wrap-necklace-brown-white","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56309765832870","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15269635391654","handle":"fringe-statement-necklace-gold-black","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56309765767334","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15269635326118","handle":"lightweight-v-neck-knot-front-sweater-proper-black","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56309765537958","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15269635293350","handle":"beyond-travel-tailored-single-button-blazer-maritime-navy","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56309765210278","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15269635260582","handle":"newport-modern-slim-straight-side-slit-trouser-pant-italian-plum","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56309764882598","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15269635227814","handle":"newport-modern-slim-straight-side-slit-trouser-pant-hunt-club","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56309764522150","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15269635162278","handle":"sophia-button-up-charmeuse-blouse-hunt-club","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56309764161702","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15269036130470","handle":"long-sleeve-crew-neck-t-shirt-airy-blue","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56304376316070","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15269036032166","handle":"hardware-trimmed-double-breasted-modern-blazer-hunt-club","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56304375922854","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15269035966630","handle":"hardware-trimmed-double-breasted-modern-blazer-italian-plum","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56304375562406","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15269035901094","handle":"faux-leather-strapless-top-proper-black","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56304375333030","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"15269035671718","handle":"lace-scoop-neck-tank-top-italian-plum","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"56304374612134","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"7934066655398","handle":"modern-single-button-blazer-aurora-pink","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"44817063477414","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"8088818843814","handle":"modern-single-button-blazer-blithe-blue","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"45236215185574","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"8258498035878","handle":"modern-single-button-blazer-dark-purple","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"45688821481638","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"8088819105958","handle":"modern-single-button-blazer-ivory","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"45236217184422","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]},{"id":"8529230004390","handle":"narvardeliveryprotection","isCollective":false,"title":null,"type":null,"untranslatedTitle":null,"url":null,"vendor":null,"remoteShopId":null,"variants":[{"id":"46514716934310","image":null,"price":null,"sku":null,"title":null,"untranslatedTitle":null}]}],"purchasingCompany":null},},"https://www.bostonproper.com/cdn","c8540278we853e1abpb62b2c4amde256306",{"modern":"","legacy":""},{"trekkieShim":true,"agentContext":true,"apiClientId":"580111","facebookCapiEnabled":"false","themeId":"197929926822","themePublished":"true","eventMetadataId":"2caeec34-dd68-4a2e-86c9-18d7ed179576","pageType":"blog","resourceId":"82989514918","shopId":"52960723110","storefrontBaseUrl":"https:\/\/www.bostonproper.com","extensionBaseUrl":"https:\/\/extensions.shopifycdn.com\/cdn\/shopifycloud\/web-pixels-manager","surface":"storefront-renderer","enabledBetaFlags":"[\"16072cab\", \"8450a54b\", \"7ee89bf1\"]","isMerchantRequest":"false","hashVersion":"c8540278we853e1abpb62b2c4amde256306","publish":"custom","events":"[[\"page_viewed\",{}]]"});})();</script>
8155<script> 8156 window.ShopifyAnalytics = window.ShopifyAnalytics || {}; 8157 window.ShopifyAnalytics.meta = window.ShopifyAnalytics.meta || {}; 8158 window.ShopifyAnalytics.meta.currency = 'USD'; 8159 var meta = {"page":{"pageType":"blog","resourceType":"blog","resourceId":82989514918,"requestId":"c9758f03-eb56-425e-8c7b-c1be7ef20e39-1790361970"}}; 8160 for (var attr in meta) { 8161 window.ShopifyAnalytics.meta[attr] = meta[attr]; 8162 } 8163</script>
vendor: 1 bytes, line 8163
8163
8164<script class="analytics"> 8165 (function () { 8166 var customDocumentWrite = function(content) { 8167 var jquery = null; 8168 8169 if (window.jQuery) { 8170 jquery = window.jQuery; 8171 } else if (window.Checkout && window.Checkout.$) { 8172 jquery = window.Checkout.$; 8173 } 8174 8175 if (jquery) { 8176 jquery('body').append(content); 8177 } 8178 }; 8179 8180 var hasLoggedConversion = function(token) { 8181 if (token) { 8182 return document.cookie.indexOf('loggedConversion=' + token) !== -1; 8183 } 8184 return false; 8185 } 8186 8187 var setCookieIfConversion = function(token) { 8188 if (token) { 8189 var twoMonthsFromNow = new Date(Date.now()); 8190 twoMonthsFromNow.setMonth(twoMonthsFromNow.getMonth() + 2); 8191 8192 document.cookie = 'loggedConversion=' + token + '; expires=' + twoMonthsFromNow; 8193 } 8194 } 8195 8196 var trekkie = window.ShopifyAnalytics.lib = window.trekkie = window.trekkie || []; 8197 window.ShopifyAnalytics.lib.trekkie = window.trekkie; 8198 if (trekkie.integrations) { 8199 return; 8200 } 8201 trekkie.methods = [ 8202 'identify', 8203 'page', 8204 'ready', 8205 'track', 8206 'trackForm', 8207 'trackLink' 8208 ]; 8209 trekkie.factory = function(method) { 8210 return function() { 8211 var args = Array.prototype.slice.call(arguments); 8212 args.unshift(method); 8213 trekkie.push(args); 8214 if (method == 'track' || method == 'page') { 8215 var pageUrl; 8216 try { 8217 pageUrl = window.location.href; 8218 } catch (e) {} 8219 var pageReferrer; 8220 try { 8221 pageReferrer = document.referrer; 8222 } catch (e) {} 8223 try { 8224 if (window.__TREKKIE_SHIM_QUEUE == null) { 8225 window.__TREKKIE_SHIM_QUEUE = []; 8226 } 8227 window.__TREKKIE_SHIM_QUEUE.push({ 8228 from: 'trekkie-stub', 8229 method: method, 8230 args: args.slice(1), 8231 pageContext: { 8232 url: pageUrl, 8233 referrer: pageReferrer 8234 } 8235 }); 8236 } catch (e) { 8237 // no-op 8238 } 8239 } 8240 return trekkie; 8241 }; 8242 }; 8243 for (var i = 0; i < trekkie.methods.length; i++) { 8244 var key = trekkie.methods[i]; 8245 trekkie[key] = trekkie.factory(key); 8246 } 8247 trekkie.load = function(config) { 8248 trekkie.config = config || {}; 8249 trekkie.config.initialDocumentCookie = document.cookie; 8250 var first = document.getElementsByTagName('script')[0]; 8251var script = document.createElement('script'); 8252script.type = 'text/javascript'; 8253script.onerror = function(e) { 8254 var scriptFallback = document.createElement('script'); 8255 scriptFallback.type = 'text/javascript'; 8256 scriptFallback.onerror = function(error) { 8257 var Monorail = { 8258 produce: function produce(monorailDomain, schemaId, payload) { 8259 var currentMs = new Date().getTime(); 8260 var event = { 8261 schema_id: schemaId, 8262 payload: payload, 8263 metadata: { 8264 event_created_at_ms: currentMs, 8265 event_sent_at_ms: currentMs 8266 } 8267 }; 8268 return Monorail.sendRequest("https://" + monorailDomain + "/v1/produce", JSON.stringify(event)); 8269 }, 8270 sendRequest: function sendRequest(endpointUrl, payload) { 8271 // Try the sendBeacon API 8272 if (window && window.navigator && typeof window.navigator.sendBeacon === 'function' && typeof window.Blob === 'function' && !Monorail.isIos12()) { 8273 var blobData = new window.Blob([payload], { 8274 type: 'text/plain' 8275 }); 8276 8277 if (window.navigator.sendBeacon(endpointUrl, blobData)) { 8278 return true; 8279 } // sendBeacon was not successful 8280 8281 } // XHR beacon 8282 8283 var xhr = new XMLHttpRequest(); 8284 8285 try { 8286 xhr.open('POST', endpointUrl); 8287 xhr.setRequestHeader('Content-Type', 'text/plain'); 8288 xhr.send(payload); 8289 } catch (e) { 8290 console.log(e); 8291 } 8292 8293 return false; 8294 }, 8295 isIos12: function isIos12() { 8296 return window.navigator.userAgent.lastIndexOf('iPhone; CPU iPhone OS 12_') !== -1 || window.navigator.userAgent.lastIndexOf('iPad; CPU OS 12_') !== -1; 8297 } 8298 }; 8299 Monorail.produce('monorail-edge.shopifysvc.com', 8300 'trekkie_storefront_load_errors/1.1', 8301 {shop_id: 52960723110, 8302 theme_id: 197929926822, 8303 app_name: "storefront", 8304 context_url: window.location.href, 8305 source_url: "//www.bostonproper.com/cdn/s/trekkie.storefront.f1ba865b3fecd812ad617f74ac079261075e9edb.min.js"}); 8306 8307 }; 8308 scriptFallback.async = true; 8309 scriptFallback.src = '//www.bostonproper.com/cdn/s/trekkie.storefront.f1ba865b3fecd812ad617f74ac079261075e9edb.min.js'; 8310 first.parentNode.insertBefore(scriptFallback, first); 8311}; 8312script.async = true; 8313script.src = '//www.bostonproper.com/cdn/s/trekkie.storefront.f1ba865b3fecd812ad617f74ac079261075e9edb.min.js'; 8314first.parentNode.insertBefore(script, first); 8315 8316 }; 8317 trekkie.load( 8318 {"Trekkie":{"appName":"storefront","development":false,"defaultAttributes":{"shopId":52960723110,"isMerchantRequest":null,"themeId":197929926822,"themeCityHash":"10505968396793769995","contentLanguage":"en","currency":"USD","eventMetadataId":"2caeec34-dd68-4a2e-86c9-18d7ed179576"},"isServerSideCookieWritingEnabled":true,"monorailRegion":"shop_domain","enabledBetaFlags":["764d78cb","8450a54b","7ee89bf1"]},"Session Attribution":{},"S2S":{"facebookCapiEnabled":false,"source":"trekkie-storefront-renderer","apiClientId":580111}} 8319 ); 8320 8321 var loaded = false;
8322 trekkie.ready(function() { 8323 if (loaded) return; 8324 loaded = true; 8325 8326 window.ShopifyAnalytics.lib = window.trekkie; 8327 8328 var originalDocumentWrite = document.write; 8329 document.write = customDocumentWrite; 8330 try { window.ShopifyAnalytics.merchantGoogleAnalytics.call(this); } catch(error) {}; 8331 document.write = originalDocumentWrite; 8332 8333 var match = window.location.pathname.match(/checkouts\/(.+)\/(thank_you|post_purchase)/) 8334 var token = match? match[1]: undefined; 8335 if (!hasLoggedConversion(token)) { 8336 setCookieIfConversion(token); 8337 8338 } 8339 }); 8340 8341 window.ShopifyAnalytics.lib.page(null,{"pageType":"blog","resourceType":"blog","resourceId":82989514918,"requestId":"c9758f03-eb56-425e-8c7b-c1be7ef20e39-1790361970","shopifyEmitted":true}); 8342 8343 var eventsListenerScript = document.createElement('script'); 8344 eventsListenerScript.async = true; 8345 eventsListenerScript.src = "//www.bostonproper.com/cdn/shopifycloud/storefront/assets/shop_events_listener-4e26a9ce.js"; 8346 document.getElementsByTagName('head')[0].appendChild(eventsListenerScript); 8347})();</script>
vendor: 1 bytes, line 8347
8347
8348<script 8349 defer 8350 src="https://www.bostonproper.com/cdn/shopifycloud/perf-kit/shopify-perf-kit-3.9.4.min.js" 8351 data-application="storefront-renderer" 8352 data-shop-id="52960723110" 8353 data-render-region="gcp-us-central1" 8354 data-page-type="blog" 8355 data-theme-instance-id="197929926822" 8356 data-theme-name="Horizon" 8357 data-theme-version="3.5.0" 8358 data-monorail-region="shop_domain" 8359 data-resource-timing-sampling-rate="10" 8360 data-shs="true" 8361 data-shs-beacon="true" 8362 data-shs-export-with-fetch="true" 8363 data-shs-logs-sample-rate="1" 8364 data-shs-beacon-endpoint="https://www.bostonproper.com/api/collect" 8365></script>
vendor: 1 bytes, line 8365
8365
8366<script src="https://cdn.shopify.com/storefront/web-components/account.js" type="module" crossorigin fetchpriority="low" async></script>
8366<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>
8366 8367<meta name="shopify-y" content="e743c6e4-1640-4408-b4f7-c7b5adf3dabc" data-expiration="1821919570000"><meta name="shopify-s" content="bacc6f19-9aa8-450c-b11d-814cc1a68b36" data-expiration="1790363770000"><meta name="new-cookie-storage-activated" content="t"> 8368</head> 8369 8370 <body class="page-width-narrow card-hover-effect-none"><noscript> 8371 <iframe 8372 src="https://sst.bostonproper.com/ns.html?id=GTM-NS3X79G>m_auth=288FkNoOr_QXQEJ-WPHnww>m_preview=env-1>m_cookies_win=x" 8373 height="0" 8374 width="0" 8375 style="display:none;visibility:hidden" 8376 ></iframe> 8377 </noscript><a 8378 class="skip-to-content-link button-secondary" 8379 href="#MainContent" 8380> 8381 Skip to content 8382</a> 8383 8384 8385 8386 <div id="header-group"> 8387 <!-- BEGIN sections: header-group --> 8388<div id="shopify-section-sections--29508264624294__header_announcements_9jGBFp" class="shopify-section shopify-section-group-header-group"> 8389 8390 8391
8391<script 8392 src="//www.bostonproper.com/cdn/shop/t/1516/assets/announcement-bar.js?v=171930887109884936311790192965" 8393 type="module" 8394 fetchpriority="low" 8395 ></script>
8395 8396 8397 8398<div class="section-background color-scheme-3"></div> 8399<aside 8400 class="announcement-bar spacing-style section section--page-width color-scheme-3" 8401 style="--padding-block-start: 15px; --padding-block-end:15px; 8402--padding-inline-start:0px; --padding-inline-end:0px; 8403; --border-bottom-width: 0px;" 8404> 8405 8406 8407 <announcement-bar-component 8408 class="announcement-bar__slider" 8409 8410 autoplay="5" aria-live="polite" 8411 8412 > 8413 8414 <slideshow-arrows 8415 position="center" 8416 8417><button 8418 class=" 8419 slideshow-control slideshow-control--previous 8420 8421 8422 slideshow-control--style-chevron 8423 button button-unstyled button-unstyled--transparent 8424 flip-x 8425 " 8426 8427 aria-label="Previous slide" 8428 8429 on:click="/previous" 8430 ref="previous" 8431> 8432 <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"> 8433 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8434</svg> 8435</span> 8436</button> 8437 8438 8439<button 8440 class=" 8441 slideshow-control slideshow-control--next 8442 8443 8444 slideshow-control--style-chevron 8445 button button-unstyled button-unstyled--transparent 8446 8447 " 8448 8449 aria-label="Next slide" 8450 8451 on:click="/next" 8452 ref="next" 8453> 8454 <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"> 8455 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8456</svg> 8457</span> 8458</button> 8459 8460 8461</slideshow-arrows> 8462 8463 8464 8465 8466 8467 <div class="announcement-bar__slides"> 8468 8469<slideshow-slide 8470 ref="slides[]" 8471 class=" 8472 announcement-bar__slide 8473 text-block 8474 text-block--ATFhPVXNtNnN3VGt2Z__announcement_ahaFK3 8475 text-block--align-center 8476 text-block--full-width 8477 custom-typography 8478 custom-font-size 8479 8480 " 8481 style=" 8482 8483--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); 8484 --width: 100%; 8485 --text-align: center; 8486 --line-height: 1; 8487 " 8488 8489 aria-hidden="false" 8490 > 8491 <p class="announcement-bar__text"> 8492 Up to 35% Off Wear-Now Styles | Shop 8493 </p> 8494 8495 8496 <a 8497 class="announcement-bar__link" 8498 href="/collections/the-right-now-edit" 8499 > 8500 <span class="visually-hidden"> 8501 Up to 35% Off Wear-Now Styles | Shop 8502 </span> 8503 </a> 8504 8505 </slideshow-slide> 8506 8507 8508 8509<slideshow-slide 8510 ref="slides[]" 8511 class=" 8512 announcement-bar__slide 8513 text-block 8514 text-block--AQTQ2cENRU28ySm1xT__announcement_qWUVy4 8515 text-block--align-center 8516 text-block--full-width 8517 custom-typography 8518 custom-font-size 8519 8520 " 8521 style=" 8522 8523--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); 8524 --width: 100%; 8525 --text-align: center; 8526 --line-height: 1; 8527 " 8528 8529 aria-hidden="true"inert 8530 > 8531 <p class="announcement-bar__text"> 8532 Plus, Free Shipping On All Orders | Code: FREESHIP 8533 </p> 8534 8535 8536 <a 8537 class="announcement-bar__link" 8538 href="/collections/new-arrivals" 8539 > 8540 <span class="visually-hidden"> 8541 Plus, Free Shipping On All Orders | Code: FREESHIP 8542 </span> 8543 </a> 8544 8545 </slideshow-slide> 8546 8547 8548 8549<slideshow-slide 8550 ref="slides[]" 8551 class=" 8552 announcement-bar__slide 8553 text-block 8554 text-block--AbWpSZlh6WUlrbm9aM__announcement_WUEBFr 8555 text-block--align-center 8556 text-block--full-width 8557 custom-typography 8558 custom-font-size 8559 8560 " 8561 style=" 8562 8563--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); 8564 --width: 100%; 8565 --text-align: center; 8566 --line-height: 1; 8567 " 8568 8569 aria-hidden="true"inert 8570 > 8571 <p class="announcement-bar__text"> 8572 Extra 30% Off Clearance | Code: EXTRA30 8573 </p> 8574 8575 8576 <a 8577 class="announcement-bar__link" 8578 href="/collections/clearance" 8579 >
8580 <span class="visually-hidden"> 8581 Extra 30% Off Clearance | Code: EXTRA30 8582 </span> 8583 </a> 8584 8585 </slideshow-slide> 8586 8587 8588 8589 </div> 8590 <button 8591 type="button" 8592 class="bp-announcement-playpause" 8593 data-bp-ann-playpause 8594 aria-label="Pause announcements" 8595 aria-pressed="false" 8596 > 8597 <svg class="bp-announcement-playpause__pause" width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true"> 8598 <rect x="2" y="1.5" width="2.6" height="9" rx="0.4" fill="currentColor"/> 8599 <rect x="7.4" y="1.5" width="2.6" height="9" rx="0.4" fill="currentColor"/> 8600 </svg> 8601 <svg class="bp-announcement-playpause__play" width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true" hidden> 8602 <path d="M2.5 1.5l8 4.5-8 4.5z" fill="currentColor"/> 8603 </svg> 8604 </button> 8605 8606 </announcement-bar-component> 8607</aside>
8607<script> 8608 (function () { 8609 if (window.__bpAnnPlayPauseWired) return; 8610 window.__bpAnnPlayPauseWired = true; 8611 8612 // Which GLYPH shows is driven purely by CSS off the bar's `[paused]` 8613 // attribute (see bp-fonts.liquid) â that survives Horizon's re-render of the 8614 // bar, which was resetting the JS-toggled `hidden` and leaving the wrong (or 8615 // both) icons showing. Here we only (a) toggle play/pause on click and 8616 // (b) keep aria-pressed/label in sync with the actual state (incl. any 8617 // auto-pause Horizon does), which CSS can't express. 8618 function syncAria(bar, btn) { 8619 var paused = bar.hasAttribute('paused'); 8620 btn.setAttribute('aria-pressed', paused ? 'true' : 'false'); 8621 btn.setAttribute('aria-label', paused ? 'Play announcements' : 'Pause announcements'); 8622 } 8623 8624 document.addEventListener('click', function (e) { 8625 var btn = e.target.closest && e.target.closest('[data-bp-ann-playpause]'); 8626 if (!btn) return; 8627 var bar = btn.closest('announcement-bar-component'); 8628 if (!bar) return; 8629 if (bar.hasAttribute('paused')) { 8630 if (typeof bar.play === 'function') bar.play(); 8631 else bar.removeAttribute('paused'); 8632 } else { 8633 if (typeof bar.pause === 'function') bar.pause(); 8634 else bar.setAttribute('paused', ''); 8635 } 8636 syncAria(bar, btn); 8637 }); 8638 8639 document.querySelectorAll('announcement-bar-component').forEach(function (bar) { 8640 var btn = bar.querySelector('[data-bp-ann-playpause]'); 8641 if (!btn) return; 8642 syncAria(bar, btn); // initial state on load 8643 try { 8644 new MutationObserver(function () { syncAria(bar, btn); }) 8645 .observe(bar, { attributes: true, attributeFilter: ['paused'] }); 8646 } catch (e) {} 8647 }); 8648 })(); 8649</script>
8649 8650 8651 8652 8653 8654</div><header id="shopify-section-sections--29508264624294__header_section" class="shopify-section shopify-section-group-header-group header-section"> 8655 8656 8657 8658 8659 8660 8661 8662 8663<header-component 8664 id="header-component" 8665 class="header" 8666 data-theme-color="rgb(254 255 250)" 8667 8668 8669 sticky="always" 8670 8671 data-skip-node-update 8672 data-scroll-direction="none" 8673 8674 8675 style=" 8676 --color-scheme-top-row: rgba(254 255 250 / 1.0); 8677 --color-scheme-bottom-row: rgba(254 255 250 / 1.0); 8678 8679 " 8680> 8681 <div class="header__underlay header__underlay-closed"></div> 8682 <div 8683 class="header__underlay header__underlay-open" 8684 ></div> 8685 8686 8687 8688 8689 8690 8691 <div 8692 class="header__row header__row--top color-scheme-1 section section--full-width-margin section--page-width" 8693 ref="headerRowTop"style="--border-bottom-width: 0px; --border-bottom-width-mobile: 0px;"> 8694 <div class="header__columns spacing-style"> 8695 <div 8696 class="header__column header__column--left" 8697 data-testid="header-top-left" 8698 > 8699 8700 8701 8702 8703 8704 8705<div 8706 class="header__drawer" 8707 ref="headerDrawerContainer" 8708 data-hydration-key="header-drawer-mobile" 8709 8710 ><bp-mobile-drawer class="bp-mobile-drawer" data-hydration-key="bp-mobile-drawer" data-skip-subtree-update> 8711 <details class="bp-mobile-drawer__details" ref="details" scroll-lock> 8712 <summary class="bp-mobile-drawer__trigger" aria-label="Menu"> 8713 <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"> 8714<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"/> 8715<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"/> 8716<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"/> 8717<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"/> 8718<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
8718084 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"/> 8719<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"/> 8720</svg> 8721</span> 8722 <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"> 8723 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8724 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8725</svg> 8726</span> 8727 </summary> 8728 8729 <div class="bp-mobile-drawer__panel" data-active-view="root"> 8730 <section class="bp-mobile-drawer__view bp-mobile-drawer__view--active" data-view="root"> 8731 <header class="bp-mobile-drawer__header"> 8732 <h2 class="bp-mobile-drawer__title">Menu</h2> 8733 <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"> 8734 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8735 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8736</svg> 8737</button> 8738 </header> 8739 8740 <ul class="bp-mobile-drawer__list"> 8741 <li 8742 role="presentation" 8743 class="menu-list__list-item bp-menu-item-li" 8744 data-bp-menu-item 8745 8746><a 8747 href="/collections/new-arrivals" 8748 data-skip-node-update="true" 8749 class="menu-list__link" 8750 aria-controls="bp-submenu-AcEtCSXg1K2Q0dGRFQ__bp_menu_new_arrivals-1" 8751 aria-haspopup="true" 8752 aria-expanded="false" 8753 ref="menuitem" 8754 > 8755 <span class="menu-list__link-title">New Arrivals</span> 8756 </a> 8757 <div class="bp-mega-submenu" id="bp-submenu-AcEtCSXg1K2Q0dGRFQ__bp_menu_new_arrivals-1"> 8758 <div class="bp-mega-submenu__inner"> 8759 <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column"> 8760 <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-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"> 8761 <p class="bp-mega__heading"><a href="/collections/new-arrivals">Featured Shops</a></p><ul class="bp-mega__links"><li><a href="/collections/featured-shops-layering">The Layering Shop</a></li><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/clothing-dresses">The Dress Code</a></li><li><a href="/collections/occasions-special-occasion">The Occasion Edit</a></li><li><a href="/collections/editors-picks">Editor's Picks</a></li><li><a href="/collections/featured-shop-intricate-details">Intricate Details</a></li><li><a href="/pages/new-to-boston-proper">New to Boston Proper? </a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li></ul></div><div class="bp-mega__column"> 8762 <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-pants-skirts">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"> 8763 <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">
8763Change 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"> 8764 <a href="/collections/the-right-now-edit" class="bp-mega__promo-link"> 8765 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_61.jpg?v=1790170113&width=400" alt="Your Right-Now Wardrobe" srcset="//www.bostonproper.com/cdn/shop/files/Image_61.jpg?v=1790170113&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_61.jpg?v=1790170113&width=400 400w" width="400" height="500" loading="lazy"> 8766</div> 8767 <h4 class="bp-mega__promo-title">Your Right-Now Wardrobe</h4><div class="bp-mega__promo-copy"><p>Up to 35% Off Wear-Now Styles + Free Shipping Limited Time. <br/>Use code: FREESHIP</p></div><span class="bp-mega__promo-cta">Shop Now</span> 8768 </a> 8769</div> 8770 8771<div class="bp-mega__promo"> 8772 <a href="/pages/the-dress-code" class="bp-mega__promo-link"> 8773 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_New_Arrivals_Dress_Code.jpg?v=1787681292&width=400" alt="The Dress Code" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_New_Arrivals_Dress_Code.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_New_Arrivals_Dress_Code.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:47.07% 8.398%;"> 8774</div> 8775 <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> 8776 </a> 8777</div> 8778 8779</div></div> 8780 </div> 8781 </div></li><li class="bp-mm-item" data-bp-mm-id="AcEtCSXg1K2Q0dGRFQ__bp_menu_new_arrivals-1"><button type="button" class="bp-mm-item__row" data-open-view="AcEtCSXg1K2Q0dGRFQ__bp_menu_new_arrivals-1"> 8782 <span class="bp-mm-item__label">New Arrivals</span> 8783 <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"> 8784 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8785</svg> 8786</span> 8787 </button> 8788 8789 <section class="bp-mm-view" data-view="AcEtCSXg1K2Q0dGRFQ__bp_menu_new_arrivals-1" hidden> 8790 <header class="bp-mm-view__header"> 8791 <button type="button" class="bp-mm-view__back" data-back> 8792 <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"> 8793 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8794</svg> 8795</span> 8796 <span>New Arrivals</span> 8797 </button> 8798 <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"> 8799 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8800 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8801</svg> 8802</button> 8803 </header><div class="bp-mm-view__sections"><section class="bp-mm-section"> 8804 <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-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"> 8805 <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-shops-layering">The Layering Shop</a></li><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/clothing-dresses">The Dress Code</a></li><li><a href="/collections/occasions-special-occasion">The Occasion Edit</a></li><li><a href="/collections/editors-picks">Editor's Picks</a></li><li><a href="/collections/featured-shop-intricate-details">Intricate Details</a></li><li><a href="/pages/new-to-boston-proper">New to Boston Proper? </a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li></ul></section><section class="bp-mm-section"> 8806 <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-pants-skirts">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"> 8807 <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">
8807Change 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"> 8808 <a href="/collections/the-right-now-edit" class="bp-mega__promo-link"> 8809 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_61.jpg?v=1790170113&width=400" alt="Your Right-Now Wardrobe" srcset="//www.bostonproper.com/cdn/shop/files/Image_61.jpg?v=1790170113&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_61.jpg?v=1790170113&width=400 400w" width="400" height="500" loading="lazy"> 8810</div> 8811 <h4 class="bp-mega__promo-title">Your Right-Now Wardrobe</h4><div class="bp-mega__promo-copy"><p>Up to 35% Off Wear-Now Styles + Free Shipping Limited Time. <br/>Use code: FREESHIP</p></div><span class="bp-mega__promo-cta">Shop Now</span> 8812 </a> 8813</div> 8814 8815<div class="bp-mega__promo"> 8816 <a href="/pages/the-dress-code" class="bp-mega__promo-link"> 8817 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_New_Arrivals_Dress_Code.jpg?v=1787681292&width=400" alt="The Dress Code" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_New_Arrivals_Dress_Code.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_New_Arrivals_Dress_Code.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:47.07% 8.398%;"> 8818</div> 8819 <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> 8820 </a> 8821</div> 8822 8823</div></section></li> 8824 8825 8826 8827<li 8828 role="presentation" 8829 class="menu-list__list-item bp-menu-item-li" 8830 data-bp-menu-item 8831 8832><a 8833 href="/collections/clothing" 8834 data-skip-node-update="true" 8835 class="menu-list__link" 8836 aria-controls="bp-submenu-Ab0RsOG9XRC8wSkVoS__bp_menu_clothing-1" 8837 aria-haspopup="true" 8838 aria-expanded="false" 8839 ref="menuitem" 8840 > 8841 <span class="menu-list__link-title">Clothing</span> 8842 </a> 8843 <div class="bp-mega-submenu" id="bp-submenu-Ab0RsOG9XRC8wSkVoS__bp_menu_clothing-1"> 8844 <div class="bp-mega-submenu__inner"> 8845 <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column"> 8846 <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"> 8847 <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">Everyday Style</a></li><li><a href="/collections/occasions-night-out">Night Out</a></li><li><a href="/collections/occasions-special-occasion">Special Occasion</a></li><li><a href="/collections/occasions-vacation">Vacation</a></li><li><a href="/collections/occasions-work">Work Style</a></li><li><a href="/collections/occasions-wedding">Wedding Guest</a></li></ul></div><div class="bp-mega__column"> 8848 <p class="bp-mega__heading"><a href="/collections/clothing">Shops</a></p><ul class="bp-mega__links"><li><a href="/collections/clothing-pants-leggings">
8848The Bottoms Guide</a></li><li><a href="/collections/clothing-jeans">The Denim Guide</a></li><li><a href="/pages/the-dress-code">The Dress Code</a></li><li><a href="/pages/essentials-collection">The Essentials Edit</a></li><li><a href="/collections/featured-shops-matching-sets">Matching Sets</a></li><li><a href="/collections/the-suiting-shop">The Suiting Shop</a></li><li><a href="/collections/essentials">The Tops Collection</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li></ul></div><div class="bp-mega__column"> 8849 <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"> 8850 <a href="/collections/sweaters-turtlenecks" class="bp-mega__promo-link"> 8851 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Turtlenecks.jpg?v=1787681293&width=400" alt="Turtlenecks" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Turtlenecks.jpg?v=1787681293&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Turtlenecks.jpg?v=1787681293&width=400 400w" width="400" height="500" loading="lazy" style="object-position:51.66% 34.766%;"> 8852</div> 8853 <h4 class="bp-mega__promo-title">Turtlenecks</h4><div class="bp-mega__promo-copy"><p>A classic made current. Clean, confident, and made for the season.</p></div><span class="bp-mega__promo-cta">Shop Now</span> 8854 </a> 8855</div> 8856 8857<div class="bp-mega__promo"> 8858 <a href="/collections/knit-tops" class="bp-mega__promo-link"> 8859 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Knits.jpg?v=1787681293&width=400" alt="Knit Tops" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Knits.jpg?v=1787681293&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Knits.jpg?v=1787681293&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 17.48%;"> 8860</div> 8861 <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> 8862 </a> 8863</div> 8864 8865</div></div> 8866 </div> 8867 </div></li><li class="bp-mm-item" data-bp-mm-id="Ab0RsOG9XRC8wSkVoS__bp_menu_clothing-1"><button type="button" class="bp-mm-item__row" data-open-view="Ab0RsOG9XRC8wSkVoS__bp_menu_clothing-1"> 8868 <span class="bp-mm-item__label">Clothing</span> 8869 <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"> 8870 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8871</svg> 8872</span> 8873 </button> 8874 8875 <section class="bp-mm-view" data-view="Ab0RsOG9XRC8wSkVoS__bp_menu_clothing-1" hidden> 8876 <header class="bp-mm-view__header"> 8877 <button type="button" class="bp-mm-view__back" data-back> 8878 <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"> 8879 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8880</svg> 8881</span>
8882 <span>Clothing</span> 8883 </button> 8884 <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"> 8885 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8886 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8887</svg> 8888</button> 8889 </header><div class="bp-mm-view__sections"><section class="bp-mm-section"> 8890 <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"> 8891 <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">Everyday Style</a></li><li><a href="/collections/occasions-night-out">Night Out</a></li><li><a href="/collections/occasions-special-occasion">Special Occasion</a></li><li><a href="/collections/occasions-vacation">Vacation</a></li><li><a href="/collections/occasions-work">Work Style</a></li><li><a href="/collections/occasions-wedding">Wedding Guest</a></li></ul></section><section class="bp-mm-section"> 8892 <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/the-dress-code">The Dress Code</a></li><li><a href="/pages/essentials-collection">The Essentials Edit</a></li><li><a href="/collections/featured-shops-matching-sets">Matching Sets</a></li><li><a href="/collections/the-suiting-shop">The Suiting Shop</a></li><li><a href="/collections/essentials">The Tops Collection</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li></ul></section><section class="bp-mm-section"> 8893 <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"> 8894 <a href="/collections/sweaters-turtlenecks" class="bp-mega__promo-link"> 8895 <div class="bp-mega__promo-image">
8895<img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Turtlenecks.jpg?v=1787681293&width=400" alt="Turtlenecks" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Turtlenecks.jpg?v=1787681293&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Turtlenecks.jpg?v=1787681293&width=400 400w" width="400" height="500" loading="lazy" style="object-position:51.66% 34.766%;"> 8896</div> 8897 <h4 class="bp-mega__promo-title">Turtlenecks</h4><div class="bp-mega__promo-copy"><p>A classic made current. Clean, confident, and made for the season.</p></div><span class="bp-mega__promo-cta">Shop Now</span> 8898 </a> 8899</div> 8900 8901<div class="bp-mega__promo"> 8902 <a href="/collections/knit-tops" class="bp-mega__promo-link"> 8903 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Knits.jpg?v=1787681293&width=400" alt="Knit Tops" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Knits.jpg?v=1787681293&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Knits.jpg?v=1787681293&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 17.48%;"> 8904</div> 8905 <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> 8906 </a> 8907</div> 8908 8909</div></section></li> 8910 8911 8912 8913<li 8914 role="presentation" 8915 class="menu-list__list-item bp-menu-item-li" 8916 data-bp-menu-item 8917 8918><a 8919 href="/pages/all-occasions" 8920 data-skip-node-update="true" 8921 class="menu-list__link" 8922 aria-controls="bp-submenu-ANytpazFVQlZ3RksxN__bp_menu_occasions-1" 8923 aria-haspopup="true" 8924 aria-expanded="false" 8925 ref="menuitem" 8926 > 8927 <span class="menu-list__link-title">Occasions</span> 8928 </a> 8929 <div class="bp-mega-submenu" id="bp-submenu-ANytpazFVQlZ3RksxN__bp_menu_occasions-1"> 8930 <div class="bp-mega-submenu__inner"> 8931 <div class="bp-mega bp-mega--image-tiles"><div class="bp-mega__tiles"><a class="bp-mega__tile" href="/collections/occasions-everyday-style"> 8932 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_19.jpg?v=1787764619&width=400" alt="Casual Chic" srcset="//www.bostonproper.com/cdn/shop/files/Image_19.jpg?v=1787764619&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_19.jpg?v=1787764619&width=400 400w" width="400" height="500" loading="lazy" style="object-position:52.148% 9.277%;"> 8933</div> 8934 <p class="bp-mega__tile-title">Casual Chic</p> 8935 <span class="bp-mega__tile-cta">Shop Now</span> 8936 </a><a class="bp-mega__tile" href="/collections/occasions-vacation"> 8937 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_20.jpg?v=1787764642&width=400" alt="Escape in Style" srcset="//www.bostonproper.com/cdn/shop/files/Image_20.jpg?v=1787764642&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_20.jpg?v=1787764642&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 11.816%;"> 8938</div> 8939 <p class="bp-mega__tile-title">Escape in Style</p> 8940 <span class="bp-mega__tile-cta">Shop Now</span> 8941 </a><a class="bp-mega__tile" href="/collections/occasions-special-occasion"> 8942 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_21.jpg?v=1787764672&width=400" alt="RSVP Ready" srcset="//www.bostonproper.com/cdn/shop/files/Image_21.jpg?v=1787764672&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_21.jpg?v=1787764672&width=400 400w" width="400" height="500" loading="lazy" style="object-position:37.012% 15.625%;"> 8943</div> 8944 <p class="bp-mega__tile-title">RSVP Ready</p> 8945 <span class="bp-mega__tile-cta">Shop Now</span> 8946 </a><a class="bp-mega__tile" href="/collections/occasions-work"> 8947 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_22.jpg?v=1787764700&width=400" alt="Power Moves" srcset="//www.bostonproper.com/cdn/shop/files/Image_22.jpg?v=1787764700&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_22.jpg?v=1787764700&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 11.621%;"> 8948</div> 8949 <p class="bp-mega__tile-title">Power Moves</p>
8950 <span class="bp-mega__tile-cta">Shop Now</span> 8951 </a><a class="bp-mega__tile" href="/collections/occasions-night-out"> 8952 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_23.jpg?v=1787764729&width=400" alt="Own the Evening" srcset="//www.bostonproper.com/cdn/shop/files/Image_23.jpg?v=1787764729&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_23.jpg?v=1787764729&width=400 400w" width="400" height="500" loading="lazy" style="object-position:21.387% 20.898%;"> 8953</div> 8954 <p class="bp-mega__tile-title">Own the Evening</p> 8955 <span class="bp-mega__tile-cta">Shop Now</span> 8956 </a><a class="bp-mega__tile" href="/collections/occasions-wedding"> 8957 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_24.jpg?v=1787764753&width=400" alt="Celebrate Beautifully" srcset="//www.bostonproper.com/cdn/shop/files/Image_24.jpg?v=1787764753&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_24.jpg?v=1787764753&width=400 400w" width="400" height="500" loading="lazy" style="object-position:50.586% 11.621%;"> 8958</div> 8959 <p class="bp-mega__tile-title">Celebrate Beautifully</p> 8960 <span class="bp-mega__tile-cta">Shop Now</span> 8961 </a></div></div> 8962 </div> 8963 </div></li><li class="bp-mm-item" data-bp-mm-id="ANytpazFVQlZ3RksxN__bp_menu_occasions-1"><button type="button" class="bp-mm-item__row" data-open-view="ANytpazFVQlZ3RksxN__bp_menu_occasions-1"> 8964 <span class="bp-mm-item__label">Occasions</span> 8965 <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"> 8966 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8967</svg> 8968</span> 8969 </button> 8970 8971 <section class="bp-mm-view" data-view="ANytpazFVQlZ3RksxN__bp_menu_occasions-1" hidden> 8972 <header class="bp-mm-view__header"> 8973 <button type="button" class="bp-mm-view__back" data-back> 8974 <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"> 8975 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8976</svg> 8977</span> 8978 <span>Occasions</span> 8979 </button> 8980 <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"> 8981 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8982 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 8983</svg> 8984</button> 8985 </header><div class="bp-mm-view__tiles"><a class="bp-mm-tile" href="/collections/occasions-everyday-style"> 8986 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_19.jpg?v=1787764619&width=400" alt="Casual Chic" srcset="//www.bostonproper.com/cdn/shop/files/Image_19.jpg?v=1787764619&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_19.jpg?v=1787764619&width=400 400w" width="400" height="500" loading="lazy" style="object-position:52.148% 9.277%;"> 8987</span> 8988 <span class="bp-mm-tile__title">Casual Chic</span> 8989 <span class="bp-mm-tile__cta">Shop Now</span> 8990 </a><a class="bp-mm-tile" href="/collections/occasions-vacation"> 8991 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_20.jpg?v=1787764642&width=400" alt="Escape in Style" srcset="//www.bostonproper.com/cdn/shop/files/Image_20.jpg?v=1787764642&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_20.jpg?v=1787764642&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 11.816%;"> 8992</span>
8993 <span class="bp-mm-tile__title">Escape in Style</span> 8994 <span class="bp-mm-tile__cta">Shop Now</span> 8995 </a><a class="bp-mm-tile" href="/collections/occasions-special-occasion"> 8996 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_21.jpg?v=1787764672&width=400" alt="RSVP Ready" srcset="//www.bostonproper.com/cdn/shop/files/Image_21.jpg?v=1787764672&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_21.jpg?v=1787764672&width=400 400w" width="400" height="500" loading="lazy" style="object-position:37.012% 15.625%;"> 8997</span> 8998 <span class="bp-mm-tile__title">RSVP Ready</span> 8999 <span class="bp-mm-tile__cta">Shop Now</span> 9000 </a><a class="bp-mm-tile" href="/collections/occasions-work"> 9001 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_22.jpg?v=1787764700&width=400" alt="Power Moves" srcset="//www.bostonproper.com/cdn/shop/files/Image_22.jpg?v=1787764700&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_22.jpg?v=1787764700&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 11.621%;"> 9002</span> 9003 <span class="bp-mm-tile__title">Power Moves</span> 9004 <span class="bp-mm-tile__cta">Shop Now</span> 9005 </a><a class="bp-mm-tile" href="/collections/occasions-night-out"> 9006 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_23.jpg?v=1787764729&width=400" alt="Own the Evening" srcset="//www.bostonproper.com/cdn/shop/files/Image_23.jpg?v=1787764729&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_23.jpg?v=1787764729&width=400 400w" width="400" height="500" loading="lazy" style="object-position:21.387% 20.898%;"> 9007</span> 9008 <span class="bp-mm-tile__title">Own the Evening</span> 9009 <span class="bp-mm-tile__cta">Shop Now</span> 9010 </a><a class="bp-mm-tile" href="/collections/occasions-wedding"> 9011 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_24.jpg?v=1787764753&width=400" alt="Celebrate Beautifully" srcset="//www.bostonproper.com/cdn/shop/files/Image_24.jpg?v=1787764753&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_24.jpg?v=1787764753&width=400 400w" width="400" height="500" loading="lazy" style="object-position:50.586% 11.621%;"> 9012</span> 9013 <span class="bp-mm-tile__title">Celebrate Beautifully</span> 9014 <span class="bp-mm-tile__cta">Shop Now</span> 9015 </a></div></section></li> 9016 9017 9018 9019<li 9020 role="presentation" 9021 class="menu-list__list-item bp-menu-item-li" 9022 data-bp-menu-item 9023 9024><a 9025 href="/pages/essentials-collection" 9026 data-skip-node-update="true" 9027 class="menu-list__link" 9028 aria-controls="bp-submenu-AVzFzNXNucVZNUytIV__bp_menu_collections-1" 9029 aria-haspopup="true" 9030 aria-expanded="false" 9031 ref="menuitem" 9032 > 9033 <span class="menu-list__link-title">Collections</span> 9034 </a> 9035 <div class="bp-mega-submenu" id="bp-submenu-AVzFzNXNucVZNUytIV__bp_menu_collections-1"> 9036 <div class="bp-mega-submenu__inner"> 9037 <div class="bp-mega bp-mega--image-tiles"><div class="bp-mega__tiles"><a class="bp-mega__tile" href="/collections/featured-shops-matching-sets"> 9038 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_15_a1d69794-6955-45f6-b7a6-8c503b9770c5.jpg?v=1789756263&width=400" alt="Matching Sets" srcset="//www.bostonproper.com/cdn/shop/files/Image_15_a1d69794-6955-45f6-b7a6-8c503b9770c5.jpg?v=1789756263&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_15_a1d69794-6955-45f6-b7a6-8c503b9770c5.jpg?v=1789756263&width=400 400w" width="400" height="500" loading="lazy"> 9039</div> 9040 <p class="bp-mega__tile-title">Matching Sets</p> 9041 <span class="bp-mega__tile-cta">Shop Now</span> 9042 </a><a class="bp-mega__tile" href="/collections/clothing-jeans"> 9043 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_15.jpg?v=1787751060&width=400" alt="Denim" srcset="//www.bostonproper.com/cdn/shop/files/Image_15.jpg?v=1787751060&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_15.jpg?v=1787751060&width=400 400w" width="400" height="500" loading="lazy" style="object-position:47.656% 11.621%;"> 9044</div> 9045 <p class="bp-mega__tile-title">Denim</p>
9046 <span class="bp-mega__tile-cta">Shop Now</span> 9047 </a><a class="bp-mega__tile" href="/collections/athleisure-luxe-lounge"> 9048 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_18.jpg?v=1787751146&width=400" alt="Luxe Lounge" srcset="//www.bostonproper.com/cdn/shop/files/Image_18.jpg?v=1787751146&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_18.jpg?v=1787751146&width=400 400w" width="400" height="500" loading="lazy" style="object-position:45.02% 13.77%;"> 9049</div> 9050 <p class="bp-mega__tile-title">Luxe Lounge</p> 9051 <span class="bp-mega__tile-cta">Shop Now</span> 9052 </a><a class="bp-mega__tile" href="/collections/travel"> 9053 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_17.jpg?v=1787751124&width=400" alt="Beyond Travel" srcset="//www.bostonproper.com/cdn/shop/files/Image_17.jpg?v=1787751124&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_17.jpg?v=1787751124&width=400 400w" width="400" height="500" loading="lazy" style="object-position:51.66% 13.477%;"> 9054</div> 9055 <p class="bp-mega__tile-title">Beyond Travel</p> 9056 <span class="bp-mega__tile-cta">Shop Now</span> 9057 </a><a class="bp-mega__tile" href="/collections/charmeuse"> 9058 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_13.jpg?v=1787750993&width=400" alt="Charmeuse" srcset="//www.bostonproper.com/cdn/shop/files/Image_13.jpg?v=1787750993&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_13.jpg?v=1787750993&width=400 400w" width="400" height="500" loading="lazy" style="object-position:43.164% 16.309%;"> 9059</div> 9060 <p class="bp-mega__tile-title">Charmeuse</p> 9061 <span class="bp-mega__tile-cta">Shop Now</span> 9062 </a><a class="bp-mega__tile" href="/collections/the-suiting-shop"> 9063 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_16.jpg?v=1787751087&width=400" alt="Modern Suiting" srcset="//www.bostonproper.com/cdn/shop/files/Image_16.jpg?v=1787751087&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_16.jpg?v=1787751087&width=400 400w" width="400" height="500" loading="lazy" style="object-position:52.148% 17.578%;"> 9064</div> 9065 <p class="bp-mega__tile-title">Modern Suiting</p> 9066 <span class="bp-mega__tile-cta">Shop Now</span> 9067 </a></div></div> 9068 </div> 9069 </div></li><li class="bp-mm-item" data-bp-mm-id="AVzFzNXNucVZNUytIV__bp_menu_collections-1"><button type="button" class="bp-mm-item__row" data-open-view="AVzFzNXNucVZNUytIV__bp_menu_collections-1"> 9070 <span class="bp-mm-item__label">Collections</span> 9071 <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"> 9072 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9073</svg> 9074</span> 9075 </button> 9076 9077 <section class="bp-mm-view" data-view="AVzFzNXNucVZNUytIV__bp_menu_collections-1" hidden> 9078 <header class="bp-mm-view__header"> 9079 <button type="button" class="bp-mm-view__back" data-back> 9080 <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"> 9081 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9082</svg> 9083</span> 9084 <span>Collections</span> 9085 </button> 9086 <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"> 9087 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9088 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9089</svg> 9090</button> 9091 </header><div class="bp-mm-view__tiles"><a class="bp-mm-tile" href="/collections/featured-shops-matching-sets">
9092 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_15_a1d69794-6955-45f6-b7a6-8c503b9770c5.jpg?v=1789756263&width=400" alt="Matching Sets" srcset="//www.bostonproper.com/cdn/shop/files/Image_15_a1d69794-6955-45f6-b7a6-8c503b9770c5.jpg?v=1789756263&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_15_a1d69794-6955-45f6-b7a6-8c503b9770c5.jpg?v=1789756263&width=400 400w" width="400" height="500" loading="lazy"> 9093</span> 9094 <span class="bp-mm-tile__title">Matching Sets</span> 9095 <span class="bp-mm-tile__cta">Shop Now</span> 9096 </a><a class="bp-mm-tile" href="/collections/clothing-jeans"> 9097 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_15.jpg?v=1787751060&width=400" alt="Denim" srcset="//www.bostonproper.com/cdn/shop/files/Image_15.jpg?v=1787751060&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_15.jpg?v=1787751060&width=400 400w" width="400" height="500" loading="lazy" style="object-position:47.656% 11.621%;"> 9098</span> 9099 <span class="bp-mm-tile__title">Denim</span> 9100 <span class="bp-mm-tile__cta">Shop Now</span> 9101 </a><a class="bp-mm-tile" href="/collections/athleisure-luxe-lounge"> 9102 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_18.jpg?v=1787751146&width=400" alt="Luxe Lounge" srcset="//www.bostonproper.com/cdn/shop/files/Image_18.jpg?v=1787751146&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_18.jpg?v=1787751146&width=400 400w" width="400" height="500" loading="lazy" style="object-position:45.02% 13.77%;"> 9103</span> 9104 <span class="bp-mm-tile__title">Luxe Lounge</span> 9105 <span class="bp-mm-tile__cta">Shop Now</span> 9106 </a><a class="bp-mm-tile" href="/collections/travel"> 9107 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_17.jpg?v=1787751124&width=400" alt="Beyond Travel" srcset="//www.bostonproper.com/cdn/shop/files/Image_17.jpg?v=1787751124&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_17.jpg?v=1787751124&width=400 400w" width="400" height="500" loading="lazy" style="object-position:51.66% 13.477%;"> 9108</span> 9109 <span class="bp-mm-tile__title">Beyond Travel</span> 9110 <span class="bp-mm-tile__cta">Shop Now</span> 9111 </a><a class="bp-mm-tile" href="/collections/charmeuse"> 9112 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_13.jpg?v=1787750993&width=400" alt="Charmeuse" srcset="//www.bostonproper.com/cdn/shop/files/Image_13.jpg?v=1787750993&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_13.jpg?v=1787750993&width=400 400w" width="400" height="500" loading="lazy" style="object-position:43.164% 16.309%;"> 9113</span> 9114 <span class="bp-mm-tile__title">Charmeuse</span> 9115 <span class="bp-mm-tile__cta">Shop Now</span> 9116 </a><a class="bp-mm-tile" href="/collections/the-suiting-shop"> 9117 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_16.jpg?v=1787751087&width=400" alt="Modern Suiting" srcset="//www.bostonproper.com/cdn/shop/files/Image_16.jpg?v=1787751087&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_16.jpg?v=1787751087&width=400 400w" width="400" height="500" loading="lazy" style="object-position:52.148% 17.578%;"> 9118</span> 9119 <span class="bp-mm-tile__title">Modern Suiting</span> 9120 <span class="bp-mm-tile__cta">Shop Now</span> 9121 </a></div></section></li> 9122 9123 9124 9125<li 9126 role="presentation" 9127 class="menu-list__list-item bp-menu-item-li" 9128 data-bp-menu-item 9129 9130><a 9131 href="/collections/shoes-accessories" 9132 data-skip-node-update="true" 9133 class="menu-list__link" 9134 aria-controls="bp-submenu-ARXIzNlBSeHFvVkpPd__bp_menu_shoes-1" 9135 aria-haspopup="true" 9136 aria-expanded="false" 9137 ref="menuitem" 9138 >
9139 <span class="menu-list__link-title">Shoes & Accessories</span> 9140 </a> 9141 <div class="bp-mega-submenu" id="bp-submenu-ARXIzNlBSeHFvVkpPd__bp_menu_shoes-1"> 9142 <div class="bp-mega-submenu__inner"> 9143 <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column"> 9144 <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"> 9145 <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"> 9146 <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"> 9147 <a href="/collections/shoes-boots" class="bp-mega__promo-link"> 9148 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Boots.jpg?v=1787681292&width=400" alt="Boots" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Boots.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Boots.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:48.926% 51.66%;"> 9149</div> 9150 <h4 class="bp-mega__promo-title">Boots</h4><div class="bp-mega__promo-copy"><p>These boots are going places. Refined prints. Rich tonal textures. Over-the-knee.  A new mood for every look.  </p></div><span class="bp-mega__promo-cta">Shop Now</span> 9151 </a> 9152</div> 9153 9154<div class="bp-mega__promo"> 9155 <a href="/collections/accessories-jewelry" class="bp-mega__promo-link"> 9156 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Jewelry.jpg?v=1787681292&width=400" alt="Jewelry" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Jewelry.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Jewelry.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 77.93%;"> 9157</div> 9158 <h4 class="bp-mega__promo-title">Jewelry</h4><div class="bp-mega__promo-copy"><p>Drenched in the details that define Boston Proper. Layered jewels and accent pieces that set the tone.  </p></div><span class="bp-mega__promo-cta">Shop Now</span> 9159 </a> 9160</div> 9161 9162</div></div> 9163 </div> 9164 </div></li><li class="bp-mm-item" data-bp-mm-id="ARXIzNlBSeHFvVkpPd__bp_menu_shoes-1"><button type="button" class="bp-mm-item__row" data-open-view="ARXIzNlBSeHFvVkpPd__bp_menu_shoes-1">
9165 <span class="bp-mm-item__label">Shoes & Accessories</span> 9166 <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"> 9167 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9168</svg> 9169</span> 9170 </button> 9171 9172 <section class="bp-mm-view" data-view="ARXIzNlBSeHFvVkpPd__bp_menu_shoes-1" hidden> 9173 <header class="bp-mm-view__header"> 9174 <button type="button" class="bp-mm-view__back" data-back> 9175 <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"> 9176 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9177</svg> 9178</span> 9179 <span>Shoes & Accessories</span> 9180 </button> 9181 <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"> 9182 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9183 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9184</svg> 9185</button> 9186 </header><div class="bp-mm-view__sections"><section class="bp-mm-section"> 9187 <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"> 9188 <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"> 9189 <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"> 9190 <a href="/collections/shoes-boots" class="bp-mega__promo-link"> 9191 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Boots.jpg?v=1787681292&width=400" alt="Boots" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Boots.jpg?v=1787681292&
9191width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Boots.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:48.926% 51.66%;"> 9192</div> 9193 <h4 class="bp-mega__promo-title">Boots</h4><div class="bp-mega__promo-copy"><p>These boots are going places. Refined prints. Rich tonal textures. Over-the-knee.  A new mood for every look.  </p></div><span class="bp-mega__promo-cta">Shop Now</span> 9194 </a> 9195</div> 9196 9197<div class="bp-mega__promo"> 9198 <a href="/collections/accessories-jewelry" class="bp-mega__promo-link"> 9199 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Jewelry.jpg?v=1787681292&width=400" alt="Jewelry" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Jewelry.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Jewelry.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 77.93%;"> 9200</div> 9201 <h4 class="bp-mega__promo-title">Jewelry</h4><div class="bp-mega__promo-copy"><p>Drenched in the details that define Boston Proper. Layered jewels and accent pieces that set the tone.  </p></div><span class="bp-mega__promo-cta">Shop Now</span> 9202 </a> 9203</div> 9204 9205</div></section></li> 9206 9207 9208 9209<li 9210 role="presentation" 9211 class="menu-list__list-item bp-menu-item-li" 9212 data-bp-menu-item 9213 9214><a 9215 href="/collections/sale-clearance" 9216 data-skip-node-update="true" 9217 class="menu-list__link" 9218 aria-controls="bp-submenu-AWFVxNmtRQ2t1ak41R__bp_menu_sale-1" 9219 aria-haspopup="true" 9220 aria-expanded="false" 9221 ref="menuitem" 9222 > 9223 <span class="menu-list__link-title">Sale & Clearance</span> 9224 </a> 9225 <div class="bp-mega-submenu" id="bp-submenu-AWFVxNmtRQ2t1ak41R__bp_menu_sale-1"> 9226 <div class="bp-mega-submenu__inner"> 9227 <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column"> 9228 <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"> 9229 <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"> 9230 <p class="bp-mega__heading"><a href="/collections/sale-clearance">Promotions</a></p><ul class="bp-mega__links"><li><a href="/collections/clothing-tops-blouses-tees">Buy one top, get one 50% off</a></li><li><a href="/collections/clearance">Extra 30% off clearance</a></li><li><a href="/collections/fall-trans-cami-promo">Stock Up On Effortless Style</a></li><li><a href="/collections/buy-2-save-20-mix-and-match">Buy 2, Save $20</a></li></ul></div></div><div class="bp-mega__promos"><div class="bp-mega__promo"> 9231 <a href="/collections/new-arrivals" class="bp-mega__promo-link"> 9232 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/bg.jpg?v=1787336860&width=400" alt="Seize The Moment" srcset="//www.bostonproper.com/cdn/shop/files/bg.jpg?v=1787336860&width=200 200w, //www.bostonproper.com/cdn/shop/files/bg.jpg?v=1787336860&width=400 400w" width="400" height="500" loading="lazy"> 9233</div> 9234 <h4 class="bp-mega__promo-title">Seize The Moment</h4><div class="bp-mega__promo-copy"><p>Shipping is on us, but not for long.<br/>Use FREESHIP</p></div><span class="bp-mega__promo-cta">Shop Now</span> 9235 </a> 9236</div> 9237 9238<div class="bp-mega__promo"> 9239 <a href="/collections/clearance" class="bp-mega__promo-link"> 9240 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_55.jpg?v=1789573352&width=400" alt="The Final Find" srcset="//www.bostonproper.com/cdn/shop/files/Image_55.jpg?v=1789573352&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_55.jpg?v=1789573352&width=400 400w" width="400" height="500" loading="lazy"> 9241</div> 9242 <h4 class="bp-mega__promo-title">The Final Find</h4><div class="bp-mega__promo-copy"><p>Take an extra 30% off Chic Clearanceâtimeless pieces, final sizes, rare finds. <br/>Use code: EXTRA30</p></div><span class="bp-mega__promo-cta">Shop Now</span> 9243 </a> 9244</div> 9245 9246</div></div> 9247 </div> 9248 </div></li><li class="bp-mm-item" data-bp-mm-id="AWFVxNmtRQ2t1ak41R__bp_menu_sale-1"><button type="button" class="bp-mm-item__row" data-open-view="AWFVxNmtRQ2t1ak41R__bp_menu_sale-1">
9249 <span class="bp-mm-item__label">Sale & Clearance</span> 9250 <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"> 9251 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9252</svg> 9253</span> 9254 </button> 9255 9256 <section class="bp-mm-view" data-view="AWFVxNmtRQ2t1ak41R__bp_menu_sale-1" hidden> 9257 <header class="bp-mm-view__header"> 9258 <button type="button" class="bp-mm-view__back" data-back> 9259 <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"> 9260 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9261</svg> 9262</span> 9263 <span>Sale & Clearance</span> 9264 </button> 9265 <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"> 9266 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9267 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9268</svg> 9269</button> 9270 </header><div class="bp-mm-view__sections"><section class="bp-mm-section"> 9271 <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"> 9272 <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"> 9273 <p class="bp-mm-section__heading"><a href="/collections/sale-clearance">Promotions</a></p><ul class="bp-mm-section__links"><li><a href="/collections/clothing-tops-blouses-tees">Buy one top, get one 50% off</a></li><li><a href="/collections/clearance">Extra 30% off clearance</a></li><li><a href="/collections/fall-trans-cami-promo">Stock Up On Effortless Style</a></li><li><a href="/collections/buy-2-save-20-mix-and-match">Buy 2, Save $20</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo"> 9274 <a href="/collections/new-arrivals" class="bp-mega__promo-link"> 9275 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/bg.jpg?v=1787336860&width=400" alt="Seize The Moment" srcset="//www.bostonproper.com/cdn/shop/files/bg.jpg?v=1787336860&width=200 200w, //www.bostonproper.com/cdn/shop/files/bg.jpg?v=1787336860&width=400 400w" width="400" height="500" loading="lazy"> 9276</div> 9277 <h4 class="bp-mega__promo-title">Seize The Moment</h4><div class="bp-mega__promo-copy"><p>Shipping is on us, but not for long.<br/>Use FREESHIP</p></div><span class="bp-mega__promo-cta">Shop Now</span> 9278 </a> 9279</div> 9280 9281<div class="bp-mega__promo"> 9282 <a href="/collections/clearance" class="bp-mega__promo-link"> 9283 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_55.jpg?v=1789573352&width=400" alt="The Final Find" srcset="//www.bostonproper.com/cdn/shop/files/Image_55.jpg?v=1789573352&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_55.jpg?v=1789573352&width=400 400w" width="400" height="500" loading="lazy"> 9284</div> 9285 <h4 class="bp-mega__promo-title">The Final Find</h4><div class="bp-mega__promo-copy"><p>Take an extra 30% off Chic Clearanceâtimeless pieces, final sizes, rare finds. <br/>Use code: EXTRA30</p></div><span class="bp-mega__promo-cta">Shop Now</span> 9286 </a> 9287</div> 9288 9289</div></section></li> 9290 9291 9292 9293<li 9294 role="presentation" 9295 class="menu-list__list-item bp-menu-item-li" 9296 data-bp-menu-item 9297 9298><a 9299 href="/blogs/styleedit" 9300 data-skip-node-update="true" 9301 class="menu-list__link" 9302 aria-controls="bp-submenu-ASVd5SE91ZGUwR3ZhZ__bp_menu_styleedit-1" 9303 aria-haspopup="true" 9304 aria-expanded="false" 9305 ref="menuitem" 9306 >
9307 <span class="menu-list__link-title">Discover</span> 9308 </a> 9309 <div class="bp-mega-submenu" id="bp-submenu-ASVd5SE91ZGUwR3ZhZ__bp_menu_styleedit-1"> 9310 <div class="bp-mega-submenu__inner"> 9311 <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column"> 9312 <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"> 9313 <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"> 9314 <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"> 9315 <a href="/pages/sheryls-loves" class="bp-mega__promo-link"> 9316 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Sheryls_Loves.jpg?v=1787681292&width=400" alt="Sherylâs Loves" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Sheryls_Loves.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Sheryls_Loves.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 14.355%;"> 9317</div> 9318 <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.â âSheryl, Editor-in-Chic </p></div><span class="bp-mega__promo-cta">Shop Now</span> 9319 </a> 9320</div> 9321 9322<div class="bp-mega__promo"> 9323 <a href="/pages/digital-catalog" class="bp-mega__promo-link"> 9324 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Catalog.jpg?v=1787681292&width=400" alt="Digital Catalog" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Catalog.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Catalog.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:68.848% 22.363%;"> 9325</div> 9326 <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. </p></div><span class="bp-mega__promo-cta">Shop Now</span> 9327 </a> 9328</div> 9329 9330</div></div> 9331 </div> 9332 </div></li><li class="bp-mm-item" data-bp-mm-id="ASVd5SE91ZGUwR3ZhZ__bp_menu_styleedit-1"><button type="button" class="bp-mm-item__row" data-open-view="ASVd5SE91ZGUwR3ZhZ__bp_menu_styleedit-1"> 9333 <span class="bp-mm-item__label">Discover</span> 9334 <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"> 9335 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9336</svg> 9337</span> 9338 </button> 9339 9340 <section class="bp-mm-view" data-view="ASVd5SE91ZGUwR3ZhZ__bp_menu_styleedit-1" hidden> 9341 <header class="bp-mm-view__header"> 9342 <button type="button" class="bp-mm-view__back" data-back>
9343 <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"> 9344 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9345</svg> 9346</span> 9347 <span>Discover</span> 9348 </button> 9349 <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"> 9350 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9351 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9352</svg> 9353</button> 9354 </header><div class="bp-mm-view__sections"><section class="bp-mm-section"> 9355 <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"> 9356 <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"> 9357 <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"> 9358 <a href="/pages/sheryls-loves" class="bp-mega__promo-link"> 9359 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Sheryls_Loves.jpg?v=1787681292&width=400" alt="Sherylâs Loves" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Sheryls_Loves.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Sheryls_Loves.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 14.355%;"> 9360</div> 9361 <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.â âSheryl, Editor-in-Chic </p></div><span class="bp-mega__promo-cta">Shop Now</span> 9362 </a> 9363</div> 9364 9365<div class="bp-mega__promo"> 9366 <a href="/pages/digital-catalog" class="bp-mega__promo-link"> 9367 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Catalog.jpg?v=1787681292&width=400" alt="Digital Catalog" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Catalog.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Catalog.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:68.848% 22.363%;"> 9368</div> 9369 <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. </p></div><span class="bp-mega__promo-cta">Shop Now</span> 9370 </a> 9371</div> 9372 9373</div></section></li> 9374 9375 9376 9377<li 9378 role="presentation" 9379 class="menu-list__list-item bp-menu-item-li" 9380 data-bp-menu-item 9381 9382><a 9383 href="/collections/brands-we-love" 9384 data-skip-node-update="true" 9385 class="menu-list__link" 9386 aria-controls="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1" 9387 aria-haspopup="true" 9388 aria-expanded="false" 9389 ref="menuitem" 9390 >
9391 <span class="menu-list__link-title">Brands We Love</span> 9392 </a> 9393 <div class="bp-mega-submenu" id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1"> 9394 <div class="bp-mega-submenu__inner"> 9395 <div class="bp-mega bp-mega--tabs-promos"><div class="bp-mega__tabs" data-bp-mega-tabs data-bp-tab-columns="2"> 9396 <ul class="bp-mega__tabs-list" role="tablist"><li role="presentation"> 9397 <button 9398 type="button" 9399 role="tab" 9400 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-tab-0" 9401 class="bp-mega__tab is-active" 9402 aria-controls="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-panel-0" 9403 aria-selected="true" 9404 data-bp-mega-tab 9405 > 9406 <span class="bp-mega__tab-label">BRANDS WE LOVE</span> 9407 <span class="bp-mega__tab-chevron" aria-hidden="true"> 9408 <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> 9409 <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"/> 9410 <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"/> 9411 </svg> 9412 </span> 9413 </button> 9414 </li><li role="presentation"> 9415 <button 9416 type="button" 9417 role="tab" 9418 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-tab-1" 9419 class="bp-mega__tab" 9420 aria-controls="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-panel-1" 9421 aria-selected="false" 9422 data-bp-mega-tab 9423 > 9424 <span class="bp-mega__tab-label">JEWELRY & ACCESSORIES</span> 9425 <span class="bp-mega__tab-chevron" aria-hidden="true"> 9426 <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> 9427 <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"/> 9428 <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"/> 9429 </svg> 9430 </span> 9431 </button> 9432 </li><li role="presentation"> 9433 <button 9434 type="button" 9435 role="tab" 9436 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-tab-2" 9437 class="bp-mega__tab" 9438 aria-controls="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-panel-2" 9439 aria-selected="false" 9440 data-bp-mega-tab 9441 >
9442 <span class="bp-mega__tab-label">ATHLEISURE</span> 9443 <span class="bp-mega__tab-chevron" aria-hidden="true"> 9444 <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> 9445 <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"/> 9446 <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"/> 9447 </svg> 9448 </span> 9449 </button> 9450 </li><li role="presentation"> 9451 <button 9452 type="button" 9453 role="tab" 9454 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-tab-3" 9455 class="bp-mega__tab" 9456 aria-controls="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-panel-3" 9457 aria-selected="false" 9458 data-bp-mega-tab 9459 > 9460 <span class="bp-mega__tab-label">HEALTH & BEAUTY</span> 9461 <span class="bp-mega__tab-chevron" aria-hidden="true"> 9462 <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> 9463 <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"/> 9464 <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"/> 9465 </svg> 9466 </span> 9467 </button> 9468 </li></ul> 9469 9470 <div class="bp-mega__tabs-panels"><div 9471 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-panel-0" 9472 role="tabpanel" 9473 aria-labelledby="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-tab-0" 9474 class="bp-mega__tab-panel is-active" 9475 data-bp-mega-panel 9476 9477 > 9478 <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">
9478Change 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 9479 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-panel-1" 9480 role="tabpanel" 9481 aria-labelledby="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-tab-1" 9482 class="bp-mega__tab-panel" 9483 data-bp-mega-panel 9484 hidden 9485 > 9486 <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 9487 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-panel-2" 9488 role="tabpanel" 9489 aria-labelledby="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-tab-2" 9490 class="bp-mega__tab-panel" 9491 data-bp-mega-panel 9492 hidden 9493 > 9494 <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 9495 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-panel-3" 9496 role="tabpanel" 9497 aria-labelledby="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-1-tab-3" 9498 class="bp-mega__tab-panel" 9499 data-bp-mega-panel 9500 hidden 9501 > 9502 <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"> 9503 <a href="/collections/brands-we-love-ettika" class="bp-mega__promo-link"> 9504 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&width=400" alt="Ettika" srcset="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&width=200 200w, //www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&width=400 400w" width="400" height="625" loading="lazy"> 9505</div> 9506 <h4 class="bp-mega__promo-title">Ettika</h4><span class="bp-mega__promo-cta">Shop Now</span> 9507 </a> 9508</div> 9509 9510<div class="bp-mega__promo"> 9511 <a href="/collections/brands-we-love-saint-jo" class="bp-mega__promo-link"> 9512 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&width=400" alt="SAINT JÅ" srcset="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&width=200 200w, //www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&width=400 400w" width="400" height="501" loading="lazy" style="object-position:50.0% 75.781%;"> 9513</div> 9514 <h4 class="bp-mega__promo-title">SAINT JÅ</h4><span class="bp-mega__promo-cta">Shop Now</span> 9515 </a> 9516</div> 9517 9518</div></div></div> 9519 </div> 9520 </div></li><li class="bp-mm-item" data-bp-mm-id="AemlLOW9md1llaXJNV__bp_menu_brands-1"><button type="button" class="bp-mm-item__row" data-open-view="AemlLOW9md1llaXJNV__bp_menu_brands-1">
9521 <span class="bp-mm-item__label">Brands We Love</span> 9522 <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"> 9523 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9524</svg> 9525</span> 9526 </button> 9527 9528 <section class="bp-mm-view" data-view="AemlLOW9md1llaXJNV__bp_menu_brands-1" hidden> 9529 <header class="bp-mm-view__header"> 9530 <button type="button" class="bp-mm-view__back" data-back> 9531 <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"> 9532 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9533</svg> 9534</span> 9535 <span>Brands We Love</span> 9536 </button> 9537 <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"> 9538 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9539 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9540</svg> 9541</button> 9542 </header><div class="bp-mm-view__sections"><section class="bp-mm-section"> 9543 <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"> 9544 <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"> 9545 <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"> 9546 <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"> 9547 <a href="/collections/brands-we-love-ettika" class="bp-mega__promo-link"> 9548 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&width=400" alt="Ettika" srcset="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&width=200 200w, //www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&width=400 400w" width="400" height="625" loading="lazy"> 9549</div> 9550 <h4 class="bp-mega__promo-title">Ettika</h4><span class="bp-mega__promo-cta">Shop Now</span> 9551 </a> 9552</div> 9553 9554<div class="bp-mega__promo"> 9555 <a href="/collections/brands-we-love-saint-jo" class="bp-mega__promo-link"> 9556 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&width=400" alt="SAINT JÅ" srcset="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&width=200 200w, //www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&width=400 400w" width="400" height="501" loading="lazy" style="object-position:50.0% 75.781%;"> 9557</div> 9558 <h4 class="bp-mega__promo-title">SAINT JÅ</h4><span class="bp-mega__promo-cta">Shop Now</span> 9559 </a> 9560</div> 9561 9562</div></section></li> 9563 9564 9565 9566 9567 9568 </ul> 9569 9570 <ul class="bp-mobile-drawer__rail"> 9571 <li> 9572 <a class="bp-mobile-drawer__rail-link" href="/account">
9573 <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"> 9574<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"/> 9575<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"/> 9576</svg> 9577</span> 9578 <span>Login</span> 9579 </a> 9580 </li> 9581 <li> 9582 <a class="bp-mobile-drawer__rail-link" href="/pages/favorites"> 9583 <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"> 9584<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"/> 9585</svg> 9586</span> 9587 <span>Favorites</span> 9588 </a> 9589 </li> 9590 </ul> 9591 </section> 9592 </div> 9593 9594 <div class="bp-mobile-drawer__backdrop" data-close></div> 9595 </details> 9596 </bp-mobile-drawer>
9596<script type="module"> 9597 if (!customElements.get('bp-mobile-drawer')) { 9598 class BPMobileDrawer extends HTMLElement { 9599 connectedCallback() { 9600 // a11y: mark the panel as a modal dialog with an accessible name. 9601 const panel = this.querySelector('.bp-mobile-drawer__panel'); 9602 if (panel) { 9603 panel.setAttribute('role', 'dialog'); 9604 panel.setAttribute('aria-modal', 'true'); 9605 if (!panel.hasAttribute('aria-label')) panel.setAttribute('aria-label', 'Menu'); 9606 panel.tabIndex = -1; 9607 // Move the sub-views to be DIRECT children of the panel. They 9608 // render nested inside the scrolling root <section> (as siblings 9609 // of their .bp-mm-item opener); as a direct panel child a 9610 // sub-view positions cleanly against the panel (full-width 9611 // overlay) and doesn't scroll with the root list. The opener 9612 // still targets it by data-view/data-open-view (block id), not 9613 // DOM nesting, so navigation is unaffected. 9614 panel.querySelectorAll('.bp-mm-view').forEach((view) => { 9615 if (view.parentElement !== panel) panel.appendChild(view); 9616 }); 9617 } 9618 this.addEventListener('click', (e) => { 9619 const opener = e.target.closest('[data-open-view]'); 9620 const back = e.target.closest('[data-back]'); 9621 const close = e.target.closest('[data-close]'); 9622 if (opener) { e.preventDefault(); this.showView(opener.dataset.openView); this._focusActiveView(); return; } 9623 if (back) { this.showView('root'); this._focusActiveView(); return; } 9624 if (close) { this.close(); return; } 9625 }); 9626 const details = this.querySelector('details'); 9627 this._summary = details?.querySelector('summary') || null; 9628 // a11y: Escape closes the drawer. 9629 this._onKeydown = (e) => { 9630 if (e.key === 'Escape' && this.querySelector('details')?.open) { 9631 e.preventDefault(); 9632 this.close(); 9633 } 9634 }; 9635 details?.addEventListener('toggle', () => { 9636 if (details.open) this._onOpen(); 9637 else this._onClose(); 9638 }); 9639 } 9640 _onOpen() { 9641 this.showView('root'); 9642 document.documentElement.style.overflow = 'hidden'; 9643 // a11y: make the rest of the page inert so focus + AT stay in the 9644 // drawer instead of tabbing into the hidden page behind it. Track 9645 // only the elements WE inert (skip any already inert from another 9646 // overlay) so _onClose doesn't un-inert something it didn't set. 9647 this._inerted = []; 9648 document.querySelectorAll('#MainContent, footer, .footer, .bp-footer').forEach((el) => { 9649 if (!el.hasAttribute('inert')) { el.setAttribute('inert', ''); this._inerted.push(el); } 9650 }); 9651 document.addEventListener('keydown', this._onKeydown); 9652 const panel = this.querySelector('.bp-mobile-drawer__panel'); 9653 requestAnimationFrame(() => { 9654 (panel?.querySelector('[data-close], a[href], button') || panel)?.focus(); 9655 }); 9656 } 9657 _onClose() { 9658 // Reset to the top-level nav so reopening never lands mid-sub-view. 9659 this.showView('root'); 9660 document.documentElement.style.overflow = ''; 9661 (this._inerted || []).forEach((el) => el.removeAttribute('inert')); 9662 this._inerted = []; 9663 document.removeEventListener('keydown', this._onKeydown); 9664 // a11y: return focus to the hamburger that opened the drawer. 9665 if (this._summary && typeof this._summary.focus === 'function') this._summary.focus(); 9666 } 9667 // a11y: after a sub-view / Back navigation, move focus into the newly 9668 // active view â otherwise the inert we set on the outgoing view drops 9669 // focus to <body> (the opener/back button that was just focused is 9670 // inside the now-inert view). 9671 _focusActiveView() { 9672 const panel = this.querySelector('.bp-mobile-drawer__panel'); 9673 if (!panel) return; 9674 const active = panel.querySelector('.bp-mm-view:not([hidden])') 9675 || panel.querySelector('.bp-mobile-drawer__view[data-view="root"]'); 9676 if (!active) return; 9677 const target = active.querySelector('[data-back], a[href], button, [tabindex]:not
9677([tabindex="-1"])'); 9678 requestAnimationFrame(() => { (target || panel).focus(); }); 9679 } 9680 showView(name) { 9681 const panel = this.querySelector('.bp-mobile-drawer__panel'); 9682 if (!panel) return; 9683 panel.dataset.activeView = name; 9684 // Simple in-place swap: exactly ONE view is shown at a time, filling 9685 // the whole panel at full width. The native `hidden` attribute both 9686 // removes the inactive views from layout AND drops them from the 9687 // focus order â so there's no overlay slide, no transform, and no 9688 // `inert` bookkeeping (all of which caused the side-by-side / 9689 // trapped-focus bugs). Root and every sub-view are position:absolute 9690 // inset:0 in the panel, so the shown one covers it completely. 9691 const root = this.querySelector('.bp-mobile-drawer__view[data-view="root"]'); 9692 if (root) root.hidden = name !== 'root'; 9693 this.querySelectorAll('.bp-mm-view').forEach((view) => { 9694 view.hidden = view.dataset.view !== name; 9695 }); 9696 panel.scrollTop = 0; 9697 } 9698 close() { 9699 const details = this.querySelector('details'); 9700 if (details) details.open = false; 9701 } 9702 } 9703 customElements.define('bp-mobile-drawer', BPMobileDrawer); 9704 } 9705</script>
9705 9706 9707 9708 9709 </div> 9710 9711 9712 9713<style data-shopify> 9714 .header__underlay { 9715 --color-submenu: rgb(254 255 250 / 1.0); 9716 } 9717</style> 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727 9728 <search-button 9729 class="search-action search-action--hidden-on-menu" 9730 > 9731 <button 9732 on:click="#search-modal/showDialog" 9733 class="button-unstyled header-actions__action" 9734 aria-label="Search" 9735 aria-haspopup="dialog" 9736 > 9737 <span class="hidden"> 9738 Search 9739 </span> 9740 9741 <span class="svg-wrapper "> 9742 <svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg"> 9743<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"/> 9744<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"/> 9745</svg> 9746 9747 </span> 9748 </button> 9749 </search-button> 9750 9751 9752 9753 9754 9755 9756 9757 9758 9759 9760 9761 9762 9763 9764<a 9765 9766 href="/" 9767 class="size-style spacing-style header-logo" 9768 style=" 9769 --size-style-width: ;--size-style-height: ; 9770 --padding-block-start: 0px;--padding-block-end: 0px; 9771 --font-family: var(--font-body--family); 9772 --font-style: var(--font-body--style); 9773 --font-weight: 600; 9774 " 9775 9776> 9777 9778 9779 <span 9780 class="header-logo__image-container header-logo__image-container--original" 9781 data-testid="header-logo" 9782 > 9783 9784 9785 9786 9787 9788 9789 9790 9791 9792 9793 9794 9795 9796 <img src="//www.bostonproper.com/cdn/shop/files/BOS-Logotype-Charcoal_1.png?height=24&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&v=1785187523 1x, //www.bostonproper.com/cdn/shop/files/BOS-Logotype-Charcoal_1.png?height=48&v=1785187523 2x, //www.bostonproper.com/cdn/shop/files/BOS-Logotype-Charcoal_1.png?height=72&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;"> 9797 9798 9799 9800 </span> 9801 9802 9803 9804 9805 <span 9806 class="header-logo__image-container header-logo__image-container--scroll" 9807 data-testid="header-logo-scroll" 9808 > 9809 9810 <span 9811 class="header-logo__image header-logo__image--svg" 9812 role="img" 9813 aria-label="Translation missing: en.Boston Proper accessibility.home" 9814 style="--header-logo-image-height: 24px; --header-logo-image-height-mobile: 18px; --header-logo-image-width: 30px; --header-logo-image-width-mobile: 23px;" 9815 ><svg width="30" height="24" viewBox="0 0 30 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 9816<g clip-path="url(#clip0_152_25204)"> 9817<g clip-path="url(#clip1_152_25204)"> 9818<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"/> 9819<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"/> 9820</g> 9821</g> 9822<defs> 9823<clipPath id="clip0_152_25204"> 9824<rect width="30" height="24" fill="white"/> 9825</clipPath> 9826<clipPath id="clip1_152_25204"> 9827<rect width="30" height="24" fill="white"/> 9828</clipPath> 9829</defs> 9830</svg> 9831</span> 9832 9833 </span> 9834</a> 9835 9836 9837 9838 9839 9840 9841 9842 9843 </div><div 9844 class="header__column header__column--center" 9845 data-testid="header-top-center" 9846 > 9847 9848 9849 9850 9851 9852 9853 9854 9855 9856 9857 <header-menu 9858 ref="headerMenu" 9859 class="header-menu" 9860 9861 data-hydration-key="header-menu" 9862 > 9863 <div class="header-menu__inner"> 9864 <nav 9865 class="menu-list" 9866 aria-label="Primary" 9867 style="--menu-top-level-font-family: var(--font-body--family); 9868--menu-top-level-font-size-desktop: 0.875rem; --menu-top-level-font-style: var(--font-body--style);
9868 --menu-top-level-font-weight: var(--font-body--weight); --menu-top-level-font-case:none; 9869 9870 --menu-top-level-font-size: var(--menu-font-sm--size); --menu-top-level-font-line-height: 9871 var(--menu-font-sm--line-height); 9872 9873--menu-top-level-font-color: var(--color-foreground); --menu-top-level-font-color-rgb: var(--color-foreground-rgb); 9874" 9875 > 9876 9877 <overflow-list 9878 9879 ref="overflowMenu" 9880 9881 9882 class="overflow-menu color-scheme-matches-parent" 9883 9884 9885 minimum-items="2" 9886 9887 9888 data-testid="header-menu-overflow-list" 9889 9890 9891 data-skip-node-update 9892 9893> 9894 <template shadowrootmode="open"> 9895 <link href="//www.bostonproper.com/cdn/shop/t/1516/assets/overflow-list.css?v=16727044177065489451790192827" rel="stylesheet" type="text/css" media="all" /> 9896 9897 <ul part="list"> 9898 <slot></slot> 9899 <slot 9900 name="more" 9901 part="more" 9902 hidden 9903 9904 > 9905 <li 9906 part="more" 9907 > 9908 <button 9909 class="button" 9910 type="button" 9911 tabindex="0" 9912 9913 > 9914 More 9915 </button> 9916 </li> 9917 </slot> 9918 <li 9919 part="placeholder" 9920 hidden 9921 ></li> 9922 </ul> 9923 9924 <div part="overflow"> 9925 <ul part="overflow-list"> 9926 <slot name="overflow"></slot> 9927 </ul> 9928 </div> 9929 </template> 9930 9931 9932 9933 <li 9934 role="presentation" 9935 class="menu-list__list-item bp-menu-item-li" 9936 data-bp-menu-item 9937 9938><a 9939 href="/collections/new-arrivals" 9940 data-skip-node-update="true" 9941 class="menu-list__link" 9942 aria-controls="bp-submenu-AcEtCSXg1K2Q0dGRFQ__bp_menu_new_arrivals" 9943 aria-haspopup="true" 9944 aria-expanded="false" 9945 ref="menuitem" 9946 > 9947 <span class="menu-list__link-title">New Arrivals</span> 9948 </a> 9949 <div class="bp-mega-submenu" id="bp-submenu-AcEtCSXg1K2Q0dGRFQ__bp_menu_new_arrivals"> 9950 <div class="bp-mega-submenu__inner"> 9951 <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column"> 9952 <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-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"> 9953 <p class="bp-mega__heading"><a href="/collections/new-arrivals">Featured Shops</a></p><ul class="bp-mega__links"><li><a href="/collections/featured-shops-layering">The Layering Shop</a></li><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/clothing-dresses">The Dress Code</a></li><li><a href="/collections/occasions-special-occasion">The Occasion Edit</a></li><li><a href="/collections/editors-picks">Editor's Picks</a></li><li><a href="/collections/featured-shop-intricate-details">Intricate Details</a></li><li><a href="/pages/new-to-boston-proper">New to Boston Proper? </a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li></ul></div><div class="bp-mega__column"> 9954 <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-pants-skirts">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"> 9955 <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">
9955Change 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"> 9956 <a href="/collections/the-right-now-edit" class="bp-mega__promo-link"> 9957 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_61.jpg?v=1790170113&width=400" alt="Your Right-Now Wardrobe" srcset="//www.bostonproper.com/cdn/shop/files/Image_61.jpg?v=1790170113&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_61.jpg?v=1790170113&width=400 400w" width="400" height="500" loading="lazy"> 9958</div> 9959 <h4 class="bp-mega__promo-title">Your Right-Now Wardrobe</h4><div class="bp-mega__promo-copy"><p>Up to 35% Off Wear-Now Styles + Free Shipping Limited Time. <br/>Use code: FREESHIP</p></div><span class="bp-mega__promo-cta">Shop Now</span> 9960 </a> 9961</div> 9962 9963<div class="bp-mega__promo"> 9964 <a href="/pages/the-dress-code" class="bp-mega__promo-link"> 9965 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_New_Arrivals_Dress_Code.jpg?v=1787681292&width=400" alt="The Dress Code" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_New_Arrivals_Dress_Code.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_New_Arrivals_Dress_Code.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:47.07% 8.398%;"> 9966</div> 9967 <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> 9968 </a> 9969</div> 9970 9971</div></div> 9972 </div> 9973 </div></li><li class="bp-mm-item" data-bp-mm-id="AcEtCSXg1K2Q0dGRFQ__bp_menu_new_arrivals"><button type="button" class="bp-mm-item__row" data-open-view="AcEtCSXg1K2Q0dGRFQ__bp_menu_new_arrivals"> 9974 <span class="bp-mm-item__label">New Arrivals</span> 9975 <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"> 9976 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9977</svg> 9978</span> 9979 </button> 9980 9981 <section class="bp-mm-view" data-view="AcEtCSXg1K2Q0dGRFQ__bp_menu_new_arrivals" hidden> 9982 <header class="bp-mm-view__header"> 9983 <button type="button" class="bp-mm-view__back" data-back> 9984 <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"> 9985 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9986</svg> 9987</span> 9988 <span>New Arrivals</span> 9989 </button> 9990 <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"> 9991 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9992 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 9993</svg> 9994</button> 9995 </header><div class="bp-mm-view__sections"><section class="bp-mm-section"> 9996 <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-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"> 9997 <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-shops-layering">The Layering Shop</a></li><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/clothing-dresses">The Dress Code</a></li><li><a href="/collections/occasions-special-occasion">The Occasion Edit</a></li><li><a href="/collections/editors-picks">Editor's Picks</a></li><li><a href="/collections/featured-shop-intricate-details">Intricate Details</a></li><li><a href="/pages/new-to-boston-proper">New to Boston Proper? </a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li></ul></section><section class="bp-mm-section"> 9998 <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-pants-skirts">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"> 9999 <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">
9999Change 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"> 10000 <a href="/collections/the-right-now-edit" class="bp-mega__promo-link"> 10001 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_61.jpg?v=1790170113&width=400" alt="Your Right-Now Wardrobe" srcset="//www.bostonproper.com/cdn/shop/files/Image_61.jpg?v=1790170113&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_61.jpg?v=1790170113&width=400 400w" width="400" height="500" loading="lazy"> 10002</div> 10003 <h4 class="bp-mega__promo-title">Your Right-Now Wardrobe</h4><div class="bp-mega__promo-copy"><p>Up to 35% Off Wear-Now Styles + Free Shipping Limited Time. <br/>Use code: FREESHIP</p></div><span class="bp-mega__promo-cta">Shop Now</span> 10004 </a> 10005</div> 10006 10007<div class="bp-mega__promo"> 10008 <a href="/pages/the-dress-code" class="bp-mega__promo-link"> 10009 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_New_Arrivals_Dress_Code.jpg?v=1787681292&width=400" alt="The Dress Code" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_New_Arrivals_Dress_Code.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_New_Arrivals_Dress_Code.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:47.07% 8.398%;"> 10010</div> 10011 <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> 10012 </a> 10013</div> 10014 10015</div></section></li> 10016 10017 10018 10019<li 10020 role="presentation" 10021 class="menu-list__list-item bp-menu-item-li" 10022 data-bp-menu-item 10023 10024><a 10025 href="/collections/clothing" 10026 data-skip-node-update="true" 10027 class="menu-list__link" 10028 aria-controls="bp-submenu-Ab0RsOG9XRC8wSkVoS__bp_menu_clothing" 10029 aria-haspopup="true" 10030 aria-expanded="false" 10031 ref="menuitem" 10032 > 10033 <span class="menu-list__link-title">Clothing</span> 10034 </a> 10035 <div class="bp-mega-submenu" id="bp-submenu-Ab0RsOG9XRC8wSkVoS__bp_menu_clothing"> 10036 <div class="bp-mega-submenu__inner"> 10037 <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column"> 10038 <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"> 10039 <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">Everyday Style</a></li><li><a href="/collections/occasions-night-out">Night Out</a></li><li><a href="/collections/occasions-special-occasion">Special Occasion</a></li><li><a href="/collections/occasions-vacation">Vacation</a></li><li><a href="/collections/occasions-work">Work Style</a></li><li><a href="/collections/occasions-wedding">Wedding Guest</a></li></ul></div><div class="bp-mega__column"> 10040 <p class="bp-mega__heading"><a href="/collections/clothing">Shops</a></p><ul class="bp-mega__links"><li><a href="/collections/clothing-pants-leggings">
10040The Bottoms Guide</a></li><li><a href="/collections/clothing-jeans">The Denim Guide</a></li><li><a href="/pages/the-dress-code">The Dress Code</a></li><li><a href="/pages/essentials-collection">The Essentials Edit</a></li><li><a href="/collections/featured-shops-matching-sets">Matching Sets</a></li><li><a href="/collections/the-suiting-shop">The Suiting Shop</a></li><li><a href="/collections/essentials">The Tops Collection</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li></ul></div><div class="bp-mega__column"> 10041 <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"> 10042 <a href="/collections/sweaters-turtlenecks" class="bp-mega__promo-link"> 10043 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Turtlenecks.jpg?v=1787681293&width=400" alt="Turtlenecks" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Turtlenecks.jpg?v=1787681293&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Turtlenecks.jpg?v=1787681293&width=400 400w" width="400" height="500" loading="lazy" style="object-position:51.66% 34.766%;"> 10044</div> 10045 <h4 class="bp-mega__promo-title">Turtlenecks</h4><div class="bp-mega__promo-copy"><p>A classic made current. Clean, confident, and made for the season.</p></div><span class="bp-mega__promo-cta">Shop Now</span> 10046 </a> 10047</div> 10048 10049<div class="bp-mega__promo"> 10050 <a href="/collections/knit-tops" class="bp-mega__promo-link"> 10051 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Knits.jpg?v=1787681293&width=400" alt="Knit Tops" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Knits.jpg?v=1787681293&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Knits.jpg?v=1787681293&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 17.48%;"> 10052</div> 10053 <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> 10054 </a> 10055</div> 10056 10057</div></div> 10058 </div> 10059 </div></li><li class="bp-mm-item" data-bp-mm-id="Ab0RsOG9XRC8wSkVoS__bp_menu_clothing"><button type="button" class="bp-mm-item__row" data-open-view="Ab0RsOG9XRC8wSkVoS__bp_menu_clothing"> 10060 <span class="bp-mm-item__label">Clothing</span> 10061 <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"> 10062 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10063</svg> 10064</span> 10065 </button> 10066 10067 <section class="bp-mm-view" data-view="Ab0RsOG9XRC8wSkVoS__bp_menu_clothing" hidden> 10068 <header class="bp-mm-view__header"> 10069 <button type="button" class="bp-mm-view__back" data-back> 10070 <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"> 10071 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10072</svg> 10073</span>
10074 <span>Clothing</span> 10075 </button> 10076 <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"> 10077 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10078 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10079</svg> 10080</button> 10081 </header><div class="bp-mm-view__sections"><section class="bp-mm-section"> 10082 <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"> 10083 <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">Everyday Style</a></li><li><a href="/collections/occasions-night-out">Night Out</a></li><li><a href="/collections/occasions-special-occasion">Special Occasion</a></li><li><a href="/collections/occasions-vacation">Vacation</a></li><li><a href="/collections/occasions-work">Work Style</a></li><li><a href="/collections/occasions-wedding">Wedding Guest</a></li></ul></section><section class="bp-mm-section"> 10084 <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/the-dress-code">The Dress Code</a></li><li><a href="/pages/essentials-collection">The Essentials Edit</a></li><li><a href="/collections/featured-shops-matching-sets">Matching Sets</a></li><li><a href="/collections/the-suiting-shop">The Suiting Shop</a></li><li><a href="/collections/essentials">The Tops Collection</a></li><li><a href="/pages/the-jacket-edit">Style Guide: The Jacket Edit</a></li></ul></section><section class="bp-mm-section"> 10085 <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"> 10086 <a href="/collections/sweaters-turtlenecks" class="bp-mega__promo-link"> 10087 <div class="bp-mega__promo-image">
10087<img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Turtlenecks.jpg?v=1787681293&width=400" alt="Turtlenecks" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Turtlenecks.jpg?v=1787681293&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Turtlenecks.jpg?v=1787681293&width=400 400w" width="400" height="500" loading="lazy" style="object-position:51.66% 34.766%;"> 10088</div> 10089 <h4 class="bp-mega__promo-title">Turtlenecks</h4><div class="bp-mega__promo-copy"><p>A classic made current. Clean, confident, and made for the season.</p></div><span class="bp-mega__promo-cta">Shop Now</span> 10090 </a> 10091</div> 10092 10093<div class="bp-mega__promo"> 10094 <a href="/collections/knit-tops" class="bp-mega__promo-link"> 10095 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Knits.jpg?v=1787681293&width=400" alt="Knit Tops" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Knits.jpg?v=1787681293&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Clothing_Knits.jpg?v=1787681293&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 17.48%;"> 10096</div> 10097 <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> 10098 </a> 10099</div> 10100 10101</div></section></li> 10102 10103 10104 10105<li 10106 role="presentation" 10107 class="menu-list__list-item bp-menu-item-li" 10108 data-bp-menu-item 10109 10110><a 10111 href="/pages/all-occasions" 10112 data-skip-node-update="true" 10113 class="menu-list__link" 10114 aria-controls="bp-submenu-ANytpazFVQlZ3RksxN__bp_menu_occasions" 10115 aria-haspopup="true" 10116 aria-expanded="false" 10117 ref="menuitem" 10118 > 10119 <span class="menu-list__link-title">Occasions</span> 10120 </a> 10121 <div class="bp-mega-submenu" id="bp-submenu-ANytpazFVQlZ3RksxN__bp_menu_occasions"> 10122 <div class="bp-mega-submenu__inner"> 10123 <div class="bp-mega bp-mega--image-tiles"><div class="bp-mega__tiles"><a class="bp-mega__tile" href="/collections/occasions-everyday-style"> 10124 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_19.jpg?v=1787764619&width=400" alt="Casual Chic" srcset="//www.bostonproper.com/cdn/shop/files/Image_19.jpg?v=1787764619&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_19.jpg?v=1787764619&width=400 400w" width="400" height="500" loading="lazy" style="object-position:52.148% 9.277%;"> 10125</div> 10126 <p class="bp-mega__tile-title">Casual Chic</p> 10127 <span class="bp-mega__tile-cta">Shop Now</span> 10128 </a><a class="bp-mega__tile" href="/collections/occasions-vacation"> 10129 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_20.jpg?v=1787764642&width=400" alt="Escape in Style" srcset="//www.bostonproper.com/cdn/shop/files/Image_20.jpg?v=1787764642&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_20.jpg?v=1787764642&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 11.816%;"> 10130</div> 10131 <p class="bp-mega__tile-title">Escape in Style</p> 10132 <span class="bp-mega__tile-cta">Shop Now</span> 10133 </a><a class="bp-mega__tile" href="/collections/occasions-special-occasion"> 10134 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_21.jpg?v=1787764672&width=400" alt="RSVP Ready" srcset="//www.bostonproper.com/cdn/shop/files/Image_21.jpg?v=1787764672&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_21.jpg?v=1787764672&width=400 400w" width="400" height="500" loading="lazy" style="object-position:37.012% 15.625%;"> 10135</div> 10136 <p class="bp-mega__tile-title">RSVP Ready</p> 10137 <span class="bp-mega__tile-cta">Shop Now</span> 10138 </a><a class="bp-mega__tile" href="/collections/occasions-work"> 10139 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_22.jpg?v=1787764700&width=400" alt="Power Moves" srcset="//www.bostonproper.com/cdn/shop/files/Image_22.jpg?v=1787764700&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_22.jpg?v=1787764700&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 11.621%;"> 10140</div> 10141 <p class="bp-mega__tile-title">Power Moves</p>
10142 <span class="bp-mega__tile-cta">Shop Now</span> 10143 </a><a class="bp-mega__tile" href="/collections/occasions-night-out"> 10144 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_23.jpg?v=1787764729&width=400" alt="Own the Evening" srcset="//www.bostonproper.com/cdn/shop/files/Image_23.jpg?v=1787764729&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_23.jpg?v=1787764729&width=400 400w" width="400" height="500" loading="lazy" style="object-position:21.387% 20.898%;"> 10145</div> 10146 <p class="bp-mega__tile-title">Own the Evening</p> 10147 <span class="bp-mega__tile-cta">Shop Now</span> 10148 </a><a class="bp-mega__tile" href="/collections/occasions-wedding"> 10149 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_24.jpg?v=1787764753&width=400" alt="Celebrate Beautifully" srcset="//www.bostonproper.com/cdn/shop/files/Image_24.jpg?v=1787764753&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_24.jpg?v=1787764753&width=400 400w" width="400" height="500" loading="lazy" style="object-position:50.586% 11.621%;"> 10150</div> 10151 <p class="bp-mega__tile-title">Celebrate Beautifully</p> 10152 <span class="bp-mega__tile-cta">Shop Now</span> 10153 </a></div></div> 10154 </div> 10155 </div></li><li class="bp-mm-item" data-bp-mm-id="ANytpazFVQlZ3RksxN__bp_menu_occasions"><button type="button" class="bp-mm-item__row" data-open-view="ANytpazFVQlZ3RksxN__bp_menu_occasions"> 10156 <span class="bp-mm-item__label">Occasions</span> 10157 <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"> 10158 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10159</svg> 10160</span> 10161 </button> 10162 10163 <section class="bp-mm-view" data-view="ANytpazFVQlZ3RksxN__bp_menu_occasions" hidden> 10164 <header class="bp-mm-view__header"> 10165 <button type="button" class="bp-mm-view__back" data-back> 10166 <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"> 10167 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10168</svg> 10169</span> 10170 <span>Occasions</span> 10171 </button> 10172 <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"> 10173 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10174 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10175</svg> 10176</button> 10177 </header><div class="bp-mm-view__tiles"><a class="bp-mm-tile" href="/collections/occasions-everyday-style"> 10178 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_19.jpg?v=1787764619&width=400" alt="Casual Chic" srcset="//www.bostonproper.com/cdn/shop/files/Image_19.jpg?v=1787764619&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_19.jpg?v=1787764619&width=400 400w" width="400" height="500" loading="lazy" style="object-position:52.148% 9.277%;"> 10179</span> 10180 <span class="bp-mm-tile__title">Casual Chic</span> 10181 <span class="bp-mm-tile__cta">Shop Now</span> 10182 </a><a class="bp-mm-tile" href="/collections/occasions-vacation"> 10183 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_20.jpg?v=1787764642&width=400" alt="Escape in Style" srcset="//www.bostonproper.com/cdn/shop/files/Image_20.jpg?v=1787764642&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_20.jpg?v=1787764642&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 11.816%;"> 10184</span>
10185 <span class="bp-mm-tile__title">Escape in Style</span> 10186 <span class="bp-mm-tile__cta">Shop Now</span> 10187 </a><a class="bp-mm-tile" href="/collections/occasions-special-occasion"> 10188 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_21.jpg?v=1787764672&width=400" alt="RSVP Ready" srcset="//www.bostonproper.com/cdn/shop/files/Image_21.jpg?v=1787764672&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_21.jpg?v=1787764672&width=400 400w" width="400" height="500" loading="lazy" style="object-position:37.012% 15.625%;"> 10189</span> 10190 <span class="bp-mm-tile__title">RSVP Ready</span> 10191 <span class="bp-mm-tile__cta">Shop Now</span> 10192 </a><a class="bp-mm-tile" href="/collections/occasions-work"> 10193 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_22.jpg?v=1787764700&width=400" alt="Power Moves" srcset="//www.bostonproper.com/cdn/shop/files/Image_22.jpg?v=1787764700&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_22.jpg?v=1787764700&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 11.621%;"> 10194</span> 10195 <span class="bp-mm-tile__title">Power Moves</span> 10196 <span class="bp-mm-tile__cta">Shop Now</span> 10197 </a><a class="bp-mm-tile" href="/collections/occasions-night-out"> 10198 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_23.jpg?v=1787764729&width=400" alt="Own the Evening" srcset="//www.bostonproper.com/cdn/shop/files/Image_23.jpg?v=1787764729&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_23.jpg?v=1787764729&width=400 400w" width="400" height="500" loading="lazy" style="object-position:21.387% 20.898%;"> 10199</span> 10200 <span class="bp-mm-tile__title">Own the Evening</span> 10201 <span class="bp-mm-tile__cta">Shop Now</span> 10202 </a><a class="bp-mm-tile" href="/collections/occasions-wedding"> 10203 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_24.jpg?v=1787764753&width=400" alt="Celebrate Beautifully" srcset="//www.bostonproper.com/cdn/shop/files/Image_24.jpg?v=1787764753&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_24.jpg?v=1787764753&width=400 400w" width="400" height="500" loading="lazy" style="object-position:50.586% 11.621%;"> 10204</span> 10205 <span class="bp-mm-tile__title">Celebrate Beautifully</span> 10206 <span class="bp-mm-tile__cta">Shop Now</span> 10207 </a></div></section></li> 10208 10209 10210 10211<li 10212 role="presentation" 10213 class="menu-list__list-item bp-menu-item-li" 10214 data-bp-menu-item 10215 10216><a 10217 href="/pages/essentials-collection" 10218 data-skip-node-update="true" 10219 class="menu-list__link" 10220 aria-controls="bp-submenu-AVzFzNXNucVZNUytIV__bp_menu_collections" 10221 aria-haspopup="true" 10222 aria-expanded="false" 10223 ref="menuitem" 10224 > 10225 <span class="menu-list__link-title">Collections</span> 10226 </a> 10227 <div class="bp-mega-submenu" id="bp-submenu-AVzFzNXNucVZNUytIV__bp_menu_collections"> 10228 <div class="bp-mega-submenu__inner"> 10229 <div class="bp-mega bp-mega--image-tiles"><div class="bp-mega__tiles"><a class="bp-mega__tile" href="/collections/featured-shops-matching-sets"> 10230 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_15_a1d69794-6955-45f6-b7a6-8c503b9770c5.jpg?v=1789756263&width=400" alt="Matching Sets" srcset="//www.bostonproper.com/cdn/shop/files/Image_15_a1d69794-6955-45f6-b7a6-8c503b9770c5.jpg?v=1789756263&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_15_a1d69794-6955-45f6-b7a6-8c503b9770c5.jpg?v=1789756263&width=400 400w" width="400" height="500" loading="lazy"> 10231</div> 10232 <p class="bp-mega__tile-title">Matching Sets</p> 10233 <span class="bp-mega__tile-cta">Shop Now</span> 10234 </a><a class="bp-mega__tile" href="/collections/clothing-jeans"> 10235 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_15.jpg?v=1787751060&width=400" alt="Denim" srcset="//www.bostonproper.com/cdn/shop/files/Image_15.jpg?v=1787751060&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_15.jpg?v=1787751060&width=400 400w" width="400" height="500" loading="lazy" style="object-position:47.656% 11.621%;"> 10236</div> 10237 <p class="bp-mega__tile-title">Denim</p>
10238 <span class="bp-mega__tile-cta">Shop Now</span> 10239 </a><a class="bp-mega__tile" href="/collections/athleisure-luxe-lounge"> 10240 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_18.jpg?v=1787751146&width=400" alt="Luxe Lounge" srcset="//www.bostonproper.com/cdn/shop/files/Image_18.jpg?v=1787751146&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_18.jpg?v=1787751146&width=400 400w" width="400" height="500" loading="lazy" style="object-position:45.02% 13.77%;"> 10241</div> 10242 <p class="bp-mega__tile-title">Luxe Lounge</p> 10243 <span class="bp-mega__tile-cta">Shop Now</span> 10244 </a><a class="bp-mega__tile" href="/collections/travel"> 10245 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_17.jpg?v=1787751124&width=400" alt="Beyond Travel" srcset="//www.bostonproper.com/cdn/shop/files/Image_17.jpg?v=1787751124&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_17.jpg?v=1787751124&width=400 400w" width="400" height="500" loading="lazy" style="object-position:51.66% 13.477%;"> 10246</div> 10247 <p class="bp-mega__tile-title">Beyond Travel</p> 10248 <span class="bp-mega__tile-cta">Shop Now</span> 10249 </a><a class="bp-mega__tile" href="/collections/charmeuse"> 10250 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_13.jpg?v=1787750993&width=400" alt="Charmeuse" srcset="//www.bostonproper.com/cdn/shop/files/Image_13.jpg?v=1787750993&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_13.jpg?v=1787750993&width=400 400w" width="400" height="500" loading="lazy" style="object-position:43.164% 16.309%;"> 10251</div> 10252 <p class="bp-mega__tile-title">Charmeuse</p> 10253 <span class="bp-mega__tile-cta">Shop Now</span> 10254 </a><a class="bp-mega__tile" href="/collections/the-suiting-shop"> 10255 <div class="bp-mega__tile-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_16.jpg?v=1787751087&width=400" alt="Modern Suiting" srcset="//www.bostonproper.com/cdn/shop/files/Image_16.jpg?v=1787751087&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_16.jpg?v=1787751087&width=400 400w" width="400" height="500" loading="lazy" style="object-position:52.148% 17.578%;"> 10256</div> 10257 <p class="bp-mega__tile-title">Modern Suiting</p> 10258 <span class="bp-mega__tile-cta">Shop Now</span> 10259 </a></div></div> 10260 </div> 10261 </div></li><li class="bp-mm-item" data-bp-mm-id="AVzFzNXNucVZNUytIV__bp_menu_collections"><button type="button" class="bp-mm-item__row" data-open-view="AVzFzNXNucVZNUytIV__bp_menu_collections"> 10262 <span class="bp-mm-item__label">Collections</span> 10263 <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"> 10264 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10265</svg> 10266</span> 10267 </button> 10268 10269 <section class="bp-mm-view" data-view="AVzFzNXNucVZNUytIV__bp_menu_collections" hidden> 10270 <header class="bp-mm-view__header"> 10271 <button type="button" class="bp-mm-view__back" data-back> 10272 <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"> 10273 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10274</svg> 10275</span> 10276 <span>Collections</span> 10277 </button> 10278 <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"> 10279 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10280 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10281</svg> 10282</button> 10283 </header><div class="bp-mm-view__tiles"><a class="bp-mm-tile" href="/collections/featured-shops-matching-sets">
10284 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_15_a1d69794-6955-45f6-b7a6-8c503b9770c5.jpg?v=1789756263&width=400" alt="Matching Sets" srcset="//www.bostonproper.com/cdn/shop/files/Image_15_a1d69794-6955-45f6-b7a6-8c503b9770c5.jpg?v=1789756263&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_15_a1d69794-6955-45f6-b7a6-8c503b9770c5.jpg?v=1789756263&width=400 400w" width="400" height="500" loading="lazy"> 10285</span> 10286 <span class="bp-mm-tile__title">Matching Sets</span> 10287 <span class="bp-mm-tile__cta">Shop Now</span> 10288 </a><a class="bp-mm-tile" href="/collections/clothing-jeans"> 10289 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_15.jpg?v=1787751060&width=400" alt="Denim" srcset="//www.bostonproper.com/cdn/shop/files/Image_15.jpg?v=1787751060&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_15.jpg?v=1787751060&width=400 400w" width="400" height="500" loading="lazy" style="object-position:47.656% 11.621%;"> 10290</span> 10291 <span class="bp-mm-tile__title">Denim</span> 10292 <span class="bp-mm-tile__cta">Shop Now</span> 10293 </a><a class="bp-mm-tile" href="/collections/athleisure-luxe-lounge"> 10294 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_18.jpg?v=1787751146&width=400" alt="Luxe Lounge" srcset="//www.bostonproper.com/cdn/shop/files/Image_18.jpg?v=1787751146&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_18.jpg?v=1787751146&width=400 400w" width="400" height="500" loading="lazy" style="object-position:45.02% 13.77%;"> 10295</span> 10296 <span class="bp-mm-tile__title">Luxe Lounge</span> 10297 <span class="bp-mm-tile__cta">Shop Now</span> 10298 </a><a class="bp-mm-tile" href="/collections/travel"> 10299 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_17.jpg?v=1787751124&width=400" alt="Beyond Travel" srcset="//www.bostonproper.com/cdn/shop/files/Image_17.jpg?v=1787751124&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_17.jpg?v=1787751124&width=400 400w" width="400" height="500" loading="lazy" style="object-position:51.66% 13.477%;"> 10300</span> 10301 <span class="bp-mm-tile__title">Beyond Travel</span> 10302 <span class="bp-mm-tile__cta">Shop Now</span> 10303 </a><a class="bp-mm-tile" href="/collections/charmeuse"> 10304 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_13.jpg?v=1787750993&width=400" alt="Charmeuse" srcset="//www.bostonproper.com/cdn/shop/files/Image_13.jpg?v=1787750993&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_13.jpg?v=1787750993&width=400 400w" width="400" height="500" loading="lazy" style="object-position:43.164% 16.309%;"> 10305</span> 10306 <span class="bp-mm-tile__title">Charmeuse</span> 10307 <span class="bp-mm-tile__cta">Shop Now</span> 10308 </a><a class="bp-mm-tile" href="/collections/the-suiting-shop"> 10309 <span class="bp-mm-tile__image"><img src="//www.bostonproper.com/cdn/shop/files/Image_16.jpg?v=1787751087&width=400" alt="Modern Suiting" srcset="//www.bostonproper.com/cdn/shop/files/Image_16.jpg?v=1787751087&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_16.jpg?v=1787751087&width=400 400w" width="400" height="500" loading="lazy" style="object-position:52.148% 17.578%;"> 10310</span> 10311 <span class="bp-mm-tile__title">Modern Suiting</span> 10312 <span class="bp-mm-tile__cta">Shop Now</span> 10313 </a></div></section></li> 10314 10315 10316 10317<li 10318 role="presentation" 10319 class="menu-list__list-item bp-menu-item-li" 10320 data-bp-menu-item 10321 10322><a 10323 href="/collections/shoes-accessories" 10324 data-skip-node-update="true" 10325 class="menu-list__link" 10326 aria-controls="bp-submenu-ARXIzNlBSeHFvVkpPd__bp_menu_shoes" 10327 aria-haspopup="true" 10328 aria-expanded="false" 10329 ref="menuitem" 10330 >
10331 <span class="menu-list__link-title">Shoes & Accessories</span> 10332 </a> 10333 <div class="bp-mega-submenu" id="bp-submenu-ARXIzNlBSeHFvVkpPd__bp_menu_shoes"> 10334 <div class="bp-mega-submenu__inner"> 10335 <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column"> 10336 <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"> 10337 <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"> 10338 <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"> 10339 <a href="/collections/shoes-boots" class="bp-mega__promo-link"> 10340 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Boots.jpg?v=1787681292&width=400" alt="Boots" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Boots.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Boots.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:48.926% 51.66%;"> 10341</div> 10342 <h4 class="bp-mega__promo-title">Boots</h4><div class="bp-mega__promo-copy"><p>These boots are going places. Refined prints. Rich tonal textures. Over-the-knee.  A new mood for every look.  </p></div><span class="bp-mega__promo-cta">Shop Now</span> 10343 </a> 10344</div> 10345 10346<div class="bp-mega__promo"> 10347 <a href="/collections/accessories-jewelry" class="bp-mega__promo-link"> 10348 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Jewelry.jpg?v=1787681292&width=400" alt="Jewelry" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Jewelry.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Jewelry.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 77.93%;"> 10349</div> 10350 <h4 class="bp-mega__promo-title">Jewelry</h4><div class="bp-mega__promo-copy"><p>Drenched in the details that define Boston Proper. Layered jewels and accent pieces that set the tone.  </p></div><span class="bp-mega__promo-cta">Shop Now</span> 10351 </a> 10352</div> 10353 10354</div></div> 10355 </div> 10356 </div></li><li class="bp-mm-item" data-bp-mm-id="ARXIzNlBSeHFvVkpPd__bp_menu_shoes"><button type="button" class="bp-mm-item__row" data-open-view="ARXIzNlBSeHFvVkpPd__bp_menu_shoes">
10357 <span class="bp-mm-item__label">Shoes & Accessories</span> 10358 <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"> 10359 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10360</svg> 10361</span> 10362 </button> 10363 10364 <section class="bp-mm-view" data-view="ARXIzNlBSeHFvVkpPd__bp_menu_shoes" hidden> 10365 <header class="bp-mm-view__header"> 10366 <button type="button" class="bp-mm-view__back" data-back> 10367 <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"> 10368 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10369</svg> 10370</span> 10371 <span>Shoes & Accessories</span> 10372 </button> 10373 <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"> 10374 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10375 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10376</svg> 10377</button> 10378 </header><div class="bp-mm-view__sections"><section class="bp-mm-section"> 10379 <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"> 10380 <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"> 10381 <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"> 10382 <a href="/collections/shoes-boots" class="bp-mega__promo-link"> 10383 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Boots.jpg?v=1787681292&width=400" alt="Boots" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Boots.jpg?v=1787681292&
10383width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Boots.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:48.926% 51.66%;"> 10384</div> 10385 <h4 class="bp-mega__promo-title">Boots</h4><div class="bp-mega__promo-copy"><p>These boots are going places. Refined prints. Rich tonal textures. Over-the-knee.  A new mood for every look.  </p></div><span class="bp-mega__promo-cta">Shop Now</span> 10386 </a> 10387</div> 10388 10389<div class="bp-mega__promo"> 10390 <a href="/collections/accessories-jewelry" class="bp-mega__promo-link"> 10391 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Jewelry.jpg?v=1787681292&width=400" alt="Jewelry" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Jewelry.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Accessories_Jewelry.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 77.93%;"> 10392</div> 10393 <h4 class="bp-mega__promo-title">Jewelry</h4><div class="bp-mega__promo-copy"><p>Drenched in the details that define Boston Proper. Layered jewels and accent pieces that set the tone.  </p></div><span class="bp-mega__promo-cta">Shop Now</span> 10394 </a> 10395</div> 10396 10397</div></section></li> 10398 10399 10400 10401<li 10402 role="presentation" 10403 class="menu-list__list-item bp-menu-item-li" 10404 data-bp-menu-item 10405 10406><a 10407 href="/collections/sale-clearance" 10408 data-skip-node-update="true" 10409 class="menu-list__link" 10410 aria-controls="bp-submenu-AWFVxNmtRQ2t1ak41R__bp_menu_sale" 10411 aria-haspopup="true" 10412 aria-expanded="false" 10413 ref="menuitem" 10414 > 10415 <span class="menu-list__link-title">Sale & Clearance</span> 10416 </a> 10417 <div class="bp-mega-submenu" id="bp-submenu-AWFVxNmtRQ2t1ak41R__bp_menu_sale"> 10418 <div class="bp-mega-submenu__inner"> 10419 <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column"> 10420 <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"> 10421 <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"> 10422 <p class="bp-mega__heading"><a href="/collections/sale-clearance">Promotions</a></p><ul class="bp-mega__links"><li><a href="/collections/clothing-tops-blouses-tees">Buy one top, get one 50% off</a></li><li><a href="/collections/clearance">Extra 30% off clearance</a></li><li><a href="/collections/fall-trans-cami-promo">Stock Up On Effortless Style</a></li><li><a href="/collections/buy-2-save-20-mix-and-match">Buy 2, Save $20</a></li></ul></div></div><div class="bp-mega__promos"><div class="bp-mega__promo"> 10423 <a href="/collections/new-arrivals" class="bp-mega__promo-link"> 10424 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/bg.jpg?v=1787336860&width=400" alt="Seize The Moment" srcset="//www.bostonproper.com/cdn/shop/files/bg.jpg?v=1787336860&width=200 200w, //www.bostonproper.com/cdn/shop/files/bg.jpg?v=1787336860&width=400 400w" width="400" height="500" loading="lazy"> 10425</div> 10426 <h4 class="bp-mega__promo-title">Seize The Moment</h4><div class="bp-mega__promo-copy"><p>Shipping is on us, but not for long.<br/>Use FREESHIP</p></div><span class="bp-mega__promo-cta">Shop Now</span> 10427 </a> 10428</div> 10429 10430<div class="bp-mega__promo"> 10431 <a href="/collections/clearance" class="bp-mega__promo-link"> 10432 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_55.jpg?v=1789573352&width=400" alt="The Final Find" srcset="//www.bostonproper.com/cdn/shop/files/Image_55.jpg?v=1789573352&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_55.jpg?v=1789573352&width=400 400w" width="400" height="500" loading="lazy"> 10433</div> 10434 <h4 class="bp-mega__promo-title">The Final Find</h4><div class="bp-mega__promo-copy"><p>Take an extra 30% off Chic Clearanceâtimeless pieces, final sizes, rare finds. <br/>Use code: EXTRA30</p></div><span class="bp-mega__promo-cta">Shop Now</span> 10435 </a> 10436</div> 10437 10438</div></div> 10439 </div> 10440 </div></li><li class="bp-mm-item" data-bp-mm-id="AWFVxNmtRQ2t1ak41R__bp_menu_sale"><button type="button" class="bp-mm-item__row" data-open-view="AWFVxNmtRQ2t1ak41R__bp_menu_sale">
10441 <span class="bp-mm-item__label">Sale & Clearance</span> 10442 <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"> 10443 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10444</svg> 10445</span> 10446 </button> 10447 10448 <section class="bp-mm-view" data-view="AWFVxNmtRQ2t1ak41R__bp_menu_sale" hidden> 10449 <header class="bp-mm-view__header"> 10450 <button type="button" class="bp-mm-view__back" data-back> 10451 <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"> 10452 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10453</svg> 10454</span> 10455 <span>Sale & Clearance</span> 10456 </button> 10457 <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"> 10458 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10459 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10460</svg> 10461</button> 10462 </header><div class="bp-mm-view__sections"><section class="bp-mm-section"> 10463 <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"> 10464 <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"> 10465 <p class="bp-mm-section__heading"><a href="/collections/sale-clearance">Promotions</a></p><ul class="bp-mm-section__links"><li><a href="/collections/clothing-tops-blouses-tees">Buy one top, get one 50% off</a></li><li><a href="/collections/clearance">Extra 30% off clearance</a></li><li><a href="/collections/fall-trans-cami-promo">Stock Up On Effortless Style</a></li><li><a href="/collections/buy-2-save-20-mix-and-match">Buy 2, Save $20</a></li></ul></section></div><div class="bp-mm-view__promos"><div class="bp-mega__promo"> 10466 <a href="/collections/new-arrivals" class="bp-mega__promo-link"> 10467 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/bg.jpg?v=1787336860&width=400" alt="Seize The Moment" srcset="//www.bostonproper.com/cdn/shop/files/bg.jpg?v=1787336860&width=200 200w, //www.bostonproper.com/cdn/shop/files/bg.jpg?v=1787336860&width=400 400w" width="400" height="500" loading="lazy"> 10468</div> 10469 <h4 class="bp-mega__promo-title">Seize The Moment</h4><div class="bp-mega__promo-copy"><p>Shipping is on us, but not for long.<br/>Use FREESHIP</p></div><span class="bp-mega__promo-cta">Shop Now</span> 10470 </a> 10471</div> 10472 10473<div class="bp-mega__promo"> 10474 <a href="/collections/clearance" class="bp-mega__promo-link"> 10475 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Image_55.jpg?v=1789573352&width=400" alt="The Final Find" srcset="//www.bostonproper.com/cdn/shop/files/Image_55.jpg?v=1789573352&width=200 200w, //www.bostonproper.com/cdn/shop/files/Image_55.jpg?v=1789573352&width=400 400w" width="400" height="500" loading="lazy"> 10476</div> 10477 <h4 class="bp-mega__promo-title">The Final Find</h4><div class="bp-mega__promo-copy"><p>Take an extra 30% off Chic Clearanceâtimeless pieces, final sizes, rare finds. <br/>Use code: EXTRA30</p></div><span class="bp-mega__promo-cta">Shop Now</span> 10478 </a> 10479</div> 10480 10481</div></section></li> 10482 10483 10484 10485<li 10486 role="presentation" 10487 class="menu-list__list-item bp-menu-item-li" 10488 data-bp-menu-item 10489 10490><a 10491 href="/blogs/styleedit" 10492 data-skip-node-update="true" 10493 class="menu-list__link" 10494 aria-controls="bp-submenu-ASVd5SE91ZGUwR3ZhZ__bp_menu_styleedit" 10495 aria-haspopup="true" 10496 aria-expanded="false" 10497 ref="menuitem" 10498 >
10499 <span class="menu-list__link-title">Discover</span> 10500 </a> 10501 <div class="bp-mega-submenu" id="bp-submenu-ASVd5SE91ZGUwR3ZhZ__bp_menu_styleedit"> 10502 <div class="bp-mega-submenu__inner"> 10503 <div class="bp-mega bp-mega--columns-promos"><div class="bp-mega__columns"><div class="bp-mega__column"> 10504 <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"> 10505 <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"> 10506 <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"> 10507 <a href="/pages/sheryls-loves" class="bp-mega__promo-link"> 10508 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Sheryls_Loves.jpg?v=1787681292&width=400" alt="Sherylâs Loves" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Sheryls_Loves.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Sheryls_Loves.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 14.355%;"> 10509</div> 10510 <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.â âSheryl, Editor-in-Chic </p></div><span class="bp-mega__promo-cta">Shop Now</span> 10511 </a> 10512</div> 10513 10514<div class="bp-mega__promo"> 10515 <a href="/pages/digital-catalog" class="bp-mega__promo-link"> 10516 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Catalog.jpg?v=1787681292&width=400" alt="Digital Catalog" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Catalog.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Catalog.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:68.848% 22.363%;"> 10517</div> 10518 <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. </p></div><span class="bp-mega__promo-cta">Shop Now</span> 10519 </a> 10520</div> 10521 10522</div></div> 10523 </div> 10524 </div></li><li class="bp-mm-item" data-bp-mm-id="ASVd5SE91ZGUwR3ZhZ__bp_menu_styleedit"><button type="button" class="bp-mm-item__row" data-open-view="ASVd5SE91ZGUwR3ZhZ__bp_menu_styleedit"> 10525 <span class="bp-mm-item__label">Discover</span> 10526 <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"> 10527 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10528</svg> 10529</span> 10530 </button> 10531 10532 <section class="bp-mm-view" data-view="ASVd5SE91ZGUwR3ZhZ__bp_menu_styleedit" hidden> 10533 <header class="bp-mm-view__header"> 10534 <button type="button" class="bp-mm-view__back" data-back>
10535 <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"> 10536 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10537</svg> 10538</span> 10539 <span>Discover</span> 10540 </button> 10541 <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"> 10542 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10543 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10544</svg> 10545</button> 10546 </header><div class="bp-mm-view__sections"><section class="bp-mm-section"> 10547 <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"> 10548 <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"> 10549 <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"> 10550 <a href="/pages/sheryls-loves" class="bp-mega__promo-link"> 10551 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Sheryls_Loves.jpg?v=1787681292&width=400" alt="Sherylâs Loves" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Sheryls_Loves.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Sheryls_Loves.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:49.121% 14.355%;"> 10552</div> 10553 <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.â âSheryl, Editor-in-Chic </p></div><span class="bp-mega__promo-cta">Shop Now</span> 10554 </a> 10555</div> 10556 10557<div class="bp-mega__promo"> 10558 <a href="/pages/digital-catalog" class="bp-mega__promo-link"> 10559 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Catalog.jpg?v=1787681292&width=400" alt="Digital Catalog" srcset="//www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Catalog.jpg?v=1787681292&width=200 200w, //www.bostonproper.com/cdn/shop/files/Fly_Down_Style_Edit_Catalog.jpg?v=1787681292&width=400 400w" width="400" height="500" loading="lazy" style="object-position:68.848% 22.363%;"> 10560</div> 10561 <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. </p></div><span class="bp-mega__promo-cta">Shop Now</span> 10562 </a> 10563</div> 10564 10565</div></section></li> 10566 10567 10568 10569<li 10570 role="presentation" 10571 class="menu-list__list-item bp-menu-item-li" 10572 data-bp-menu-item 10573 10574><a 10575 href="/collections/brands-we-love" 10576 data-skip-node-update="true" 10577 class="menu-list__link" 10578 aria-controls="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands" 10579 aria-haspopup="true" 10580 aria-expanded="false" 10581 ref="menuitem" 10582 >
10583 <span class="menu-list__link-title">Brands We Love</span> 10584 </a> 10585 <div class="bp-mega-submenu" id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands"> 10586 <div class="bp-mega-submenu__inner"> 10587 <div class="bp-mega bp-mega--tabs-promos"><div class="bp-mega__tabs" data-bp-mega-tabs data-bp-tab-columns="2"> 10588 <ul class="bp-mega__tabs-list" role="tablist"><li role="presentation"> 10589 <button 10590 type="button" 10591 role="tab" 10592 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-tab-0" 10593 class="bp-mega__tab is-active" 10594 aria-controls="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-panel-0" 10595 aria-selected="true" 10596 data-bp-mega-tab 10597 > 10598 <span class="bp-mega__tab-label">BRANDS WE LOVE</span> 10599 <span class="bp-mega__tab-chevron" aria-hidden="true"> 10600 <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> 10601 <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"/> 10602 <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"/> 10603 </svg> 10604 </span> 10605 </button> 10606 </li><li role="presentation"> 10607 <button 10608 type="button" 10609 role="tab" 10610 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-tab-1" 10611 class="bp-mega__tab" 10612 aria-controls="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-panel-1" 10613 aria-selected="false" 10614 data-bp-mega-tab 10615 > 10616 <span class="bp-mega__tab-label">JEWELRY & ACCESSORIES</span> 10617 <span class="bp-mega__tab-chevron" aria-hidden="true"> 10618 <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> 10619 <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"/> 10620 <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"/> 10621 </svg> 10622 </span> 10623 </button> 10624 </li><li role="presentation"> 10625 <button 10626 type="button" 10627 role="tab" 10628 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-tab-2" 10629 class="bp-mega__tab" 10630 aria-controls="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-panel-2" 10631 aria-selected="false" 10632 data-bp-mega-tab 10633 >
10634 <span class="bp-mega__tab-label">ATHLEISURE</span> 10635 <span class="bp-mega__tab-chevron" aria-hidden="true"> 10636 <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> 10637 <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"/> 10638 <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"/> 10639 </svg> 10640 </span> 10641 </button> 10642 </li><li role="presentation"> 10643 <button 10644 type="button" 10645 role="tab" 10646 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-tab-3" 10647 class="bp-mega__tab" 10648 aria-controls="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-panel-3" 10649 aria-selected="false" 10650 data-bp-mega-tab 10651 > 10652 <span class="bp-mega__tab-label">HEALTH & BEAUTY</span> 10653 <span class="bp-mega__tab-chevron" aria-hidden="true"> 10654 <svg width="20" height="20" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> 10655 <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"/> 10656 <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"/> 10657 </svg> 10658 </span> 10659 </button> 10660 </li></ul> 10661 10662 <div class="bp-mega__tabs-panels"><div 10663 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-panel-0" 10664 role="tabpanel" 10665 aria-labelledby="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-tab-0" 10666 class="bp-mega__tab-panel is-active" 10667 data-bp-mega-panel 10668 10669 > 10670 <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">
10670Change 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 10671 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-panel-1" 10672 role="tabpanel" 10673 aria-labelledby="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-tab-1" 10674 class="bp-mega__tab-panel" 10675 data-bp-mega-panel 10676 hidden 10677 > 10678 <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 10679 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-panel-2" 10680 role="tabpanel" 10681 aria-labelledby="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-tab-2" 10682 class="bp-mega__tab-panel" 10683 data-bp-mega-panel 10684 hidden 10685 > 10686 <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 10687 id="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-panel-3" 10688 role="tabpanel" 10689 aria-labelledby="bp-submenu-AemlLOW9md1llaXJNV__bp_menu_brands-tab-3" 10690 class="bp-mega__tab-panel" 10691 data-bp-mega-panel 10692 hidden 10693 > 10694 <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"> 10695 <a href="/collections/brands-we-love-ettika" class="bp-mega__promo-link"> 10696 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&width=400" alt="Ettika" srcset="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&width=200 200w, //www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&width=400 400w" width="400" height="625" loading="lazy"> 10697</div> 10698 <h4 class="bp-mega__promo-title">Ettika</h4><span class="bp-mega__promo-cta">Shop Now</span> 10699 </a> 10700</div> 10701 10702<div class="bp-mega__promo"> 10703 <a href="/collections/brands-we-love-saint-jo" class="bp-mega__promo-link"> 10704 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&width=400" alt="SAINT JÅ" srcset="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&width=200 200w, //www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&width=400 400w" width="400" height="501" loading="lazy" style="object-position:50.0% 75.781%;"> 10705</div> 10706 <h4 class="bp-mega__promo-title">SAINT JÅ</h4><span class="bp-mega__promo-cta">Shop Now</span> 10707 </a> 10708</div> 10709 10710</div></div></div> 10711 </div> 10712 </div></li><li class="bp-mm-item" data-bp-mm-id="AemlLOW9md1llaXJNV__bp_menu_brands"><button type="button" class="bp-mm-item__row" data-open-view="AemlLOW9md1llaXJNV__bp_menu_brands">
10713 <span class="bp-mm-item__label">Brands We Love</span> 10714 <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"> 10715 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10716</svg> 10717</span> 10718 </button> 10719 10720 <section class="bp-mm-view" data-view="AemlLOW9md1llaXJNV__bp_menu_brands" hidden> 10721 <header class="bp-mm-view__header"> 10722 <button type="button" class="bp-mm-view__back" data-back> 10723 <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"> 10724 <path d="M11 5.5L7 9.5L3 5.5" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10725</svg> 10726</span> 10727 <span>Brands We Love</span> 10728 </button> 10729 <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"> 10730 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10731 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 10732</svg> 10733</button> 10734 </header><div class="bp-mm-view__sections"><section class="bp-mm-section"> 10735 <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"> 10736 <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"> 10737 <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"> 10738 <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"> 10739 <a href="/collections/brands-we-love-ettika" class="bp-mega__promo-link"> 10740 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&width=400" alt="Ettika" srcset="//www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&width=200 200w, //www.bostonproper.com/cdn/shop/files/Ettika_flydown.jpg?v=1733336269&width=400 400w" width="400" height="625" loading="lazy"> 10741</div> 10742 <h4 class="bp-mega__promo-title">Ettika</h4><span class="bp-mega__promo-cta">Shop Now</span> 10743 </a> 10744</div> 10745 10746<div class="bp-mega__promo"> 10747 <a href="/collections/brands-we-love-saint-jo" class="bp-mega__promo-link"> 10748 <div class="bp-mega__promo-image"><img src="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&width=400" alt="SAINT JÅ" srcset="//www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&width=200 200w, //www.bostonproper.com/cdn/shop/files/10271_Saint-Jo_flydown_3.jpg?v=1785254177&width=400 400w" width="400" height="501" loading="lazy" style="object-position:50.0% 75.781%;"> 10749</div> 10750 <h4 class="bp-mega__promo-title">SAINT JÅ</h4><span class="bp-mega__promo-cta">Shop Now</span> 10751 </a> 10752</div> 10753 10754</div></section></li> 10755 10756 10757 10758 10759 10760 <li 10761 class="menu-list__list-item" 10762 role="presentation" 10763 slot="more" 10764 on:focus="/activate" 10765 on:blur="/deactivate"
10766 on:pointerenter="/activate" 10767 on:pointerleave="/deactivate" 10768 ><button class="menu-list__link button-unstyled"> 10769 <span class="menu-list__link-title">More</span> 10770 </button> 10771 </li> 10772 10773</overflow-list> 10774 10775 </nav> 10776 </div> 10777 10778
10778<script 10779 src="//www.bostonproper.com/cdn/shop/t/1516/assets/header-menu.js?v=13599797148522725401790192827" 10780 type="module" 10781 fetchpriority="low" 10782 ></script>
10782 10783 </header-menu> 10784 10785 10786<style data-shopify> 10787 .header__underlay { 10788 --color-submenu: rgb(254 255 250 / 1.0); 10789 } 10790</style> 10791 10792 10793 10794 10795 10796 10797 10798 </div><div 10799 class="header__column header__column--right" 10800 data-testid="header-top-right" 10801 > 10802 10803 10804 10805 10806 10807 10808 10809 10810 10811 10812 10813 10814 10815 <search-button 10816 class="search-action search-action--hidden-on-drawer" 10817 > 10818 <button 10819 on:click="#search-modal/showDialog" 10820 class="button-unstyled header-actions__action" 10821 aria-label="Search" 10822 aria-haspopup="dialog" 10823 > 10824 <span class="hidden"> 10825 Search 10826 </span> 10827 10828 <span class="svg-wrapper "> 10829 <svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg"> 10830<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"/> 10831<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"/> 10832</svg> 10833 10834 </span> 10835 </button> 10836 </search-button> 10837 10838 10839 10840 10841 10842 10843 10844 10845 10846 10847
10848<script 10849 type="module" 10850 src="//www.bostonproper.com/cdn/shop/t/1516/assets/cart-icon.js?v=157241182139685326961790192827" 10851 fetchpriority="low" 10852></script>
10852 10853 10854 10855 10856 10857<header-actions 10858 10859 data-bp-mobile-account="hamburger"> 10860 10861<bp-saved-drawer class="bp-saved-drawer" data-hydration-key="bp-saved-drawer"> 10862 <button 10863 type="button" 10864 class="bp-saved-drawer__trigger header-actions__action" 10865 data-bp-saved-open 10866 aria-haspopup="dialog" 10867 aria-label="Saved for later" 10868 ><svg width="24" height="24" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> 10869 <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"/> 10870 </svg> 10871 <span class="bp-saved-drawer__trigger-count" data-bp-saved-trigger-count hidden></span> 10872 </button> 10873 10874 <dialog class="bp-saved-drawer__dialog" data-bp-saved-dialog aria-label="Saved for Later"> 10875 <header class="bp-saved-drawer__header"> 10876 <h2 class="bp-saved-drawer__heading"> 10877 <span class="bp-saved-drawer__bubble" data-bp-saved-bubble>0</span> 10878 Saved for Later 10879 </h2> 10880 <button type="button" class="bp-saved-drawer__close" data-bp-saved-close aria-label="Close"> 10881 <svg width="20" height="20" viewBox="0 0 20 20" fill="none" aria-hidden="true"> 10882 <path d="M5 5l10 10M15 5L5 15" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/> 10883 </svg> 10884 </button> 10885 </header> 10886 10887 <div class="bp-saved-drawer__body"> 10888 <div class="bp-saved-drawer__loading" data-bp-saved-loading hidden> 10889 <span class="bp-saved-drawer__spinner" aria-hidden="true"></span> 10890 <p>Loading your saved itemsâ¦</p> 10891 </div> 10892 10893 <div class="bp-saved-drawer__empty" data-bp-saved-empty> 10894 <p>No saved items yet.</p> 10895 <p class="bp-saved-drawer__empty-help">Tap the bookmark on any bag item to save it for later.</p> 10896 </div> 10897 10898 <ul class="bp-saved-drawer__list" data-bp-saved-list hidden></ul><template data-bp-saved-template> 10899 <li class="bp-saved-drawer__card" data-bp-saved-card> 10900 <a class="bp-saved-drawer__image" data-bp-card-link> 10901 <img alt="" data-bp-card-image> 10902 </a> 10903 <div class="bp-saved-drawer__details"> 10904 <div class="bp-saved-drawer__title-row"> 10905 <h3 class="bp-saved-drawer__name"><a data-bp-card-link></a></h3> 10906 <span class="bp-saved-drawer__price" data-bp-card-price></span> 10907 </div> 10908 <p class="bp-saved-drawer__variant" data-bp-card-variant></p> 10909 <ul class="bp-saved-drawer__props" data-bp-card-props></ul> 10910 <div class="bp-saved-drawer__actions"> 10911 <button type="button" class="bp-saved-drawer__btn bp-saved-drawer__btn--primary" data-bp-card-move>Move to Bag</button> 10912 <button type="button" class="bp-saved-drawer__btn bp-saved-drawer__btn--secondary" data-bp-card-remove>Remove</button> 10913 </div> 10914 </div> 10915 </li> 10916 </template> 10917 </div> 10918 </dialog> 10919</bp-saved-drawer> 10920 10921<style data-shopify> 10922 bp-saved-drawer { display: contents; } 10923 10924 .bp-saved-drawer__trigger { 10925 position: relative; 10926 background: transparent; 10927 border: 0; 10928 padding: 0; 10929 cursor: pointer; 10930 color: var(--color-foreground); 10931 display: inline-flex; 10932 align-items: center; 10933 justify-content: center; 10934 width: 44px; 10935 height: 44px; 10936 } 10937 .bp-saved-drawer__trigger svg { width: 24px; height: 24px; display: block; } 10938 .bp-saved-drawer__trigger-count { 10939 position: absolute; 10940 top: 4px; 10941 right: 4px; 10942 min-width: 18px; 10943 height: 18px; 10944 padding: 0 5px; 10945 /* 18Ã18 circular notification badge â see matching note in 10946 snippets/bp-cart-drawer.liquid. Kept as a circle, not squared. */ 10947 border-radius: 50%; 10948 background: #EBAE55; 10949 /* Dark ink on the gold badge â white on #EBAE55 is only 1.96:1 (fails 10950 WCAG). Matches the cart trigger-count badge. */ 10951 color: var(--bp-color-text); 10952 font-family: var(--bp-font-body); 10953 font-size: 11px; 10954 font-weight: 500; 10955 display: inline-flex; 10956 align-items: center; 10957 justify-content: center; 10958 } 10959 .bp-saved-drawer__trigger-count[hidden] { display: none; } 10960 /* Loading badge â shown while we wait for Swym to reconcile, so the count 10961 never briefly shows a stale/wrong number. A quiet pulse on the empty 10962 badge; the real number replaces it once synced. */ 10963 .bp-saved-drawer__trigger-count.is-loading { 10964 background: rgba(23, 22, 9, 0.18); 10965 min-width: 12px; 10966 height: 12px; 10967 padding: 0; 10968 top: 6px; 10969 right: 6px; 10970 animation: bp-saved-badge-pulse 0.9s ease-in-out infinite; 10971 } 10972 @keyframes bp-saved-badge-pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 0.9; } } 10973 @media (prefers-reduced-motion: reduce) { 10974 .bp-saved-drawer__trigger-count.is-loading { animation: none; opacity: 0.5; } 10975 } 10976 10977 .bp-saved-drawer__dialog { 10978 position: fixed; 10979 inset: 0 0 0 auto; 10980 margin: 0; 10981 padding: 0; 10982 border: 0; 10983 width: calc(100vw / 3); 10984 min-width: 480px; 10985 max-width: 100vw; 10986 height: 100dvh; 10987 max-height: 100dvh; 10988 background: var(--bp-color-bg-page); 10989 color: var(--bp-color-text);
10990 box-shadow: -8px 0 30px rgb(0 0 0 / 0.12); 10991 overflow: hidden; 10992 font-family: var(--bp-font-body); 10993 z-index: 9999; 10994 } 10995 .bp-saved-drawer__dialog[open] { 10996 display: flex; 10997 flex-direction: column; 10998 animation: bpDrawerSlideIn 0.25s cubic-bezier(0.4, 0, 0.2, 1) forwards; 10999 } 11000 .bp-saved-drawer__dialog.is-closing { 11001 animation: bpDrawerSlideOut 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards; 11002 } 11003 .bp-saved-drawer__dialog::backdrop { background: rgb(0 0 0 / 0.3); } 11004 @media (max-width: 749px) { 11005 .bp-saved-drawer__dialog { width: 100vw; min-width: 0; } 11006 } 11007 11008 .bp-saved-drawer__header { 11009 flex: 0 0 auto; 11010 display: flex; 11011 align-items: center; 11012 justify-content: space-between; 11013 padding: 20px 24px; 11014 border-bottom: 1px solid rgba(23, 22, 9, 0.08); 11015 background: var(--bp-color-bg-page); 11016 } 11017 .bp-saved-drawer__heading { 11018 margin: 0; 11019 display: inline-flex; 11020 align-items: center; 11021 gap: 12px; 11022 color: var(--bp-color-text); 11023 font-family: var(--bp-font-display); 11024 font-size: 28px; 11025 font-weight: 300; 11026 line-height: 120%; 11027 letter-spacing: -0.56px; 11028 } 11029 .bp-saved-drawer__bubble { 11030 display: inline-flex; 11031 align-items: center; 11032 justify-content: center; 11033 width: 32px; 11034 height: 32px; 11035 border-radius: 50%; 11036 background: #EBAE55; 11037 /* Dark ink on the gold badge â #fff on #EBAE55 is only 1.96:1 (WCAG fail). 11038 #171609 clears AA at 9.3:1. Same fix already applied to the cart count 11039 badge (QA 7/27, contrast audit â last of the gold-badge group). */ 11040 color: var(--bp-color-text, #171609); 11041 font-family: var(--bp-font-body); 11042 font-size: 14px; 11043 font-weight: 500; 11044 } 11045 .bp-saved-drawer__close { 11046 background: transparent; 11047 border: 0; 11048 padding: 0; 11049 width: 32px; 11050 height: 32px; 11051 cursor: pointer; 11052 color: var(--bp-color-text); 11053 display: inline-flex; 11054 align-items: center; 11055 justify-content: center; 11056 } 11057 .bp-saved-drawer__close:hover { opacity: 0.6; } 11058 11059 .bp-saved-drawer__body { 11060 flex: 1 1 auto; 11061 overflow-y: auto; 11062 padding: 0 24px 24px; 11063 } 11064 .bp-saved-drawer__empty { 11065 padding: 48px 0; 11066 text-align: center; 11067 color: var(--bp-color-body-copy); 11068 } 11069 .bp-saved-drawer__loading { 11070 padding: 48px 0; 11071 text-align: center; 11072 color: var(--bp-color-body-copy); 11073 display: flex; 11074 flex-direction: column; 11075 align-items: center; 11076 gap: 12px; 11077 } 11078 .bp-saved-drawer__loading[hidden] { display: none; } 11079 .bp-saved-drawer__spinner { 11080 width: 28px; 11081 height: 28px; 11082 border: 2px solid rgba(23, 22, 9, 0.18); 11083 border-top-color: var(--bp-color-text, #171609); 11084 border-radius: 50%; 11085 animation: bp-saved-spin 0.7s linear infinite; 11086 } 11087 @keyframes bp-saved-spin { to { transform: rotate(360deg); } } 11088 @media (prefers-reduced-motion: reduce) { 11089 .bp-saved-drawer__spinner { animation-duration: 1.6s; } 11090 } 11091 .bp-saved-drawer__empty-help { 11092 margin-top: 4px; 11093 color: var(--bp-color-body-copy); 11094 font-size: 13px; 11095 } 11096 11097 .bp-saved-drawer__list { 11098 list-style: none; 11099 margin: 0; 11100 padding: 0; 11101 display: flex; 11102 flex-direction: column; 11103 } 11104 11105 .bp-saved-drawer__card { 11106 display: grid; 11107 grid-template-columns: 110px 1fr; 11108 gap: 16px; 11109 padding: 20px 0; 11110 border-bottom: 1px solid rgba(23, 22, 9, 0.08); 11111 } 11112 .bp-saved-drawer__card:last-child { border-bottom: 0; } 11113 11114 .bp-saved-drawer__image { 11115 display: block; 11116 width: 110px; 11117 aspect-ratio: 4 / 5; 11118 background: var(--bp-color-bg-cream); 11119 overflow: hidden; 11120 } 11121 .bp-saved-drawer__image img { 11122 width: 100%; 11123 height: 100%; 11124 object-fit: cover; 11125 display: block; 11126 } 11127 .bp-saved-drawer__details { 11128 display: flex; 11129 flex-direction: column; 11130 gap: 6px; 11131 min-width: 0; 11132 } 11133 .bp-saved-drawer__title-row { 11134 display: flex; 11135 justify-content: space-between; 11136 gap: 12px; 11137 align-items: baseline; 11138 } 11139 .bp-saved-drawer__name { 11140 margin: 0; 11141 font-family: var(--bp-font-body); 11142 font-size: 14px; 11143 font-weight: 700; 11144 line-height: 145%; 11145 letter-spacing: -0.14px; 11146 color: var(--bp-color-text); 11147 } 11148 .bp-saved-drawer__name a { color: inherit; text-decoration: none; } 11149 .bp-saved-drawer__price { 11150 flex: 0 0 auto; 11151 font-size: 14px; 11152 font-weight: 700; 11153 color: var(--bp-color-text); 11154 } 11155 .bp-saved-drawer__variant { 11156 margin: 0; 11157 color: var(--bp-color-body-copy); 11158 font-size: 13px; 11159 } 11160 .bp-saved-drawer__props { 11161 list-style: none; 11162 margin: 4px 0 0; 11163 padding: 0; 11164 display: flex; 11165 flex-wrap: wrap; 11166 gap: 6px; 11167 } 11168 .bp-saved-drawer__props li { 11169 background: var(--bp-color-bg-cream); 11170 padding: 2px 8px; 11171 font-size: 11px; 11172 font-weight: 700; 11173 letter-spacing: 0.04em; 11174 text-transform: uppercase; 11175 color: var(--bp-color-text); 11176 } 11177 .bp-saved-drawer__actions { 11178 margin-top: 10px; 11179 display: flex; 11180 gap: 8px; 11181 flex-wrap: wrap; 11182 } 11183 .bp-saved-drawer__btn { 11184 height: 40px; 11185 padding: 0 16px; 11186 border: 1px solid var(--bp-color-text); 11187 cursor: pointer; 11188 font-family: var(--bp-font-body); 11189 font-size: 13px; 11190 font-weight: 500; 11191 letter-spacing: -0.13px; 11192 transition: opacity 0.2s ease, background 0.2s ease; 11193 } 11194 .bp-saved-drawer__btn--primary { 11195 background: var(--bp-color-text); 11196 color: var(--bp-color-cta-text); 11197 } 11198 .bp-saved-drawer__btn--primary:hover { opacity: 0.85; } 11199 .bp-saved-drawer__btn--primary:disabled { opacity: 0.4; cursor: wait; } 11200 /* Sold-out Move button: stays disabled + relabelled, no hover lift. */ 11201 .bp-saved-drawer__btn--soldout, 11202 .bp-saved-drawer__btn--primary.bp-saved-drawer__btn--soldout:disabled { 11203 opacity: 0.4;
11204 cursor: not-allowed; 11205 } 11206 .bp-saved-drawer__btn--secondary { 11207 background: var(--bp-color-bg-page); 11208 color: var(--bp-color-text); 11209 } 11210 .bp-saved-drawer__btn--secondary:hover { background: var(--bp-color-bg-cream); } 11211 /* Sold-out marker â mirrors the cart line's unavailable treatment 11212 (snippets/bp-cart-line-item.liquid), BP promo red. */ 11213 .bp-saved-drawer__unavailable { 11214 margin: 4px 0 0; 11215 font-family: var(--bp-font-body); 11216 font-size: 12px; 11217 font-weight: 700; 11218 letter-spacing: 0.04em; 11219 text-transform: uppercase; 11220 color: var(--bp-color-promo, #B5341B); 11221 } 11222 .bp-saved-drawer__card.is-unavailable .bp-saved-drawer__image, 11223 .bp-saved-drawer__card.is-unavailable .bp-saved-drawer__name { 11224 opacity: 0.55; 11225 } 11226</style> 11227
11228<script type="module"> 11229 if (!customElements.get('bp-saved-drawer')) { 11230 class BpSavedDrawer extends HTMLElement { 11231 connectedCallback() { 11232 this.dialog = this.querySelector('[data-bp-saved-dialog]'); 11233 this.list = this.querySelector('[data-bp-saved-list]'); 11234 this.empty = this.querySelector('[data-bp-saved-empty]'); 11235 this.loading = this.querySelector('[data-bp-saved-loading]'); 11236 this.template = this.querySelector('[data-bp-saved-template]'); 11237 this.bubble = this.querySelector('[data-bp-saved-bubble]'); 11238 this.triggerCount = this.querySelector('[data-bp-saved-trigger-count]'); 11239 11240 // Local trigger inside this component. 11241 const localOpener = this.querySelector('[data-bp-saved-open]'); 11242 if (localOpener) localOpener.addEventListener('click', (e) => { e.preventDefault(); this.open(); }); 11243 11244 // Delegated open for any element anywhere with data-bp-saved-open. 11245 // Using `once: false` lets cart-drawer footer/empty links open us too. 11246 if (!window.__bpSavedOpenWired) { 11247 window.__bpSavedOpenWired = true; 11248 document.addEventListener('click', (e) => { 11249 const trigger = e.target.closest('[data-bp-saved-open]'); 11250 if (!trigger || this.contains(trigger)) return; 11251 e.preventDefault(); 11252 const el = document.querySelector('bp-saved-drawer'); 11253 if (el && typeof el.open === 'function') el.open(); 11254 }); 11255 } 11256 11257 this.dialog.addEventListener('click', (e) => { 11258 if (e.target.closest('[data-bp-saved-close]')) { 11259 e.preventDefault(); 11260 this.close(); 11261 return; 11262 } 11263 if (e.target === this.dialog) this.close(); 11264 }); 11265 11266 this.dialog.addEventListener('cancel', (e) => { 11267 e.preventDefault(); 11268 this.close(); 11269 }); 11270 11271 // Card actions (Move to Bag / Remove). 11272 this.list.addEventListener('click', async (e) => { 11273 const card = e.target.closest('[data-bp-saved-card]'); 11274 if (!card) return; 11275 const key = card.dataset.savedKey; 11276 11277 if (e.target.closest('[data-bp-card-remove]')) { 11278 this.removeSaved(key); 11279 this.render(); 11280 return; 11281 } 11282 if (e.target.closest('[data-bp-card-move]')) { 11283 const moveBtn = e.target.closest('[data-bp-card-move]'); 11284 moveBtn.disabled = true; 11285 moveBtn.textContent = 'Addingâ¦'; 11286 try { 11287 await this.moveToBag(key); 11288 } catch (err) { 11289 // The item is still saved â handleMoveToBag only drops the 11290 // save after /cart/add.js succeeds. Leave the card in the 11291 // list and say why, instead of dropping the shopper back to 11292 // an unchanged button with no explanation. (This branch was 11293 // unreachable until handleMoveToBag stopped swallowing add 11294 // failures: it removed the save first, warned to the console, 11295 // and returned as if it had worked â so the item disappeared 11296 // from Saved for Later without ever reaching the cart.) 11297 console.error('[bp-saved-drawer] move-to-bag failed', err); 11298 if (err && err.status === 422) { 11299 // Genuinely unsellable (sold out). Stamp it persistently 11300 // instead of flickering the label back to "Move to Bag" 11301 // after 2.6s (Dragana QA 7/22) â the item stays saved and 11302 // reads Sold out / Unavailable until stock returns. 11303 this.markUnavailable(card); 11304 if (err.description) moveBtn.title = err.description; 11305 } else { 11306 // Transient failure (network, etc.) â let them retry. 11307 moveBtn.disabled = false; 11308 moveBtn.textContent = 'Try again'; 11309 moveBtn.title = (err && err.description) || 'Could not add to bag'; 11310 setTimeout(() => { 11311 moveBtn.textContent = 'Move to Bag'; 11312 moveBtn.removeAttribute('title'); 11313 }, 2600); 11314 } 11315 return; 11316 } 11317 this.removeSaved(key); 11318 this.render(); 11319 // Close saved drawer so the cart drawer becomes the active dialog, 11320 // then refresh + open the cart drawer. 11321 this.close(); 11322 document.dispatchEvent(new CustomEvent('cart:updated')); 11323 const cartDrawer = document.querySelector('bp-cart-drawer'); 11324 if (cartDrawer && typeof cartDrawer.open === 'function') { 11325 setTimeout(() => cartDrawer.open(), 220); 11326 } 11327 } 11328 }); 11329 11330 // Cross-tab + same-tab sync. We listen on the legacy 11331 // `bp.saved_for_later` key AND the Swym-mirror key 11332 // `save-for-later-items` (bp-swym-helpers). 11333 window.addEventListener('storage', (e) => { 11334 if (e.key === 'bp.saved_for_later' || e.key === 'save-for-later-items') this.render(); 11335 });
11336 document.addEventListener('bp:saved:updated', () => this.render()); 11337 document.addEventListener('wishlist:updated', () => this.render()); 11338 document.addEventListener('wishlist:item-saved', () => this.render()); 11339 // Swym finished its reconcile â leave the loading state and render. 11340 document.addEventListener('bp:saved:synced', () => this.render()); 11341 11342 // Migrate any pre-existing local-only entries (legacy 11343 // `bp.saved_for_later`) into the Swym-compatible mirror so 11344 // the customer doesn't lose what they already saved. 11345 this.migrateLegacy(); 11346 11347 this.render(); 11348 } 11349 11350 // ----- Storage adapter â prefer Swym-backed mirror ----- 11351 // Returns the list of saved items either from the Swym mirror 11352 // (bp-swym-helpers) when available, falling back to the legacy 11353 // single-array `bp.saved_for_later` key for back-compat. 11354 readItems() { 11355 if (window.bpSavedForLater && typeof window.bpSavedForLater.getLocalWishlist === 'function') { 11356 const w = window.bpSavedForLater.getLocalWishlist(); 11357 return Array.isArray(w && w.items) ? w.items : []; 11358 } 11359 try { return JSON.parse(localStorage.getItem('bp.saved_for_later') || '[]'); } 11360 catch (_) { return []; } 11361 } 11362 migrateLegacy() { 11363 if (!window.bpSavedForLater) return; 11364 let legacy = []; 11365 try { legacy = JSON.parse(localStorage.getItem('bp.saved_for_later') || '[]'); } 11366 catch (_) { legacy = []; } 11367 if (!Array.isArray(legacy) || !legacy.length) return; 11368 const customerId = window.bpSavedForLater.getCustomerId(); 11369 const all = window.bpSavedForLater.getSavedItemsLocalStorage() || {}; 11370 const current = all[customerId] || { items: [], count: 0 }; 11371 // De-dupe by variant_id. 11372 const have = new Set(current.items.map((it) => String(it.variant_id))); 11373 const adapted = legacy 11374 .filter((it) => !have.has(String(it.variantId || it.variant_id))) 11375 .map((it) => ({ 11376 id: String(it.productId || it.product_id || it.variantId), 11377 handle: it.handle || '', 11378 variant_id: String(it.variantId || it.variant_id), 11379 variant_price: String(it.price || it.variant_price || ''), 11380 variant_compare_at_price: String(it.compare_at_price || it.variant_compare_at_price || ''), 11381 variant_title: String(it.variantTitle || it.variant_title || ''), 11382 title: it.title || '', 11383 image: it.image || '', 11384 quantity: String(it.quantity || 1), 11385 properties: it.properties || {}, 11386 variant_sku: it.sku || it.variant_sku || '' 11387 })); 11388 if (!adapted.length) return; 11389 const merged = current.items.concat(adapted); 11390 all[customerId] = { ...current, items: merged, count: merged.length }; 11391 window.bpSavedForLater.storeSavedItemsLocalStorage(all); 11392 // Wipe the legacy bucket so the migration is one-shot. 11393 try { localStorage.removeItem('bp.saved_for_later'); } catch (_) {} 11394 } 11395 11396 open() { 11397 this.render(); 11398 if (this.dialog.open) return; 11399 if (typeof this.dialog.showModal === 'function') this.dialog.showModal(); 11400 else this.dialog.setAttribute('open', ''); 11401 } 11402 close() { 11403 if (this._closing || !this.dialog.open) return; 11404 this._closing = true; 11405 this.dialog.classList.add('is-closing'); 11406 const onEnd = () => { 11407 this.dialog.classList.remove('is-closing'); 11408 this._closing = false; 11409 try { this.dialog.close(); } catch (_) { this.dialog.removeAttribute('open'); } 11410 }; 11411 this.dialog.addEventListener('animationend', onEnd, { once: true }); 11412 setTimeout(() => { if (this._closing) onEnd(); }, 350); 11413 } 11414 11415 getSaved() { return this.readItems(); } 11416 removeSaved(key) { 11417 // `key` for Swym-mirror items is variant_id; legacy items used 11418 // a `key` field. We resolve by either. 11419 const items = this.readItems(); 11420 const target = items.find((i) => String(i.variant_id) === String(key) || String(i.key) === String(key)); 11421 if (!target) return; 11422 if (window.bpSavedForLater && window.bpSavedForLater.removeWishlistItem) { 11423 window.bpSavedForLater.removeWishlistItem(target.id, target.variant_id); 11424 } 11425 } 11426 11427 async moveToBag(key) { 11428 const items = this.readItems(); 11429 const item = items.find((i) => String(i.variant_id) === String(key) || String(i.key) === String(key)); 11430 if (!item) return; 11431 const productId = item.id; 11432 const variantId = item.variant_id || item.variantId;
11433 const qty = parseInt(item.quantity, 10) || 1; 11434 const isWishlistItemProductLevel = String(productId) === String(variantId); 11435 if (typeof window.handleMoveToBag === 'function') { 11436 await window.handleMoveToBag(productId, variantId, qty, isWishlistItemProductLevel, item, null); 11437 return; 11438 } 11439 // Last-resort fallback if Swym helpers haven't loaded yet. 11440 const body = { items: [{ id: variantId, quantity: qty, properties: item.properties || {} }] }; 11441 const res = await fetch('/cart/add.js', { 11442 method: 'POST', 11443 headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, 11444 body: JSON.stringify(body) 11445 }); 11446 if (!res.ok) throw new Error('HTTP ' + res.status); 11447 } 11448 11449 formatMoney(cents) { return '$' + (cents / 100).toFixed(2); } 11450 // Atlas's variant_price is a currency-formatted string ("$25.00" or 11451 // "2500" cents string). Normalise to cents for arithmetic. 11452 parsePriceCents(v) { 11453 if (v == null) return 0; 11454 const s = String(v).replace(/[^0-9.-]/g, ''); 11455 if (!s) return 0; 11456 if (s.indexOf('.') >= 0) return Math.round(parseFloat(s) * 100); 11457 return parseInt(s, 10) || 0; 11458 } 11459 11460 // Saved entries store no availability (only id/handle/price/title/â¦), 11461 // so a sold-out save looked identical to an in-stock one and the only 11462 // "unavailable" hint was the transient 422 flicker on Move to Bag. 11463 // Resolve availability from /products/<handle>.js â cached per handle 11464 // (one fetch, reused across re-renders) â so each card can carry a 11465 // stable sold-out marker up front (Dragana QA 7/22). 11466 fetchProductJson(handle) { 11467 if (!handle) return Promise.resolve(null); 11468 if (!this._prodCache) this._prodCache = new Map(); 11469 if (this._prodCache.has(handle)) return this._prodCache.get(handle); 11470 const p = fetch(`/products/${handle}.js`, { credentials: 'same-origin' }) 11471 .then((r) => (r.ok ? r.json() : null)) 11472 .catch(() => null); 11473 this._prodCache.set(handle, p); 11474 return p; 11475 } 11476 11477 // Resolves to false only when we can confirm sold-out. Unknown (fetch 11478 // failed / no handle) resolves true so we never falsely block a save â 11479 // the 422 path still catches a genuine sold-out at add time. 11480 isSavedItemAvailable(item) { 11481 const variantId = item.variant_id || item.variantId; 11482 return this.fetchProductJson(item.handle).then((product) => { 11483 if (!product) return true; 11484 const variants = product.variants || []; 11485 if (variantId) { 11486 const v = variants.find((vv) => String(vv.id) === String(variantId)); 11487 // Exact saved variant known â trust its own availability. 11488 if (v) return !!v.available; 11489 } 11490 // Product-level save, or the saved variant was retired: sellable 11491 // if ANY variant is still in stock. 11492 return variants.some((vv) => vv.available); 11493 }); 11494 } 11495 11496 // Stamp a card as sold out: red marker + a disabled, relabelled Move 11497 // button. Idempotent, and safe to call from both render() (proactive) 11498 // and the 422 catch (reactive) â see the Move to Bag handler. 11499 markUnavailable(node) { 11500 if (!node || node.classList.contains('is-unavailable')) return; 11501 node.classList.add('is-unavailable'); 11502 const moveBtn = node.querySelector('[data-bp-card-move]'); 11503 if (moveBtn) { 11504 moveBtn.disabled = true; 11505 moveBtn.textContent = 'Unavailable'; 11506 moveBtn.classList.add('bp-saved-drawer__btn--soldout'); 11507 } 11508 const details = node.querySelector('.bp-saved-drawer__details'); 11509 if (details && !details.querySelector('[data-bp-card-unavailable]')) { 11510 const marker = document.createElement('p'); 11511 marker.className = 'bp-saved-drawer__unavailable'; 11512 marker.setAttribute('data-bp-card-unavailable', ''); 11513 marker.textContent = 'Sold out'; 11514 const actions = details.querySelector('.bp-saved-drawer__actions'); 11515 if (actions) details.insertBefore(marker, actions); 11516 else details.appendChild(marker); 11517 } 11518 } 11519 11520 // Ready to render for real: Swym has reconciled the wishlist, OR we've 11521 // fallen back to localStorage after a timeout (Swym slow / errored / not 11522 // installed). Until then we show a LOADING state everywhere instead of 11523 // rendering localStorage first and then flashing when Swym swaps it in â 11524 // the single-source approach that killed the appear/vanish/reappear flash. 11525 _ready() { 11526 if (this._localFallback) return true; 11527 return !!(window.bpSavedForLater 11528 && typeof window.bpSavedForLater.isSynced === 'function' 11529 && window.bpSavedForLater.isSynced()); 11530 } 11531 11532 // Kick a sync (in case the drawer mounted before the helper's load-time 11533 // sync ran) and arm a fallback so we're never stuck on the spinner. 11534 _scheduleReady() { 11535 if (this._readyWaiting) return; 11536 this._readyWaiting = true; 11537 if (window.bpSavedForLater && typeof window.bpSavedForLater.checkWishlistSync === 'function') { 11538 try { window.bpSavedForLater.checkWishlistSync(); } catch (_) {} 11539 } 11540 setTimeout(() => { 11541 if (!this._ready()) { this._localFallback = true; this.render(); } 11542 }, 5000); 11543 } 11544 11545 render() { 11546 // Loading state â shown until Swym is synced (or we time out to local). 11547 // Covers the drawer body AND the topnav count so nothing shows a 11548 // premature/for-a-moment-wrong value. 11549 if (!this._ready()) { 11550 if (this.loading) this.loading.hidden = false;
11551 if (this.list) this.list.hidden = true; 11552 if (this.empty) this.empty.hidden = true; 11553 if (this.triggerCount) { 11554 this.triggerCount.hidden = false; 11555 this.triggerCount.classList.add('is-loading'); 11556 this.triggerCount.textContent = ''; 11557 } 11558 this._scheduleReady(); 11559 return; 11560 } 11561 if (this.loading) this.loading.hidden = true; 11562 if (this.triggerCount) this.triggerCount.classList.remove('is-loading'); 11563 11564 const items = this.getSaved(); 11565 11566 // Trigger + header bubble. 11567 if (this.bubble) this.bubble.textContent = items.length; 11568 if (this.triggerCount) { 11569 this.triggerCount.textContent = items.length; 11570 this.triggerCount.toggleAttribute('hidden', items.length === 0); 11571 } 11572 11573 if (!items.length) { 11574 this._renderSig = ''; 11575 this.list.innerHTML = ''; 11576 this.list.hidden = true; 11577 this.empty.hidden = false; 11578 return; 11579 } 11580 this.empty.hidden = true; 11581 this.list.hidden = false; 11582 11583 // Newest-first. Sort by the Swym-proof order map (variant_id â 11584 // timestamp, stored under its own key that Swym's sync never rewrites), 11585 // falling back to the per-item savedAt, then 0. This is what keeps a 11586 // fresh save on top both in-session and after refresh â the per-item 11587 // savedAt alone kept getting dropped/reordered by Swym's async sync, so 11588 // the item slid to the bottom. Items with no timestamp keep their 11589 // relative order below the ranked ones (stable sort). 11590 const order = (window.bpSavedForLater && typeof window.bpSavedForLater.getSavedOrder === 'function') 11591 ? window.bpSavedForLater.getSavedOrder() 11592 : {}; 11593 const rank = (it) => Number(order[String(it.variant_id)]) || Number(it.savedAt) || 0; 11594 const ordered = items.slice().sort((a, b) => rank(b) - rank(a)); 11595 11596 // Skip the rebuild when the visible list is unchanged. render() fires 11597 // several times right after a reload-then-open (open + Swym's 11598 // checkWishlistSync swapping in the remote item objects + storage / 11599 // wishlist events); each innerHTML reset flashed a blank frame between 11600 // paints, so the items appeared, vanished, then reappeared. Key the 11601 // signature on the ordered variant ids only, String-normalized so 11602 // Swym's reformatted objects (numeric vs string ids) don't falsely 11603 // differ from the localStorage ones. 11604 // 11605 // CRUCIAL: only skip when the DOM ACTUALLY reflects that signature 11606 // (childElementCount matches). Otherwise a render that set the signature 11607 // but left the list empty (e.g. an interrupted build) would skip forever 11608 // and the drawer would never show items. 11609 const sig = ordered.map((it) => String(it.variant_id || it.variantId || '')).join('|'); 11610 if (sig === this._renderSig && this.list.childElementCount === ordered.length) return; 11611 this._renderSig = sig; 11612 11613 this.list.innerHTML = ''; 11614 ordered.forEach((item) => { 11615 // Each entry stored by bp-swym-helpers uses Atlas's shape 11616 // (variant_id, variant_title, variant_price, title, image, 11617 // handle, quantity). Legacy entries used variantId/title/price/ 11618 // variantTitle/url â read either form. 11619 const variantId = item.variant_id || item.variantId; 11620 const productId = item.id || item.productId; 11621 const variantTitle = item.variant_title || item.variantTitle || ''; 11622 const url = item.handle ? `/products/${item.handle}` : (item.url || '#'); 11623 const priceCents = this.parsePriceCents(item.variant_price || item.price); 11624 const qty = parseInt(item.quantity, 10) || 1; 11625 11626 const node = this.template.content.firstElementChild.cloneNode(true); 11627 node.dataset.savedKey = variantId || item.key; 11628 11629 const img = node.querySelector('[data-bp-card-image]'); 11630 if (item.image) { 11631 img.src = item.image; 11632 img.alt = item.title || ''; 11633 } else { 11634 img.remove(); 11635 } 11636 node.querySelectorAll('[data-bp-card-link]').forEach((a) => { 11637 if (url) a.href = url; 11638 if (a.tagName === 'A' && a.children.length === 0) a.textContent = item.title || 'Item'; 11639 }); 11640 11641 node.querySelector('[data-bp-card-price]').textContent = 11642 this.formatMoney(priceCents * qty); 11643 11644 const variantEl = node.querySelector('[data-bp-card-variant]'); 11645 if (variantTitle && variantTitle !== 'Default Title') { 11646 variantEl.textContent = variantTitle.replace(' / ', ' - '); 11647 } else { 11648 variantEl.remove(); 11649 } 11650 11651 const propsEl = node.querySelector('[data-bp-card-props]'); 11652 const props = item.properties || {}; 11653 const visible = Object.entries(props).filter(([k, v]) => k && k[0] !== '_' && v); 11654 if (!visible.length) { 11655 propsEl.remove(); 11656 } else { 11657 visible.forEach(([k, v]) => { 11658 const li = document.createElement('li'); 11659 li.textContent = (k === 'Final Sale' || k === 'Final_Sale') ? 'Final Sale' : `${k}: ${v}`; 11660 propsEl.appendChild(li); 11661 }); 11662 } 11663 11664 this.list.appendChild(node); 11665 11666 // Resolve availability async and stamp sold-out state once known. 11667 // Guard on isConnected so a re-render mid-fetch doesn't touch a
11668 // detached node. 11669 this.isSavedItemAvailable(item).then((available) => { 11670 if (!available && node.isConnected) this.markUnavailable(node); 11671 }); 11672 }); 11673 } 11674 } 11675 customElements.define('bp-saved-drawer', BpSavedDrawer); 11676 } 11677</script>
11677 11678 11679 11680 11681 11682 <div 11683 class="account-button header-actions__action color-scheme-1" 11684 > 11685 <shopify-store store-domain="https://www.bostonproper.com" country="US" language="en"></shopify-store> 11686<shopify-account 11687 menu="customer-account-main-menu" 11688 11689 > 11690 11691 <span 11692 slot="signed-out-avatar" 11693 class="account-button__text header-actions__text-style hidden" 11694 > 11695 Account 11696 </span> 11697 11698 <span 11699 slot="signed-out-avatar" 11700 class="" 11701 aria-hidden="true" 11702 > 11703 11704 <span 11705 slot="signed-out-avatar" 11706 class="account-button__icon" 11707 aria-hidden="true" 11708 ><svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg"> 11709<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"/> 11710<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"/> 11711</svg> 11712</span> 11713 11714 </span> 11715 11716 </shopify-account> 11717 </div> 11718 11719 11720 11721<bp-cart-drawer class="bp-cart-drawer"><button 11722 type="button" 11723 class="bp-cart-drawer__trigger button-unstyled header-actions__action" 11724 data-bp-cart-open 11725 aria-haspopup="dialog" 11726 aria-label="Cart" 11727 ><svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg"> 11728<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
11728583 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"/> 11729<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"/> 11730</svg> 11731<span class="bp-cart-drawer__trigger-count" data-bp-cart-trigger-count hidden>0</span> 11732 </button> 11733 11734 <dialog class="bp-cart-drawer__dialog" data-bp-cart-dialog aria-label="Bag"> 11735 <header class="bp-cart-drawer__header"> 11736 <h2 class="bp-cart-drawer__heading"> 11737 <span class="bp-cart-drawer__bubble" data-bp-cart-bubble>0</span> 11738 Bag 11739 </h2> 11740 <button type="button" class="bp-cart-drawer__close" data-bp-cart-close aria-label="Close bag"> 11741 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true"> 11742 <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"/> 11743 <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"/> 11744 <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"/> 11745 <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"/> 11746 </svg> 11747 </button> 11748 </header> 11749 11750 <div class="bp-cart-drawer__body" data-bp-cart-body><div class="bp-cart-drawer__empty" data-bp-cart-empty > 11751 <p>Your bag is empty.</p> 11752 <a href="/collections/all" class="bp-cart-drawer__empty-cta">Continue shopping</a> 11753 <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"> 11754 <h3 class="bp-cart-drawer__recs-title">Recommended for you</h3> 11755 <div class="bp-cart-drawer__recs-arrows"> 11756 <button type="button" class="bp-cart-drawer__recs-arrow" data-bp-recs-
11756prev aria-label="Previous"><svg width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true"> 11757 <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"/> 11758 <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"/> 11759 </svg> 11760 </button> 11761 <button type="button" class="bp-cart-drawer__recs-arrow" data-bp-recs-next aria-label="Next"> 11762 <svg width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true"> 11763 <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"/> 11764 <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"/> 11765 </svg> 11766 </button> 11767 </div> 11768 </header> 11769 <ul class="bp-cart-drawer__recs-track" role="list"><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host"> 11770 <article 11771 class="bp-card" 11772 data-product-id="15399681392806" 11773 data-product-url="/products/leopard-print-skirt-brown-multi" 11774 data-bp-card-secondary-hover="true" 11775 data-bp-card-qv-dest="drawer" 11776 data-bp-card-qv-vis-d="hover" 11777 data-bp-card-qv-vis-m="shown" 11778 data-bp-card-qb-style="disabled" 11779 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_e449d9f8-fa91-4b71-a931-89e5295d2d60.jpg?v=1790318066\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": 63 } }' 11780 > 11781 <div class="bp-card__media"> 11782 <a class="bp-card__media-link" href="/products/leopard-print-skirt-brown-multi" aria-label="Leopard Print Skirt Brown Multi" ref="productCardLink"><img 11783 class="bp-card__image bp-card__image--primary" 11784 src="//www.bostonproper.com/cdn/shop/files/2DO3390_SET_e449d9f8-fa91-4b71-a931-89e5295d2d60.jpg?v=1790318066&width=720" 11785 srcset="//www.bostonproper.com/cdn/shop/files/2DO3390_SET_e449d9f8-fa91-4b71-a931-89e5295d2d60.jpg?v=1790318066&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DO3390_SET_e449d9f8-fa91-4b71-a931-89e5295d2d60.jpg?v=1790318066&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DO3390_SET_e449d9f8-fa91-4b71-a931-89e5295d2d60.jpg?v=1790318066&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DO3390_SET_e449d9f8-fa91-4b71-a931-89e5295d2d60.jpg?v=1790318066&width=1080 1080w" 11786 sizes="(min-width: 1024px) 25vw, 50vw" 11787 width="1639" 11788 height="2048" 11789 alt="Leopard Print Skirt Brown Multi" 11790 loading="lazy" 11791 data-bp-card-image-primary 11792 ><img 11793 class="bp-card__image bp-card__image--secondary" 11794 src="//www.bostonproper.com/cdn/shop/files/2_dead2446-d579-467e-97bd-b826507a5f69.jpg?v=1790318067&width=720" 11795 srcset="//www.bostonproper.com/cdn/shop/files/2_dead2446-d579-467e-97bd-b826507a5f69.jpg?v=1790318067&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_dead2446-d579-467e-97bd-b826507a5f69.jpg?v=1790318067&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_dead2446-d579-467e-97bd-b826507a5f69.jpg?v=1790318067&width=720 720w" 11796 sizes="(min-width: 1024px) 25vw, 50vw" 11797 width="1639" 11798 height="2048" 11799 alt="" 11800 loading="lazy" 11801 aria-hidden="true" 11802 data-bp-card-image-secondary 11803 ></a><div class="bp-card__badges" data-bp-card-badges></div></div> 11804 11805 <div class="bp-card__body"><h3 class="bp-card__title"> 11806 <a href="/products/leopard-print-skirt-brown-multi">Leopard Print Skirt</a> 11807 </h3> 11808 11809 <div class="bp-card__price-row"><span class="bp-card__price">$110</span> 11810 <s class="bp-card__compare" hidden></s></div></div> 11811 </article> 11812</product-card> 11813</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host"> 11814 <article 11815 class="bp-card" 11816 data-product-id="15399681360038" 11817 data-product-url="/products/metallic-zebra-printed-dress-tan-multi" 11818 data-bp-card-secondary-hover="true" 11819 data-bp-card-qv-dest="drawer" 11820 data-bp-card-qv-vis-d="hover" 11821 data-bp-card-qv-vis-m="shown" 11822 data-bp-card-qb-style="disabled" 11823 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_
11823SET_3e78a356-4a13-44de-871d-1d9f536a1a85.jpg?v=1790318054\u0026width=720", "category": "Dresses", "product_type":null, "selected_variant": { "id": 56779670782118, "sku": "2DO0590006", "price": 129.0, "compare_at_price": 180.0, "option1": "Tan Multi", "option2": "6", "product_id": 15399681360038, "available": true, "inventory_quantity": 50 } }' 11824 > 11825 <div class="bp-card__media"> 11826 <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 11827 class="bp-card__image bp-card__image--primary" 11828 src="//www.bostonproper.com/cdn/shop/files/2DO0590_SET_3e78a356-4a13-44de-871d-1d9f536a1a85.jpg?v=1790318054&width=720" 11829 srcset="//www.bostonproper.com/cdn/shop/files/2DO0590_SET_3e78a356-4a13-44de-871d-1d9f536a1a85.jpg?v=1790318054&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DO0590_SET_3e78a356-4a13-44de-871d-1d9f536a1a85.jpg?v=1790318054&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DO0590_SET_3e78a356-4a13-44de-871d-1d9f536a1a85.jpg?v=1790318054&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DO0590_SET_3e78a356-4a13-44de-871d-1d9f536a1a85.jpg?v=1790318054&width=1080 1080w" 11830 sizes="(min-width: 1024px) 25vw, 50vw" 11831 width="1639" 11832 height="2048" 11833 alt="Metallic Zebra Printed Dress Tan Multi" 11834 loading="lazy" 11835 data-bp-card-image-primary 11836 ><img 11837 class="bp-card__image bp-card__image--secondary" 11838 src="//www.bostonproper.com/cdn/shop/files/2_a7042052-cb79-4a3a-bc67-beabd9416119.jpg?v=1790318054&width=720" 11839 srcset="//www.bostonproper.com/cdn/shop/files/2_a7042052-cb79-4a3a-bc67-beabd9416119.jpg?v=1790318054&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_a7042052-cb79-4a3a-bc67-beabd9416119.jpg?v=1790318054&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_a7042052-cb79-4a3a-bc67-beabd9416119.jpg?v=1790318054&width=720 720w" 11840 sizes="(min-width: 1024px) 25vw, 50vw" 11841 width="1639" 11842 height="2048" 11843 alt="" 11844 loading="lazy" 11845 aria-hidden="true" 11846 data-bp-card-image-secondary 11847 ></a><div class="bp-card__badges" data-bp-card-badges></div></div> 11848 11849 <div class="bp-card__body"><h3 class="bp-card__title"> 11850 <a href="/products/metallic-zebra-printed-dress-tan-multi">Metallic Zebra Printed Dress</a> 11851 </h3> 11852 11853 <div class="bp-card__price-row"><span class="bp-card__price">$129</span> 11854 <s class="bp-card__compare">$180</s><span class="bp-card__promo">Limited time! Up to 35% off. Price as marked</span></div></div> 11855 </article> 11856</product-card> 11857</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host"> 11858 <article 11859 class="bp-card" 11860 data-product-id="15366923452582" 11861 data-product-url="/products/mock-neck-intarsia-flare-sleeve-tunic-west-side-paisley" 11862 data-bp-card-secondary-hover="true" 11863 data-bp-card-qv-dest="drawer" 11864 data-bp-card-qv-vis-d="hover" 11865 data-bp-card-qv-vis-m="shown" 11866 data-bp-card-qb-style="disabled" 11867 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_499b9b85-0db7-4637-8d16-16c878e06144.jpg?v=1790318077\u0026width=720", "category": "Sweater Tops", "product_type":null, "selected_variant": { "id": 56658234933414, "sku": "2DM9540400", "price": 69.0, "compare_at_price": 100.0, "option1": "West Side Paisley", "option2": "XXS", "product_id": 15366923452582, "available": true, "inventory_quantity": 5 } }' 11868 > 11869 <div class="bp-card__media"> 11870 <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 11871 class="bp-card__image bp-card__image--primary" 11872 src="//www.bostonproper.com/cdn/shop/files/2DM9540_SET_499b9b85-0db7-4637-8d16-16c878e06144.jpg?v=1790318077&width=720" 11873 srcset="//www.bostonproper.com/cdn/shop/files/2DM9540_SET_499b9b85-0db7-4637-8d16-16c878e06144.jpg?v=1790318077&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DM9540_SET_499b9b85-0db7-4637-8d16-16c878e06144.jpg?v=1790318077&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DM9540_SET_499b9b85-0db7-4637-8d16-16c878e06144.jpg?v=1790318077&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DM9540_SET_499b9b85-0db7-4637-8d16-16c878e06144.jpg?v=1790318077&width=1080 1080w" 11874 sizes="(min-width: 1024px) 25vw, 50vw" 11875 width="1639" 11876 height="2048" 11877 alt="Mock Neck Intarsia Flare Sleeve Tunic West Side Paisley" 11878 loading="lazy" 11879 data-bp-card-image-primary 11880 ><img 11881 class="bp-card__image bp-card__image--secondary" 11882 src="//www.bostonproper.com/cdn/shop/files/2_00a39f4d-0849-463b-8461-326fe573f6a1.jpg?v=1790318077&width=720" 11883 srcset="//www.bostonproper.com/cdn/shop/files/2_00a39f4d-0849-463b-8461-326fe573f6a1.jpg?v=1790318077&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_00a39f4d-0849-463b-8461-326fe573f6a1.jpg?v=1790318077&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_00a39f4d-0849-463b-8461-326fe573f6a1.jpg?v=1790318077&width=720 720w" 11884 sizes="(min-width: 1024px) 25vw, 50vw" 11885 width="1639" 11886 height="2048" 11887 alt="" 11888 loading="lazy" 11889 aria-hidden="true" 11890 data-bp-card-image-secondary 11891 ></a><div class="bp-card__badges" data-bp-card-badges></div></div> 11892 11893 <div class="bp-card__body"><h3 class="bp-card__title"> 11894 <a href="/products/mock-neck-intarsia-flare-sleeve-tunic-west-side-paisley">Mock Neck Intarsia Flare Sleeve Tunic</a> 11895 </h3> 11896 11897 <div class="bp-card__price-row"><span class="bp-card__price">$69</span> 11898 <s class="bp-card__compare">$100</s><span class="bp-card__promo">
11898Limited time! Up to 35% off. Price as marked</span></div></div> 11899 </article> 11900</product-card> 11901</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host"> 11902 <article 11903 class="bp-card" 11904 data-product-id="15336227864742" 11905 data-product-url="/products/knit-suede-drape-front-jacket-stone" 11906 data-bp-card-secondary-hover="true" 11907 data-bp-card-qv-dest="drawer" 11908 data-bp-card-qv-vis-d="hover" 11909 data-bp-card-qv-vis-m="shown" 11910 data-bp-card-qb-style="disabled" 11911 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=1790318159\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 } }' 11912 > 11913 <div class="bp-card__media"> 11914 <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 11915 class="bp-card__image bp-card__image--primary" 11916 src="//www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1790318159&width=720" 11917 srcset="//www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1790318159&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1790318159&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1790318159&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1790318159&width=1080 1080w" 11918 sizes="(min-width: 1024px) 25vw, 50vw" 11919 width="1639" 11920 height="2048" 11921 alt="Knit Suede Drape Front Jacket Stone" 11922 loading="lazy" 11923 data-bp-card-image-primary 11924 ><img 11925 class="bp-card__image bp-card__image--secondary" 11926 src="//www.bostonproper.com/cdn/shop/files/2_94315d5c-6ff8-48ec-ab66-ed64157b7e3d.jpg?v=1790318159&width=720" 11927 srcset="//www.bostonproper.com/cdn/shop/files/2_94315d5c-6ff8-48ec-ab66-ed64157b7e3d.jpg?v=1790318159&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_94315d5c-6ff8-48ec-ab66-ed64157b7e3d.jpg?v=1790318159&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_94315d5c-6ff8-48ec-ab66-ed64157b7e3d.jpg?v=1790318159&width=720 720w" 11928 sizes="(min-width: 1024px) 25vw, 50vw" 11929 width="1639" 11930 height="2048" 11931 alt="" 11932 loading="lazy" 11933 aria-hidden="true" 11934 data-bp-card-image-secondary 11935 ></a><div class="bp-card__badges" data-bp-card-badges></div></div> 11936 11937 <div class="bp-card__body"><h3 class="bp-card__title"> 11938 <a href="/products/knit-suede-drape-front-jacket-stone">Knit Suede Drape Front Jacket</a> 11939 </h3> 11940 11941 <div class="bp-card__price-row"><span class="bp-card__price">$125</span> 11942 <s class="bp-card__compare" hidden></s></div><ul class="bp-card__swatches" role="list" aria-label="Available colors"> 11943 <li class="bp-card__swatch-item"><button 11944 type="button" 11945 class="bp-card__swatch" 11946 aria-label="Blue" 11947 11948 data-bp-card-swatch-image="https://media.bostonproper.com/s/bostonproper/2DR1730_SET?w=720" 11949 data-bp-card-swatch-hover="https://media.bostonproper.com/s/bostonproper/2DR1730_SET/2?w=720" 11950 data-bp-variant-url="/products/knit-suede-drape-front-jacket-blue" 11951 data-bp-swatch-price="$125" 11952 11953 > 11954 <img 11955 class="bp-card__swatch-img" 11956 src="https://media.bostonproper.com/i/bostonproper/2DR1730_2?$poiswatch$&img404=2DR1730_1" 11957 alt="" 11958 aria-hidden="true" 11959 width="23" 11960 height="23" 11961 loading="lazy" 11962 > 11963 </button></li><li class="bp-card__swatch-item"><button 11964 type="button" 11965 class="bp-card__swatch bp-card__swatch--active" 11966 aria-label="Stone" 11967 aria-current="true" 11968 data-bp-card-swatch-image="https://media.bostonproper.com/s/bostonproper/2DR1780_SET?w=720" 11969 data-bp-card-swatch-hover="https://media.bostonproper.com/s/bostonproper/2DR1780_SET/2?w=720" 11970 data-bp-variant-url="/products/knit-suede-drape-front-jacket-stone" 11971 data-bp-swatch-price="$125" 11972 11973 > 11974 <img 11975 class="bp-card__swatch-img" 11976 src="https://media.bostonproper.com/i/bostonproper/2DR1780_2?$poiswatch$&img404=2DR1780_1" 11977 alt="" 11978 aria-hidden="true" 11979 width="23" 11980 height="23" 11981 loading="lazy" 11982 > 11983 </button></li> 11984</ul></div> 11985 </article> 11986</product-card> 11987</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host"> 11988 <article 11989 class="bp-card" 11990 data-product-id="15336227831974" 11991 data-product-url="/products/knit-suede-drape-front-jacket-blue" 11992 data-bp-card-secondary-hover="true" 11993 data-bp-card-qv-dest="drawer" 11994 data-bp-card-qv-vis-d="hover" 11995 data-bp-card-qv-vis-m="shown" 11996 data-bp-card-qb-style="disabled" 11997 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_4798346d-afe4-4852-b131-cc3ad06c0346.jpg?v=1790318158\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": 13 } }' 11998 > 11999 <div class="bp-card__media"> 12000 <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 12001 class="bp-card__image bp-card__image--primary" 12002 src="//www.bostonproper.com/cdn/shop/files/2DR1730_SET_4798346d-afe4-4852-b131-cc3ad06c0346.jpg?v=1790318158&width=720" 12003 srcset="//www.bostonproper.com/cdn/shop/files/2DR1730_SET_4798346d-afe4-4852-b131-cc3ad06c0346.jpg?v=1790318158&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DR1730_SET_4798346d-afe4-4852-b131-cc3ad06c0346.jpg?v=1790318158&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DR1730_SET_4798346d-afe4-4852-b131-cc3ad06c0346.jpg?v=1790318158&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DR1730_SET_4798346d-afe4-4852-b131-cc3ad06c0346.jpg?v=1790318158&width=1080 1080w" 12004 sizes="(min-width: 1024px) 25vw, 50vw" 12005 width="1639" 12006 height="2048" 12007 alt="Knit Suede Drape Front Jacket Blue" 12008 loading="lazy" 12009 data-bp-card-image-primary 12010 ><img 12011 class="bp-card__image bp-card__image--secondary" 12012 src="//www.bostonproper.com/cdn/shop/files/2_22701656-8e50-488c-923f-0bbb7322e514.jpg?v=1790318158&width=720" 12013 srcset="//www.bostonproper.com/cdn/shop/files/2_22701656-8e50-488c-923f-0bbb7322e514.jpg?v=1790318158&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_22701656-8e50-488c-923f-0bbb7322e514.jpg?v=1790318158&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_22701656-8e50-488c-923f-0bbb7322e514.jpg?v=1790318158&width=720 720w" 12014 sizes="(min-width: 1024px) 25vw, 50vw" 12015 width="1639" 12016 height="2048" 12017 alt="" 12018 loading="lazy" 12019 aria-hidden="true" 12020 data-bp-card-image-secondary 12021 ></a><div class="bp-card__badges" data-bp-card-badges></div></div> 12022 12023 <div class="bp-card__body"><h3 class="bp-card__title"> 12024 <a href="/products/knit-suede-drape-front-jacket-blue">Knit Suede Drape Front Jacket</a> 12025 </h3> 12026 12027 <div class="bp-card__price-row"><span class="bp-card__price">$125</span> 12028 <s class="bp-card__compare" hidden></s></div><ul class="bp-card__swatches" role="list" aria-label="Available colors"> 12029 <li class="bp-card__swatch-item"><button 12030 type="button" 12031 class="bp-card__swatch bp-card__swatch--active" 12032 aria-label="Blue" 12033 aria-current="true" 12034 data-bp-card-swatch-image="https://media.bostonproper.com/s/bostonproper/2DR1730_SET?w=720" 12035 data-bp-card-swatch-hover="https://media.bostonproper.com/s/bostonproper/2DR1730_SET/2?w=720" 12036 data-bp-variant-url="/products/knit-suede-drape-front-jacket-blue" 12037 data-bp-swatch-price="$125" 12038 12039 > 12040 <img 12041 class="bp-card__swatch-img" 12042 src="https://media.bostonproper.com/i/bostonproper/2DR1730_2?$poiswatch$&img404=2DR1730_1" 12043 alt="" 12044 aria-hidden="true" 12045 width="23" 12046 height="23" 12047 loading="lazy" 12048 > 12049 </button></li><li class="bp-card__swatch-item"><button 12050 type="button" 12051 class="bp-card__swatch" 12052 aria-label="Stone" 12053 12054 data-bp-card-swatch-image="https://media.bostonproper.com/s/bostonproper/2DR1780_SET?w=720" 12055 data-bp-card-swatch-hover="https://media.bostonproper.com/s/bostonproper/2DR1780_SET/2?w=720" 12056 data-bp-variant-url="/products/knit-suede-drape-front-jacket-stone" 12057 data-bp-swatch-price="$125" 12058 12059 > 12060 <img 12061 class="bp-card__swatch-img" 12062 src="https://media.bostonproper.com/i/bostonproper/2DR1780_2?$poiswatch$&img404=2DR1780_1" 12063 alt="" 12064 aria-hidden="true" 12065 width="23" 12066 height="23" 12067 loading="lazy" 12068 > 12069 </button></li> 12070</ul></div> 12071 </article> 12072</product-card> 12073</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host"> 12074 <article 12075 class="bp-card" 12076 data-product-id="15325066035366" 12077 data-product-url="/products/modern-capri-trouser-sesame" 12078 data-bp-card-secondary-hover="true" 12079 data-bp-card-qv-dest="drawer" 12080 data-bp-card-qv-vis-d="hover" 12081 data-bp-card-qv-vis-m="shown" 12082 data-bp-card-qb-style="disabled" 12083 data-bp-track-product='{ "id": 15325066035366, "title": "Modern Capri Trouser Sesame", "vendor": "Boston Proper", "handle": "modern-capri-trouser-sesame", "url": "\/products\/modern-capri-trouser-sesame", "image": "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DR1580_SET.jpg?v=1790318150\u0026width=720", "category": "Pants", "product_type":null, "selected_variant": { "id": 56510704353446, "sku": "2DR1580000", "price": 59.0, "compare_at_price": 90.0, "option1": "Sesame", "option2": "0", "product_id": 15325066035366, "available": true, "inventory_quantity": 1 } }' 12084 > 12085 <div class="bp-card__media"> 12086 <a class="bp-card__media-link" href="/products/modern-capri-trouser-sesame" aria-label="Modern Capri Trouser Sesame" ref="productCardLink"><img 12087 class="bp-card__image bp-card__image--primary" 12088 src="//www.bostonproper.com/cdn/shop/files/2DR1580_SET.jpg?v=1790318150&width=720" 12089 srcset="//www.bostonproper.com/cdn/shop/files/2DR1580_SET.jpg?v=1790318150&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DR1580_SET.jpg?v=1790318150&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DR1580_SET.jpg?v=1790318150&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DR1580_SET.jpg?v=1790318150&width=1080 1080w" 12090 sizes="(min-width: 1024px) 25vw, 50vw" 12091 width="1639" 12092 height="2048" 12093 alt="Modern Capri Trouser Sesame" 12094 loading="lazy" 12095 data-bp-card-image-primary 12096 ><img 12097 class="bp-card__image bp-card__image--secondary" 12098 src="//www.bostonproper.com/cdn/shop/files/2_dc8f2b3f-fc14-41e6-a7ba-b29d8b8729ae.jpg?v=1790318150&width=720" 12099 srcset="//www.bostonproper.com/cdn/shop/files/2_dc8f2b3f-fc14-41e6-a7ba-b29d8b8729ae.jpg?v=1790318150&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_dc8f2b3f-fc14-41e6-a7ba-b29d8b8729ae.jpg?v=1790318150&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_dc8f2b3f-fc14-41e6-a7ba-b29d8b8729ae.jpg?v=1790318150&width=720 720w" 12100 sizes="(min-width: 1024px) 25vw, 50vw" 12101 width="1639" 12102 height="2048" 12103 alt="" 12104 loading="lazy" 12105 aria-hidden="true" 12106 data-bp-card-image-secondary 12107 ></a><div class="bp-card__badges" data-bp-card-badges></div></div> 12108 12109 <div class="bp-card__body"><p class="bp-card__collection">Modern Suiting</p><h3 class="bp-card__title"> 12110 <a href="/products/modern-capri-trouser-sesame">Modern Capri Trouser</a> 12111 </h3> 12112 12113 <div class="bp-card__price-row"><span class="bp-card__price">$59</span> 12114 <s class="bp-card__compare">$90</s><span class="bp-card__promo">
12114Limited time! Up to 35% off. Price as marked</span></div></div> 12115 </article> 12116</product-card> 12117</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host"> 12118 <article 12119 class="bp-card" 12120 data-product-id="15323390738598" 12121 data-product-url="/products/modern-single-button-blazer-sesame" 12122 data-bp-card-secondary-hover="true" 12123 data-bp-card-qv-dest="drawer" 12124 data-bp-card-qv-vis-d="hover" 12125 data-bp-card-qv-vis-m="shown" 12126 data-bp-card-qb-style="disabled" 12127 data-bp-track-product='{ "id": 15323390738598, "title": "Modern Single Button Blazer Sesame", "vendor": "Boston Proper", "handle": "modern-single-button-blazer-sesame", "url": "\/products\/modern-single-button-blazer-sesame", "image": "\/\/www.bostonproper.com\/cdn\/shop\/files\/2CL2681_SET_aa39b6f4-ae6c-4879-a355-440339ed6f52.jpg?v=1790318148\u0026width=720", "category": "Jackets", "product_type":null, "selected_variant": { "id": 56505725419686, "sku": "2CL2681000", "price": 109.0, "compare_at_price": 150.0, "option1": "Sesame", "option2": "0", "product_id": 15323390738598, "available": true, "inventory_quantity": 4 } }' 12128 > 12129 <div class="bp-card__media"> 12130 <a class="bp-card__media-link" href="/products/modern-single-button-blazer-sesame" aria-label="Modern Single Button Blazer Sesame" ref="productCardLink"><img 12131 class="bp-card__image bp-card__image--primary" 12132 src="//www.bostonproper.com/cdn/shop/files/2CL2681_SET_aa39b6f4-ae6c-4879-a355-440339ed6f52.jpg?v=1790318148&width=720" 12133 srcset="//www.bostonproper.com/cdn/shop/files/2CL2681_SET_aa39b6f4-ae6c-4879-a355-440339ed6f52.jpg?v=1790318148&width=360 360w, //www.bostonproper.com/cdn/shop/files/2CL2681_SET_aa39b6f4-ae6c-4879-a355-440339ed6f52.jpg?v=1790318148&width=540 540w, //www.bostonproper.com/cdn/shop/files/2CL2681_SET_aa39b6f4-ae6c-4879-a355-440339ed6f52.jpg?v=1790318148&width=720 720w, //www.bostonproper.com/cdn/shop/files/2CL2681_SET_aa39b6f4-ae6c-4879-a355-440339ed6f52.jpg?v=1790318148&width=1080 1080w" 12134 sizes="(min-width: 1024px) 25vw, 50vw" 12135 width="1639" 12136 height="2048" 12137 alt="Modern Single Button Blazer Sesame" 12138 loading="lazy" 12139 data-bp-card-image-primary 12140 ><img 12141 class="bp-card__image bp-card__image--secondary" 12142 src="//www.bostonproper.com/cdn/shop/files/2_61acc2c3-f92d-45fc-98d2-6b1663afb354.jpg?v=1790318148&width=720" 12143 srcset="//www.bostonproper.com/cdn/shop/files/2_61acc2c3-f92d-45fc-98d2-6b1663afb354.jpg?v=1790318148&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_61acc2c3-f92d-45fc-98d2-6b1663afb354.jpg?v=1790318148&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_61acc2c3-f92d-45fc-98d2-6b1663afb354.jpg?v=1790318148&width=720 720w" 12144 sizes="(min-width: 1024px) 25vw, 50vw" 12145 width="1639" 12146 height="2048" 12147 alt="" 12148 loading="lazy" 12149 aria-hidden="true" 12150 data-bp-card-image-secondary 12151 ></a><div class="bp-card__badges" data-bp-card-badges></div></div> 12152 12153 <div class="bp-card__body"><p class="bp-card__collection">Modern Suiting</p><h3 class="bp-card__title"> 12154 <a href="/products/modern-single-button-blazer-sesame">Modern Single Button Blazer</a> 12155 </h3> 12156 12157 <div class="bp-card__price-row"><span class="bp-card__price">$109</span> 12158 <s class="bp-card__compare">$150</s><span class="bp-card__promo">Limited time! Up to 35% off. Price as marked</span></div></div> 12159 </article> 12160</product-card> 12161</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host"> 12162 <article 12163 class="bp-card" 12164 data-product-id="15321518801062" 12165 data-product-url="/products/ultimate-ponte-crest-button-capri-black" 12166 data-bp-card-secondary-hover="true" 12167 data-bp-card-qv-dest="drawer" 12168 data-bp-card-qv-vis-d="hover" 12169 data-bp-card-qv-vis-m="shown" 12170 data-bp-card-qb-style="disabled" 12171 data-bp-track-product='{ "id": 15321518801062, "title": "Ultimate Ponte Crest Button Capri Black", "vendor": "Boston Proper", "handle": "ultimate-ponte-crest-button-capri-black", "url": "\/products\/ultimate-ponte-crest-button-capri-black", "image": "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DR1320_SET_c3def464-d326-4a18-9955-f994a93aa3e1.jpg?v=1790318145\u0026width=720", "category": "Pants", "product_type":null, "selected_variant": { "id": 56499190923430, "sku": "2DR1320500", "price": 65.0, "compare_at_price": 90.0, "option1": "Black", "option2": "XS", "product_id": 15321518801062, "available": true, "inventory_quantity": 11 } }' 12172 > 12173 <div class="bp-card__media"> 12174 <a class="bp-card__media-link" href="/products/ultimate-ponte-crest-button-capri-black" aria-label="Ultimate Ponte Crest Button Capri Black" ref="productCardLink"><img 12175 class="bp-card__image bp-card__image--primary" 12176 src="//www.bostonproper.com/cdn/shop/files/2DR1320_SET_c3def464-d326-4a18-9955-f994a93aa3e1.jpg?v=1790318145&width=720" 12177 srcset="//www.bostonproper.com/cdn/shop/files/2DR1320_SET_c3def464-d326-4a18-9955-f994a93aa3e1.jpg?v=1790318145&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DR1320_SET_c3def464-d326-4a18-9955-f994a93aa3e1.jpg?v=1790318145&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DR1320_SET_c3def464-d326-4a18-9955-f994a93aa3e1.jpg?v=1790318145&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DR1320_SET_c3def464-d326-4a18-9955-f994a93aa3e1.jpg?v=1790318145&width=1080 1080w" 12178 sizes="(min-width: 1024px) 25vw, 50vw" 12179 width="1639" 12180 height="2048" 12181 alt="Ultimate Ponte Crest Button Capri Black" 12182 loading="lazy" 12183 data-bp-card-image-primary 12184 ><img 12185 class="bp-card__image bp-card__image--secondary" 12186 src="//www.bostonproper.com/cdn/shop/files/2_0419c0c4-f9cb-4555-af46-1b5043cdb38c.jpg?v=1790318146&width=720" 12187 srcset="//www.bostonproper.com/cdn/shop/files/2_0419c0c4-f9cb-4555-af46-1b5043cdb38c.jpg?v=1790318146&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_0419c0c4-f9cb-4555-af46-1b5043cdb38c.jpg?v=1790318146&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_0419c0c4-f9cb-4555-af46-1b5043cdb38c.jpg?v=1790318146&width=720 720w" 12188 sizes="(min-width: 1024px) 25vw, 50vw" 12189 width="1639" 12190 height="2048" 12191 alt="" 12192 loading="lazy" 12193 aria-hidden="true" 12194 data-bp-card-image-secondary 12195 ></a><div class="bp-card__badges" data-bp-card-badges></div></div> 12196 12197 <div class="bp-card__body"><h3 class="bp-card__title"> 12198 <a href="/products/ultimate-ponte-crest-button-capri-black">Ultimate Ponte Crest Button Capri</a> 12199 </h3> 12200 12201 <div class="bp-card__price-row"><span class="bp-card__price">$65</span> 12202 <s class="bp-card__compare">$90</s><span class="bp-card__promo">
12202Limited time! Up to 35% off. Price as marked</span></div></div> 12203 </article> 12204</product-card> 12205</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host"> 12206 <article 12207 class="bp-card" 12208 data-product-id="15321518768294" 12209 data-product-url="/products/denim-capri-medium-wash" 12210 data-bp-card-secondary-hover="true" 12211 data-bp-card-qv-dest="drawer" 12212 data-bp-card-qv-vis-d="hover" 12213 data-bp-card-qv-vis-m="shown" 12214 data-bp-card-qb-style="disabled" 12215 data-bp-track-product='{ "id": 15321518768294, "title": "Denim Capri Medium Wash", "vendor": "Boston Proper", "handle": "denim-capri-medium-wash", "url": "\/products\/denim-capri-medium-wash", "image": "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DR1230_SET_882436a8-510d-4022-994f-d20b1d2cba14.jpg?v=1790318144\u0026width=720", "category": "Jeans", "product_type":null, "selected_variant": { "id": 56499190595750, "sku": "2DR1230000", "price": 55.0, "compare_at_price": 90.0, "option1": "Medium Wash", "option2": "0", "product_id": 15321518768294, "available": true, "inventory_quantity": 2 } }' 12216 > 12217 <div class="bp-card__media"> 12218 <a class="bp-card__media-link" href="/products/denim-capri-medium-wash" aria-label="Denim Capri Medium Wash" ref="productCardLink"><img 12219 class="bp-card__image bp-card__image--primary" 12220 src="//www.bostonproper.com/cdn/shop/files/2DR1230_SET_882436a8-510d-4022-994f-d20b1d2cba14.jpg?v=1790318144&width=720" 12221 srcset="//www.bostonproper.com/cdn/shop/files/2DR1230_SET_882436a8-510d-4022-994f-d20b1d2cba14.jpg?v=1790318144&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DR1230_SET_882436a8-510d-4022-994f-d20b1d2cba14.jpg?v=1790318144&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DR1230_SET_882436a8-510d-4022-994f-d20b1d2cba14.jpg?v=1790318144&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DR1230_SET_882436a8-510d-4022-994f-d20b1d2cba14.jpg?v=1790318144&width=1080 1080w" 12222 sizes="(min-width: 1024px) 25vw, 50vw" 12223 width="1639" 12224 height="2048" 12225 alt="Denim Capri Medium Wash" 12226 loading="lazy" 12227 data-bp-card-image-primary 12228 ><img 12229 class="bp-card__image bp-card__image--secondary" 12230 src="//www.bostonproper.com/cdn/shop/files/2_168682a3-0bba-471a-bc26-637becc1ace4.jpg?v=1790318144&width=720" 12231 srcset="//www.bostonproper.com/cdn/shop/files/2_168682a3-0bba-471a-bc26-637becc1ace4.jpg?v=1790318144&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_168682a3-0bba-471a-bc26-637becc1ace4.jpg?v=1790318144&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_168682a3-0bba-471a-bc26-637becc1ace4.jpg?v=1790318144&width=720 720w" 12232 sizes="(min-width: 1024px) 25vw, 50vw" 12233 width="1639" 12234 height="2048" 12235 alt="" 12236 loading="lazy" 12237 aria-hidden="true" 12238 data-bp-card-image-secondary 12239 ></a><div class="bp-card__badges" data-bp-card-badges></div></div> 12240 12241 <div class="bp-card__body"><h3 class="bp-card__title"> 12242 <a href="/products/denim-capri-medium-wash">Denim Capri</a> 12243 </h3> 12244 12245 <div class="bp-card__price-row"><span class="bp-card__price">$55</span> 12246 <s class="bp-card__compare">$90</s><span class="bp-card__promo">Limited time! Up to 35% off. Price as marked</span></div></div> 12247 </article> 12248</product-card> 12249</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host"> 12250 <article 12251 class="bp-card" 12252 data-product-id="15321518702758" 12253 data-product-url="/products/boston-proper-best-era-yet-t-shirt-pure-white" 12254 data-bp-card-secondary-hover="true" 12255 data-bp-card-qv-dest="drawer" 12256 data-bp-card-qv-vis-d="hover" 12257 data-bp-card-qv-vis-m="shown" 12258 data-bp-card-qb-style="disabled" 12259 data-bp-track-product='{ "id": 15321518702758, "title": "Boston Proper Best Era Yet T-Shirt Pure White", "vendor": "Boston Proper", "handle": "boston-proper-best-era-yet-t-shirt-pure-white", "url": "\/products\/boston-proper-best-era-yet-t-shirt-pure-white", "image": "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DR1140_SET_84ec4187-cdab-4754-9d74-380674ed3d9d.jpg?v=1790318143\u0026width=720", "category": "Knit Tops", "product_type":null, "selected_variant": { "id": 56499190202534, "sku": "2DR1140400", "price": 30.0, "compare_at_price": 30.0, "option1": "Pure White", "option2": "XXS", "product_id": 15321518702758, "available": true, "inventory_quantity": 8 } }' 12260 > 12261 <div class="bp-card__media"> 12262 <a class="bp-card__media-link" href="/products/boston-proper-best-era-yet-t-shirt-pure-white" aria-label="Boston Proper Best Era Yet T-Shirt Pure White" ref="productCardLink"><img 12263 class="bp-card__image bp-card__image--primary" 12264 src="//www.bostonproper.com/cdn/shop/files/2DR1140_SET_84ec4187-cdab-4754-9d74-380674ed3d9d.jpg?v=1790318143&width=720" 12265 srcset="//www.bostonproper.com/cdn/shop/files/2DR1140_SET_84ec4187-cdab-4754-9d74-380674ed3d9d.jpg?v=1790318143&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DR1140_SET_84ec4187-cdab-4754-9d74-380674ed3d9d.jpg?v=1790318143&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DR1140_SET_84ec4187-cdab-4754-9d74-380674ed3d9d.jpg?v=1790318143&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DR1140_SET_84ec4187-cdab-4754-9d74-380674ed3d9d.jpg?v=1790318143&width=1080 1080w" 12266 sizes="(min-width: 1024px) 25vw, 50vw" 12267 width="1639" 12268 height="2048" 12269 alt="Boston Proper Best Era Yet T-Shirt Pure White" 12270 loading="lazy" 12271 data-bp-card-image-primary 12272 ><img 12273 class="bp-card__image bp-card__image--secondary" 12274 src="//www.bostonproper.com/cdn/shop/files/2_421c55a0-3294-4ae6-9960-baf5c996aa3e.jpg?v=1790318143&width=720" 12275 srcset="//www.bostonproper.com/cdn/shop/files/2_421c55a0-3294-4ae6-9960-baf5c996aa3e.jpg?v=1790318143&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_421c55a0-3294-4ae6-9960-baf5c996aa3e.jpg?v=1790318143&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_421c55a0-3294-4ae6-9960-baf5c996aa3e.jpg?v=1790318143&width=720 720w" 12276 sizes="(min-width: 1024px) 25vw, 50vw" 12277 width="1639" 12278 height="2048" 12279 alt="" 12280 loading="lazy" 12281 aria-hidden="true" 12282 data-bp-card-image-secondary 12283 ></a><div class="bp-card__badges" data-bp-card-badges></div></div> 12284 12285 <div class="bp-card__body"><h3 class="bp-card__title"> 12286 <a href="/products/boston-proper-best-era-yet-t-shirt-pure-white">Boston Proper Best Era Yet T-Shirt</a> 12287 </h3> 12288 12289 <div class="bp-card__price-row"><span class="bp-card__price">$30</span> 12290 <s class="bp-card__compare" hidden></s></div></div> 12291 </article> 12292</product-card> 12293</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host"> 12294 <article 12295 class="bp-card" 12296 data-product-id="15300355555494" 12297 data-product-url="/products/printed-woven-back-denim-jacket-cheetah-gems" 12298 data-bp-card-secondary-hover="true" 12299 data-bp-card-qv-dest="drawer" 12300 data-bp-card-qv-vis-d="hover" 12301 data-bp-card-qv-vis-m="shown" 12302 data-bp-card-qb-style="disabled" 12303 data-bp-track-product='{ "id": 15300355555494, "title": "Printed Woven Back Denim Jacket Cheetah Gems", "vendor": "Boston Proper", "handle": "printed-woven-back-denim-jacket-cheetah-gems", "url": "\/products\/printed-woven-back-denim-jacket-cheetah-gems", "image": "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO4480_SET.jpg?v=1790318126\u0026width=720", "category": "Jackets", "product_type":null, "selected_variant": { "id": 56437744271526, "sku": "2DO4480400", "price": 99.0, "compare_at_price": 130.0, "option1": "Cheetah Gems", "option2": "XXS", "product_id": 15300355555494, "available": true, "inventory_quantity": 12 } }' 12304 > 12305 <div class="bp-card__media"> 12306 <a class="bp-card__media-link" href="/products/printed-woven-back-denim-jacket-cheetah-gems" aria-label="Printed Woven Back Denim Jacket Cheetah Gems" ref="productCardLink"><img 12307 class="bp-card__image bp-card__image--primary" 12308 src="//www.bostonproper.com/cdn/shop/files/2DO4480_SET.jpg?v=1790318126&width=720" 12309 srcset="//www.bostonproper.com/cdn/shop/files/2DO4480_SET.jpg?v=1790318126&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DO4480_SET.jpg?v=1790318126&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DO4480_SET.jpg?v=1790318126&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DO4480_SET.jpg?v=1790318126&width=1080 1080w" 12310 sizes="(min-width: 1024px) 25vw, 50vw" 12311 width="1639" 12312 height="2048" 12313 alt="Printed Woven Back Denim Jacket Cheetah Gems" 12314 loading="lazy" 12315 data-bp-card-image-primary 12316 ><img 12317 class="bp-card__image bp-card__image--secondary" 12318 src="//www.bostonproper.com/cdn/shop/files/2_d818b3c
12318d-ab17-4001-92be-bfcf75b3f9b4.jpg?v=1790318126&width=720" 12319 srcset="//www.bostonproper.com/cdn/shop/files/2_d818b3cd-ab17-4001-92be-bfcf75b3f9b4.jpg?v=1790318126&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_d818b3cd-ab17-4001-92be-bfcf75b3f9b4.jpg?v=1790318126&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_d818b3cd-ab17-4001-92be-bfcf75b3f9b4.jpg?v=1790318126&width=720 720w" 12320 sizes="(min-width: 1024px) 25vw, 50vw" 12321 width="1639" 12322 height="2048" 12323 alt="" 12324 loading="lazy" 12325 aria-hidden="true" 12326 data-bp-card-image-secondary 12327 ></a><div class="bp-card__badges" data-bp-card-badges></div></div> 12328 12329 <div class="bp-card__body"><h3 class="bp-card__title"> 12330 <a href="/products/printed-woven-back-denim-jacket-cheetah-gems">Printed Woven Back Denim Jacket</a> 12331 </h3> 12332 12333 <div class="bp-card__price-row"><span class="bp-card__price">$99</span> 12334 <s class="bp-card__compare">$130</s><span class="bp-card__promo">Limited time! Up to 35% off. Price as marked</span></div></div> 12335 </article> 12336</product-card> 12337</li><li class="bp-cart-drawer__recs-card"><product-card class="bp-card-host"> 12338 <article 12339 class="bp-card" 12340 data-product-id="15298631631014" 12341 data-product-url="/products/essential-printed-cami-tiny-midnight-dot" 12342 data-bp-card-secondary-hover="true" 12343 data-bp-card-qv-dest="drawer" 12344 data-bp-card-qv-vis-d="hover" 12345 data-bp-card-qv-vis-m="shown" 12346 data-bp-card-qb-style="disabled" 12347 data-bp-track-product='{ "id": 15298631631014, "title": "Essential Printed Cami Tiny Midnight Dot", "vendor": "Boston Proper", "handle": "essential-printed-cami-tiny-midnight-dot", "url": "\/products\/essential-printed-cami-tiny-midnight-dot", "image": "\/\/www.bostonproper.com\/cdn\/shop\/files\/2DN7421_SET.jpg?v=1790318119\u0026width=720", "category": "Knit Tops", "product_type":null, "selected_variant": { "id": 56433081155750, "sku": "2DN7421400", "price": 25.0, "compare_at_price": 30.0, "option1": "Tiny Midnight Dot", "option2": "XXS", "product_id": 15298631631014, "available": true, "inventory_quantity": 31 } }' 12348 > 12349 <div class="bp-card__media"> 12350 <a class="bp-card__media-link" href="/products/essential-printed-cami-tiny-midnight-dot" aria-label="Essential Printed Cami Tiny Midnight Dot" ref="productCardLink"><img 12351 class="bp-card__image bp-card__image--primary" 12352 src="//www.bostonproper.com/cdn/shop/files/2DN7421_SET.jpg?v=1790318119&width=720" 12353 srcset="//www.bostonproper.com/cdn/shop/files/2DN7421_SET.jpg?v=1790318119&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DN7421_SET.jpg?v=1790318119&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DN7421_SET.jpg?v=1790318119&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DN7421_SET.jpg?v=1790318119&width=1080 1080w" 12354 sizes="(min-width: 1024px) 25vw, 50vw" 12355 width="1639" 12356 height="2048" 12357 alt="Essential Printed Cami Tiny Midnight Dot" 12358 loading="lazy" 12359 data-bp-card-image-primary 12360 ><img 12361 class="bp-card__image bp-card__image--secondary" 12362 src="//www.bostonproper.com/cdn/shop/files/2_dc0d2c36-038f-4a0c-a1b3-0d29a54aede0.jpg?v=1790318119&width=720" 12363 srcset="//www.bostonproper.com/cdn/shop/files/2_dc0d2c36-038f-4a0c-a1b3-0d29a54aede0.jpg?v=1790318119&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_dc0d2c36-038f-4a0c-a1b3-0d29a54aede0.jpg?v=1790318119&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_dc0d2c36-038f-4a0c-a1b3-0d29a54aede0.jpg?v=1790318119&width=720 720w" 12364 sizes="(min-width: 1024px) 25vw, 50vw" 12365 width="1639" 12366 height="2048" 12367 alt="" 12368 loading="lazy" 12369 aria-hidden="true" 12370 data-bp-card-image-secondary 12371 ></a><div class="bp-card__badges" data-bp-card-badges></div></div> 12372 12373 <div class="bp-card__body"><h3 class="bp-card__title"> 12374 <a href="/products/essential-printed-cami-tiny-midnight-dot">Essential Printed Cami</a> 12375 </h3> 12376 12377 <div class="bp-card__price-row"><span class="bp-card__price">$25</span> 12378 <s class="bp-card__compare">$30</s><span class="bp-card__promo">
12378Limited time! Up to 35% off. Price as marked</span></div></div> 12379 </article> 12380</product-card> 12381</li></ul> 12382 </div></div> 12383 <ul class="bp-cart-drawer__items" data-bp-cart-items hidden></ul><section class="bp-cart-drawer__ctl" data-bp-ctl hidden> 12384 <header class="bp-cart-drawer__ctl-head"> 12385 <h3 class="bp-cart-drawer__ctl-title">Complete the Look</h3> 12386 <div class="bp-cart-drawer__ctl-arrows"> 12387 <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"> 12388 <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"/> 12389 <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"/> 12390 </svg> 12391 </button> 12392 <button type="button" class="bp-cart-drawer__ctl-arrow" data-bp-ctl-next aria-label="Next"> 12393 <svg width="44" height="44" viewBox="0 0 44 44" fill="none" aria-hidden="true"> 12394 <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"/> 12395 <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"/> 12396 </svg> 12397 </button> 12398 </div> 12399 </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> 12400 </section> 12401 </div><footer class="bp-cart-drawer__foot" hidden><section 12402 class="bp-cart-discount bp-cart-discount--drawer" 12403 data-bp-cart-discount 12404 data-bp-existing-codes="" 12405><div class="bp-cart-discount__collapse" data-bp-promo-collapse> 12406 <button 12407 type="button" 12408 class="bp-cart-discount__summary" 12409 data-bp-promo-toggle 12410 aria-expanded="false" 12411 aria-controls="bp-promo-body-drawer" 12412 >
12413 <span class="bp-cart-discount__summary-text">Promo code</span> 12414 <svg class="bp-cart-discount__summary-chev" width="12" height="8" viewBox="0 0 12 8" fill="none" aria-hidden="true"> 12415 <path d="M1 1.5L6 6.5L11 1.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/> 12416 </svg> 12417 </button> 12418 <div class="bp-cart-discount__collapse-body" id="bp-promo-body-drawer" data-bp-promo-body> 12419 <div class="bp-cart-discount__collapse-inner"><form class="bp-cart-discount__form" data-bp-cart-discount-form novalidate> 12420 <div class="bp-cart-discount__row"> 12421 <input 12422 type="text" 12423 id="bp-cart-discount-input-drawer" 12424 name="discount" 12425 class="bp-cart-discount__input" 12426 placeholder="Enter promo code" 12427 autocomplete="off" 12428 autocapitalize="characters" 12429 spellcheck="false" 12430 data-bp-cart-discount-input 12431 aria-label="Promo code" 12432 aria-describedby="bp-cart-discount-error-drawer" 12433 > 12434 <button type="submit" class="bp-cart-discount__submit" data-bp-cart-discount-submit>Apply</button> 12435 </div> 12436 <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> 12437 </form></div> 12438 </div> 12439 </div></section> 12440 12441<style data-shopify> 12442 .bp-cart-discount { 12443 width: 100%; 12444 margin: 12px 0 0; 12445 font-family: var(--bp-font-body); 12446 } 12447 /* Drawer footer (snippets/bp-cart-drawer.liquid) is a flex column with 12448 its own `gap` between rows â this block's own top margin stacked on 12449 top of that gap, doubling the space above it. Page surface keeps the 12450 margin (not laid out in a gapped flex stack). */ 12451 .bp-cart-discount--drawer { margin-top: 0; } 12452 .bp-cart-discount__form { margin: 0; padding: 0; } 12453 12454 /* Collapsible promo bar (drawer). Collapsed = just the summary row, 12455 so the sticky footer reclaims the input + button height. The body 12456 grows/shrinks with a grid-template-rows 0fr<->1fr transition. */ 12457 .bp-cart-discount__collapse { width: 100%; } 12458 .bp-cart-discount__summary { 12459 display: flex; 12460 width: 100%; 12461 align-items: center; 12462 justify-content: space-between; 12463 gap: 8px; 12464 margin: 0; 12465 padding: 2px 0; 12466 background: transparent; 12467 border: 0; 12468 text-align: left; 12469 cursor: pointer; 12470 font-family: var(--bp-font-body); 12471 font-size: 12px; 12472 font-weight: 700; 12473 letter-spacing: 0.5px; 12474 text-transform: uppercase; 12475 color: var(--bp-color-text); 12476 } 12477 .bp-cart-discount__summary:focus-visible { 12478 outline: 2px solid var(--bp-color-text); 12479 outline-offset: 2px; 12480 } 12481 .bp-cart-discount__summary-chev { 12482 flex: 0 0 auto; 12483 transition: transform 0.28s ease; 12484 } 12485 .bp-cart-discount__collapse.is-open .bp-cart-discount__summary-chev { transform: rotate(180deg); } 12486 12487 .bp-cart-discount__collapse-body { 12488 display: grid; 12489 grid-template-rows: 0fr; 12490 transition: grid-template-rows 0.28s ease; 12491 } 12492 .bp-cart-discount__collapse.is-open .bp-cart-discount__collapse-body { grid-template-rows: 1fr; } 12493 /* The inner wrapper is the animated row â must clip + allow 0 height. */ 12494 .bp-cart-discount__collapse-inner { 12495 overflow: hidden; 12496 min-height: 0; 12497 padding-top: 10px; 12498 } 12499 @media (prefers-reduced-motion: reduce) { 12500 .bp-cart-discount__collapse-body, 12501 .bp-cart-discount__summary-chev { transition: none; } 12502 } 12503 12504 .bp-cart-discount__label { 12505 display: block; 12506 margin: 0 0 6px; 12507 font-size: 12px; 12508 font-weight: 700; 12509 letter-spacing: 0.5px; 12510 text-transform: uppercase; 12511 color: var(--bp-color-text); 12512 } 12513 .bp-cart-discount__row { 12514 display: flex; 12515 gap: 8px; 12516 align-items: stretch; 12517 } 12518 .bp-cart-discount__input { 12519 flex: 1 1 auto; 12520 min-width: 0; 12521 height: 44px; 12522 padding: 0 12px; 12523 background: transparent; 12524 border: 1px solid rgba(23, 22, 9, 0.32); 12525 color: var(--bp-color-text); 12526 font-family: var(--bp-font-body); 12527 font-size: 14px; 12528 line-height: 1; 12529 letter-spacing: 0.04em; 12530 text-transform: uppercase; 12531 box-sizing: border-box; 12532 } 12533 .bp-cart-discount__input::placeholder { color: var(--bp-color-body-copy, #74736B); text-transform: none; letter-spacing: -0.14px; } 12534 .bp-cart-discount__input:focus { 12535 outline: none; 12536 border-color: var(--bp-color-text); 12537 } 12538 .bp-cart-discount__input:focus-visible { 12539 outline: 2px solid var(--bp-color-text); 12540 outline-offset: 2px; 12541 } 12542 .bp-cart-discount__submit { 12543 flex: 0 0 auto; 12544 height: 44px; 12545 padding: 0 20px; 12546 background: var(--bp-color-text); 12547 color: var(--bp-color-cta-text); 12548 border: 0; 12549 font-family: var(--bp-font-body); 12550 font-size: 14px; 12551 font-weight: 500; 12552 letter-spacing: -0.14px; 12553 cursor: pointer; 12554 transition: opacity 0.2s ease; 12555 } 12556 .bp-cart-discount__submit:hover { opacity: 0.85; } 12557 .bp-cart-discount__submit:disabled { opacity: 0.5;
12557 cursor: not-allowed; } 12558 .bp-cart-discount__error { 12559 margin: 8px 0 0; 12560 color: var(--bp-color-promo, #B5341B); 12561 font-size: 12px; 12562 line-height: 145%; 12563 letter-spacing: -0.12px; 12564 } 12565 12566 /* Applied-code pills */ 12567 .bp-cart-discount__pills { 12568 list-style: none; 12569 margin: 10px 0 0; 12570 padding: 0; 12571 display: flex; 12572 flex-wrap: wrap; 12573 gap: 6px; 12574 } 12575 .bp-cart-discount__pill { 12576 display: inline-flex; 12577 align-items: center; 12578 gap: 6px; 12579 padding: 4px 4px 4px 10px; 12580 background: var(--bp-color-bg-cream, #F7F6EA); 12581 color: var(--bp-color-text); 12582 font-size: 12px; 12583 font-weight: 500; 12584 letter-spacing: 0.04em; 12585 text-transform: uppercase; 12586 border-radius: 0; 12587 } 12588 .bp-cart-discount__pill-code { line-height: 1; } 12589 .bp-cart-discount__pill-remove { 12590 display: inline-flex; 12591 align-items: center; 12592 justify-content: center; 12593 width: 20px; 12594 height: 20px; 12595 padding: 0; 12596 background: transparent; 12597 border: 0; 12598 color: var(--bp-color-text); 12599 cursor: pointer; 12600 border-radius: 50%; 12601 transition: background 0.15s ease; 12602 } 12603 .bp-cart-discount__pill-remove:hover { background: rgba(23, 22, 9, 0.08); } 12604</style> 12605
12606<script> 12607 (function () { 12608 if (window.__bpCartDiscountWired) return; 12609 window.__bpCartDiscountWired = true; 12610 12611 const ROOT = (window.Shopify && window.Shopify.routes && window.Shopify.routes.root) || '/'; 12612 12613 function getCodesFromHost(host) { 12614 const raw = host.getAttribute('data-bp-existing-codes') || ''; 12615 return raw ? raw.split(',').filter(Boolean) : []; 12616 } 12617 12618 async function postDiscount(codes) { 12619 const res = await fetch(ROOT + 'cart/update.js', { 12620 method: 'POST', 12621 headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, 12622 body: JSON.stringify({ discount: codes.join(',') }), 12623 credentials: 'same-origin', 12624 cache: 'no-store', 12625 }); 12626 if (!res.ok) throw new Error('cart/update.js HTTP ' + res.status); 12627 return res.json(); 12628 } 12629 12630 function setError(host, show, msg) { 12631 const el = host.querySelector('[data-bp-cart-discount-error]'); 12632 const input = host.querySelector('[data-bp-cart-discount-input]'); 12633 if (input) input.setAttribute('aria-invalid', show ? 'true' : 'false'); 12634 if (!el) return; 12635 if (show) { 12636 if (msg) el.textContent = msg; 12637 el.hidden = false; 12638 } else { 12639 el.hidden = true; 12640 } 12641 } 12642 12643 function isApplicableInCart(cart, code) { 12644 return (cart.discount_codes || []).some((d) => d.code === code && d.applicable === true); 12645 } 12646 12647 function esc(s) { 12648 return String(s == null ? '' : s) 12649 .replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>') 12650 .replace(/"/g, '"'); 12651 } 12652 12653 // Rebuild the applied-code pills in place so they behave like checkout: 12654 // a chip with a remove appears the moment a code applies and clears the 12655 // moment it is removed, with no page reload. Mirrors the server-rendered 12656 // pill markup; the delegated remove handler below covers injected buttons. 12657 function renderPills(host, applied) { 12658 const form = host.querySelector('[data-bp-cart-discount-form]'); 12659 if (!form) return; 12660 let ul = host.querySelector('[data-bp-cart-discount-pills]'); 12661 if (!applied.length) { if (ul) ul.remove(); return; } 12662 if (!ul) { 12663 ul = document.createElement('ul'); 12664 ul.className = 'bp-cart-discount__pills'; 12665 ul.setAttribute('data-bp-cart-discount-pills', ''); 12666 ul.setAttribute('role', 'list'); 12667 form.parentNode.insertBefore(ul, form.nextSibling); 12668 } 12669 ul.innerHTML = applied.map((code) => { 12670 const c = esc(code); 12671 return '<li class="bp-cart-discount__pill" data-bp-cart-discount-pill data-discount-code="' + c + '">' + 12672 '<span class="bp-cart-discount__pill-code">' + c + '</span>' + 12673 '<button type="button" class="bp-cart-discount__pill-remove" aria-label="Remove ' + c + '" data-bp-cart-discount-remove="' + c + '">' + 12674 '<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>' + 12675 '</button></li>'; 12676 }).join(''); 12677 } 12678 12679 function broadcastCartUpdate(cart) { 12680 document.dispatchEvent(new CustomEvent('cart:updated', { detail: { cart } })); 12681 // Update every BP-discount host's data-bp-existing-codes (so the next 12682 // submit carries the new state) AND re-render its applied-code pills in 12683 // place, so the removable chip shows/clears live like the checkout one. 12684 const applied = (cart.discount_codes || []) 12685 .filter((d) => d.applicable) 12686 .map((d) => d.code); 12687 document.querySelectorAll('[data-bp-cart-discount]').forEach((host) => { 12688 host.setAttribute('data-bp-existing-codes', applied.join(',')); 12689 renderPills(host, applied); 12690 }); 12691 } 12692 12693 // Collapsible promo bar (drawer) â toggle the accordion open/closed. 12694 document.addEventListener('click', (e) => { 12695 const toggle = e.target && e.target.closest && e.target.closest('[data-bp-promo-toggle]'); 12696 if (!toggle) return; 12697 const collapse = toggle.closest('[data-bp-promo-collapse]'); 12698 if (!collapse) return; 12699 const open = collapse.classList.toggle('is-open'); 12700 toggle.setAttribute('aria-expanded', open ? 'true' : 'false'); 12701 }); 12702 12703 document.addEventListener('submit', async (e) => { 12704 const form = e.target && e.target.closest && e.target.closest('[data-bp-cart-discount-form]'); 12705 if (!form) return; 12706 e.preventDefault(); 12707 const host = form.closest('[data-bp-cart-discount]'); 12708 const input = form.querySelector('[data-bp-cart-discount-input]'); 12709 const submit = form.querySelector('[data-bp-cart-discount-submit]'); 12710 if (!host || !input) return; 12711 const code = (input.value || '').trim(); 12712 if (!code) return; 12713 12714 const existing = getCodesFromHost(host); 12715 if (existing.includes(code)) { 12716 input.value = ''; 12717 return; 12718 } 12719 setError(host, false); 12720 if (submit) submit.disabled = true;
12721 try { 12722 const cart = await postDiscount(existing.concat([code])); 12723 if (!isApplicableInCart(cart, code)) { 12724 setError(host, true); 12725 input.value = ''; 12726 return; 12727 } 12728 broadcastCartUpdate(cart); 12729 input.value = ''; 12730 // Success confirmation. The subtotal change alone is easy to miss and 12731 // the applied-code pills only re-render on reload, so the shopper had 12732 // no signal the code applied (QA 7/22, Dragana). Surface a toast now. 12733 if (window.bpToast) window.bpToast('Promo code "' + code + '" applied.'); 12734 } catch (err) { 12735 console.warn('[bp-cart-discount] apply failed', err); 12736 setError(host, true, 'Something went wrong. Please try again.'); 12737 } finally { 12738 if (submit) submit.disabled = false; 12739 } 12740 }); 12741 12742 document.addEventListener('click', async (e) => { 12743 const btn = e.target && e.target.closest && e.target.closest('[data-bp-cart-discount-remove]'); 12744 if (!btn) return; 12745 e.preventDefault(); 12746 const host = btn.closest('[data-bp-cart-discount]'); 12747 if (!host) return; 12748 const codeToRemove = btn.getAttribute('data-bp-cart-discount-remove'); 12749 const existing = getCodesFromHost(host).filter((c) => c !== codeToRemove);
12750 try { 12751 const cart = await postDiscount(existing); 12752 broadcastCartUpdate(cart); 12753 } catch (err) { 12754 console.warn('[bp-cart-discount] remove failed', err); 12755 } 12756 }); 12757 12758 // Hydrate the applied-code pills from the live cart on load. A code applied 12759 // in a PRIOR session (persisted on the cart) reliably shows up in /cart.js 12760 // discount_codes, but the server-side Liquid cart object can render empty 12761 // for it, so the server-rendered pill was missing and an already-applied 12762 // code showed no chip until re-applied. Reading the live cart here makes 12763 // the removable chip appear on load regardless. 12764 (function hydrateAppliedCodes() { 12765 const run = () => { 12766 if (!document.querySelector('[data-bp-cart-discount]')) return; 12767 fetch(ROOT + 'cart.js', { credentials: 'same-origin', cache: 'no-store' }) 12768 .then((r) => (r.ok ? r.json() : null)) 12769 .then((cart) => { 12770 if (!cart) return; 12771 const applied = (cart.discount_codes || []) 12772 .filter((d) => d.applicable) 12773 .map((d) => d.code); 12774 document.querySelectorAll('[data-bp-cart-discount]').forEach((host) => { 12775 host.setAttribute('data-bp-existing-codes', applied.join(',')); 12776 renderPills(host, applied); 12777 }); 12778 }) 12779 .catch(() => {}); 12780 }; 12781 if (document.readyState === 'loading') { 12782 document.addEventListener('DOMContentLoaded', run); 12783 } else { 12784 run(); 12785 } 12786 })(); 12787 })(); 12788</script>
12788 12789 12790<div class="bp-cart-drawer__subtotal"> 12791 <span class="bp-cart-drawer__subtotal-label">Subtotal:</span> 12792 <span class="bp-cart-drawer__subtotal-value" data-bp-cart-subtotal>$0</span><span class="totals__subtotal-value" aria-hidden="true" hidden></span> 12793 </div> 12794<div class="bp-cart-drawer__sp-skeleton" data-bp-sp-skeleton aria-hidden="true"> 12795 <div class="bp-cart-drawer__sp-skeleton-head"> 12796 <span class="bp-sp-skeleton-bar bp-cart-drawer__sp-skeleton-title"></span> 12797 <span class="bp-sp-skeleton-bar bp-cart-drawer__sp-skeleton-amt"></span> 12798 </div> 12799 <span class="bp-sp-skeleton-bar bp-cart-drawer__sp-skeleton-desc"></span> 12800 </div> 12801 <div 12802 id="narvar-cart-drawer-dp-widget" 12803 class="bp-cart-drawer__narvar-widget" 12804 data-skip-node-update 12805 data-skip-subtree-update 12806 ></div> 12807 12808 <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 12809 type="submit" 12810 name="checkout" 12811 class="bp-cart-drawer__btn bp-cart-drawer__btn--primary" 12812 data-narvar-feature="CartCheckoutButton" 12813 data-skip-node-update 12814 data-skip-subtree-update 12815 > 12816 Checkout 12817 </button> 12818 <div 12819 id="narvar-cart-drawer-dp-buttons" 12820 class="bp-cart-drawer__narvar-buttons" 12821 data-skip-node-update 12822 data-skip-subtree-update 12823 ></div> 12824 </form> 12825 <a href="/cart" class="bp-cart-drawer__view-bag">View Bag</a> 12826 </footer> 12827 </dialog> 12828</bp-cart-drawer> 12829 12830<style data-shopify> 12831 /* ===== BP Cart Drawer ===== */ 12832 bp-cart-drawer { display: contents; } 12833 12834 /* Trigger (icon button in header) â inherits header sizing. */ 12835 .bp-cart-drawer__trigger { 12836 position: relative; 12837 background: transparent; 12838 border: 0; 12839 padding: 0; 12840 cursor: pointer; 12841 color: var(--color-foreground); 12842 display: inline-flex; 12843 align-items: center; 12844 justify-content: center; 12845 width: 44px; 12846 height: 44px; 12847 } 12848 .bp-cart-drawer__trigger svg { width: 24px; height: 24px; display: block; } 12849 .bp-cart-drawer__trigger-count { 12850 position: absolute; 12851 top: 4px; 12852 right: 4px; 12853 min-width: 18px; 12854 height: 18px; 12855 padding: 0 5px; 12856 /* 18Ã18 circular notification badge â kept as a circle (50%) 12857 rather than squared off per the "no rounded corners" sweep 12858 since notification bubbles are conventionally circular and 12859 9px on an 18Ã18 is geometrically a circle anyway. */ 12860 border-radius: 50%; 12861 background: #EBAE55; 12862 /* Dark ink on the gold badge â white (#fff) on #EBAE55 is only 1.96:1, 12863 failing WCAG AA (QA). #171609 on the gold clears AA comfortably. The 12864 larger .bp-cart-drawer__bubble already uses this. */ 12865 color: var(--bp-color-text); 12866 font-family: var(--bp-font-body); 12867 font-size: 11px; 12868 font-weight: 500; 12869 display: inline-flex; 12870 align-items: center; 12871 justify-content: center; 12872 } 12873 .bp-cart-drawer__trigger-count[hidden] { display: none; } 12874 12875 /* Dialog. */ 12876 .bp-cart-drawer__dialog { 12877 position: fixed; 12878 inset: 0 0 0 auto; 12879 margin: 0; 12880 padding: 0; 12881 border: 0; 12882 width: calc(100vw / 3); 12883 min-width: 480px; 12884 max-width: 100vw; 12885 height: 100dvh; 12886 max-height: 100dvh; 12887 background: var(--bp-color-bg-page, #FEFFFA); 12888 color: var(--bp-color-text); 12889 box-shadow: -8px 0 30px rgb(0 0 0 / 0.12); 12890 overflow: hidden; 12891 font-family: var(--bp-font-body); 12892 z-index: 9999; 12893 } 12894 .bp-cart-drawer__dialog[open] { 12895 display: flex; 12896 flex-direction: column; 12897 animation: bpDrawerSlideIn 0.25s cubic-bezier(0.4, 0, 0.2, 1) forwards; 12898 } 12899 .bp-cart-drawer__dialog.is-closing { 12900 animation: bpDrawerSlideOut 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards; 12901 } 12902 .bp-cart-drawer__dialog::backdrop { background: rgb(0 0 0 / 0.3); } 12903 @media (max-width: 749px) { 12904 .bp-cart-drawer__dialog { width: 100vw; min-width: 0; } 12905 /* Tighter footer on mobile (QA 7/23, Brooke â Figma parity). */ 12906 .bp-cart-drawer__foot { padding: 16px !important; gap: 4px !important; } 12907 } 12908 12909 /* Header. */ 12910 .bp-cart-drawer__header { 12911 flex: 0 0 auto; 12912 display: flex; 12913 align-items: center; 12914 justify-content: space-between; 12915 padding: 20px 24px; 12916 border-bottom: 1px solid rgba(23, 22, 9, 0.08); 12917 background: var(--bp-color-bg-page, #FEFFFA); 12918 } 12919 .bp-cart-drawer__heading { 12920 margin: 0; 12921 display: inline-flex; 12922 align-items: center; 12923 gap: 12px; 12924 color: var(--bp-color-text); 12925 font-family: var(--bp-font-display); 12926 font-size: 28px; 12927 font-weight: 300; 12928 line-height: 120%; 12929 letter-spacing: -0.56px; 12930 } 12931 .bp-cart-drawer__bubble { 12932 /* Sunset pill (QA 7/23, Brooke â was 32px circle, white text) */ 12933 display: flex; 12934 width: 40px; 12935 padding: 10px 0; 12936 justify-content: center;
12937 align-items: center; 12938 border-radius: 100px; 12939 background: #EBAE55; 12940 color: var(--bp-color-text); 12941 text-align: center; 12942 /* Body / Semi / Small */ 12943 font-family: var(--bp-font-body); 12944 font-size: 14px; 12945 font-weight: 660; 12946 line-height: 145%; 12947 letter-spacing: -0.14px; 12948 } 12949 .bp-cart-drawer__close { 12950 background: transparent; 12951 border: 0; 12952 padding: 0; 12953 width: 32px; 12954 height: 32px; 12955 cursor: pointer; 12956 color: var(--bp-color-text); 12957 display: inline-flex; 12958 align-items: center; 12959 justify-content: center; 12960 } 12961 .bp-cart-drawer__close:hover { opacity: 0.6; } 12962 12963 .bp-cart-drawer__body { 12964 flex: 1 1 auto; 12965 overflow-y: auto; 12966 padding: 0 24px; 12967 } 12968 12969 /* Items list. */ 12970 .bp-cart-drawer__items { 12971 margin: 0; 12972 padding: 0; 12973 list-style: none; 12974 } 12975 12976 .bp-cart-drawer__empty { 12977 padding: 48px 0; 12978 text-align: center; 12979 color: var(--bp-color-body-copy); 12980 font-family: var(--bp-font-body); 12981 } 12982 .bp-cart-drawer__empty-cta { 12983 /* CTA / CTA Regular */ 12984 display: block; 12985 margin: 12px auto 0; 12986 background: transparent; 12987 border: 0; 12988 padding: 0; 12989 cursor: pointer; 12990 font-family: var(--bp-font-body); 12991 font-size: 17px; 12992 font-style: normal; 12993 font-weight: 500; 12994 line-height: normal; 12995 letter-spacing: -0.17px; 12996 leading-trim: both; 12997 text-edge: cap; 12998 color: var(--bp-color-text); 12999 text-decoration: underline; 13000 text-underline-offset: 3px; 13001 } 13002 13003 /* "Recommended for you" rail in the empty bag (QA 7/16). */ 13004 .bp-cart-drawer__recs { 13005 margin-top: 40px; 13006 text-align: left; 13007 } 13008 .bp-cart-drawer__recs-head { 13009 display: flex; 13010 align-items: center; 13011 justify-content: space-between; 13012 gap: 12px; 13013 margin-bottom: 16px; 13014 } 13015 .bp-cart-drawer__recs-title { 13016 font-family: var(--bp-font-display); 13017 font-size: 18px; 13018 font-weight: 300; 13019 letter-spacing: -0.36px; 13020 color: var(--bp-color-text); 13021 margin: 0; 13022 } 13023 .bp-cart-drawer__recs-arrows { display: inline-flex; gap: 12px; flex-shrink: 0; } 13024 .bp-cart-drawer__recs-arrow { 13025 /* 44px hit area â same chevron frame as Complete the Look / YMAL. */ 13026 width: 44px; 13027 height: 44px; 13028 background: transparent; 13029 border: 0; 13030 padding: 0; 13031 cursor: pointer; 13032 color: var(--bp-color-text); 13033 display: inline-flex; 13034 align-items: center; 13035 justify-content: center; 13036 transition: opacity 0.15s ease; 13037 } 13038 .bp-cart-drawer__recs-arrow:hover { opacity: 0.6; } 13039 /* Both buttons carry the right-pointing glyph; mirror the prev one. */ 13040 .bp-cart-drawer__recs-arrow[data-bp-recs-prev] svg { transform: scaleX(-1); } 13041 .bp-cart-drawer__recs-track { 13042 display: flex; 13043 gap: 12px; 13044 margin: 0; 13045 padding: 0; 13046 list-style: none; 13047 overflow-x: auto; 13048 scroll-snap-type: x mandatory; 13049 scrollbar-width: none; 13050 -ms-overflow-style: none; 13051 } 13052 .bp-cart-drawer__recs-track::-webkit-scrollbar { display: none; } 13053 /* Each rail item holds a full bp-product-card (collection eyebrow, swatches, 13054 price). Fixed width so the cards peek in the horizontal rail. */ 13055 .bp-cart-drawer__recs-card { 13056 /* % of the rail so ~2.3 cards show (two full + a peek of the third) 13057 regardless of drawer width, rather than three cramped ones (QA 7/27). */ 13058 flex: 0 0 42%; 13059 scroll-snap-align: start; 13060 } 13061 13062 /* Complete the Look. */ 13063 .bp-cart-drawer__ctl { padding: 24px 0 8px; } 13064 .bp-cart-drawer__ctl-head { 13065 display: flex; 13066 align-items: center; 13067 justify-content: space-between; 13068 margin-bottom: 12px; 13069 } 13070 .bp-cart-drawer__ctl-title { 13071 margin: 0; 13072 font-family: var(--bp-font-display); 13073 font-size: 20px; 13074 font-weight: 300; 13075 letter-spacing: -0.4px; 13076 color: var(--bp-color-text); 13077 } 13078 .bp-cart-drawer__ctl-arrows { display: inline-flex; gap: 12px; } 13079 .bp-cart-drawer__ctl-arrow { 13080 /* 44px hit area matches the Figma chevron frame (QA 7/23). */ 13081 width: 44px; 13082 height: 44px; 13083 background: transparent; 13084 border: 0; 13085 padding: 0; 13086 cursor: pointer; 13087 color: var(--bp-color-text); 13088 display: inline-flex; 13089 align-items: center; 13090 justify-content: center; 13091 transition: opacity 0.15s ease; 13092 } 13093 .bp-cart-drawer__ctl-arrow:hover { opacity: 0.6; } 13094 /* Both buttons carry the right-pointing glyph; mirror the prev one. */ 13095 .bp-cart-drawer__ctl-arrow[data-bp-ctl-prev] svg { transform: scaleX(-1); } 13096 13097 .bp-cart-drawer__ctl-track { 13098 display: flex; 13099 gap: 12px; 13100 overflow-x: auto; 13101 scroll-behavior: smooth; 13102 scroll-snap-type: x mandatory; 13103 -webkit-overflow-scrolling: touch; 13104 scrollbar-width: none; 13105 -ms-overflow-style: none; 13106 } 13107 .bp-cart-drawer__ctl-track::-webkit-scrollbar { display: none; }
13108 /* Scroll-progress indicator â ported from bp-product-carousel's 13109 .bp-pc__indicator (same thin bar + moving thumb). */ 13110 .bp-cart-drawer__ctl-indicator { 13111 margin-top: 12px; 13112 height: 3px; 13113 background: rgba(23, 22, 9, 0.12); 13114 position: relative; 13115 overflow: hidden; 13116 } 13117 .bp-cart-drawer__ctl-indicator::after { 13118 content: ''; 13119 position: absolute; 13120 top: 0; 13121 bottom: 0; 13122 left: calc(var(--bp-ctl-thumb-x, 0) * (100% - var(--bp-ctl-thumb-w, 100%))); 13123 width: var(--bp-ctl-thumb-w, 100%); 13124 background: var(--bp-color-text); 13125 transition: left 0.1s linear, width 0.1s linear; 13126 } 13127 .bp-cart-drawer__ctl-card { 13128 /* Fixed card width so cards don't stretch with the drawer/screen 13129 width (QA 7/23, Brooke): on wide screens a flex-fill basis made 13130 each card huge and the square cover image looked zoomed in. 13131 A fixed 175px basis keeps the card size constant and lets more 13132 cards fit per view as the drawer widens (2 on mobile â 3+ on 13133 desktop) instead of two ever-expanding cards. */ 13134 flex: 0 0 175px; 13135 max-width: 175px; 13136 min-width: 0; 13137 scroll-snap-align: start; 13138 position: relative; 13139 } 13140 .bp-cart-drawer__ctl-badge { 13141 position: absolute; 13142 top: 8px; 13143 left: 8px; 13144 z-index: 1; 13145 padding: 4px 8px; 13146 background: var(--bp-color-bg-cream); 13147 color: var(--bp-color-text); 13148 font-family: var(--bp-font-body); 13149 font-size: 11px; 13150 font-weight: 500; 13151 letter-spacing: 0.04em; 13152 } 13153 .bp-cart-drawer__ctl-image { 13154 aspect-ratio: 3 / 4; 13155 background: var(--bp-color-bg-cream); 13156 overflow: hidden; 13157 margin-bottom: 8px; 13158 } 13159 .bp-cart-drawer__ctl-image svg, 13160 .bp-cart-drawer__ctl-image img { 13161 width: 100%; 13162 height: 100%; 13163 object-fit: contain; 13164 display: block; 13165 } 13166 .bp-cart-drawer__ctl-name { 13167 margin: 0; 13168 font-family: var(--bp-font-body); 13169 font-size: 13px; 13170 color: var(--bp-color-text); 13171 } 13172 .bp-cart-drawer__ctl-price { 13173 margin: 4px 0 0; 13174 font-family: var(--bp-font-body); 13175 font-size: 13px; 13176 color: var(--bp-color-text); 13177 } 13178 .bp-cart-drawer__ctl-sale { color: var(--bp-color-promo); margin-right: 6px; } 13179 .bp-cart-drawer__ctl-compare { color: var(--bp-color-body-copy); text-decoration: line-through; } 13180 13181 /* Promo code input â hidden in the cart flyout per request (still 13182 available on the /cart page). */ 13183 .bp-cart-discount--drawer { display: none; } 13184 13185 /* Footer (sticky). */ 13186 .bp-cart-drawer__foot { 13187 flex: 0 0 auto; 13188 background: var(--bp-color-bg-page); 13189 /* Horizontal padding must match .bp-cart-drawer__body/__header (24px) so 13190 the subtotal + checkout buttons line up with the product images/titles 13191 above (QA 7/27 â footer was 16px, 8px left of the body edge, Figma 13192 has them flush). */ 13193 padding: 12px 24px 16px; 13194 border-top: 1px solid rgba(23, 22, 9, 0.08); 13195 display: flex; 13196 flex-direction: column; 13197 gap: 6px; 13198 } 13199 .bp-cart-drawer__subtotal { 13200 display: flex; 13201 justify-content: space-between; 13202 align-items: baseline; 13203 } 13204 .bp-cart-drawer__subtotal-label { 13205 /* Heading / H5 (was H4/24px) */ 13206 font-family: var(--bp-font-display); 13207 font-size: 20px; 13208 font-style: normal; 13209 font-weight: 300; 13210 line-height: 120%; 13211 letter-spacing: -0.48px; 13212 color: var(--bp-color-text); 13213 } 13214 .bp-cart-drawer__subtotal-value { 13215 /* Body / Regular / Medium */ 13216 font-family: var(--bp-font-body); 13217 font-size: 17px; 13218 font-style: normal; 13219 font-weight: 500; 13220 line-height: 145%; 13221 letter-spacing: -0.17px; 13222 color: var(--bp-color-text); 13223 text-align: right; 13224 } 13225 13226 /* Narvar mount slots. The footer's own flex `gap` already reserves 13227 even spacing around the widget whether it's empty or populated, so 13228 no margin here â an earlier `:not(:empty)` margin stacked on top of 13229 that gap once Narvar injected, doubling the space AND causing the 13230 surrounding rows to visibly jump apart as it populated (the opposite 13231 of the intended effect). The injected widget owns its own internal 13232 styling. */ 13233 .bp-cart-drawer__narvar-widget, 13234 .bp-cart-drawer__narvar-buttons { width: 100%; } 13235 .bp-cart-drawer__narvar-buttons:not(:empty) { margin-top: 12px; } 13236 .bp-cart-drawer__protection { 13237 background: var(--bp-color-bg-cream); 13238 padding: 14px 16px; 13239 cursor: pointer; 13240 display: block; 13241 } 13242 .bp-cart-drawer__protection-toggle { 13243 position: absolute; 13244 opacity: 0; 13245 pointer-events: none; 13246 } 13247 .bp-cart-drawer__protection-row { 13248 display: flex; 13249 justify-content: space-between; 13250 align-items: baseline; 13251 gap: 8px; 13252 } 13253 .bp-cart-drawer__protection-label { 13254 /* Heading / H6 */ 13255 font-family: var(--bp-font-display); 13256 font-size: 14px; 13257 font-weight: 300; 13258 line-height: 120%; 13259 letter-spacing: -0.28px; 13260 color: var(--bp-color-text); 13261 display: inline-flex; 13262 align-items: center; 13263 gap: 6px; 13264 } 13265 .bp-cart-drawer__protection-info { 13266 display: inline-flex; 13267 align-items: center; 13268 color: var(--bp-color-text); 13269 transform: translateY(1px); 13270 }
13271 .bp-cart-drawer__protection-price { 13272 /* Body / Book / Small */ 13273 font-family: var(--bp-font-body); 13274 font-size: 14px; 13275 font-weight: 400; 13276 line-height: 145%; 13277 letter-spacing: -0.14px; 13278 color: var(--bp-color-text); 13279 text-align: right; 13280 flex: 0 0 auto; 13281 } 13282 .bp-cart-drawer__protection-help { 13283 /* Body / Book / Tiny */ 13284 display: block; 13285 margin-top: 4px; 13286 font-family: var(--bp-font-body); 13287 font-size: 10px; 13288 font-weight: 400; 13289 line-height: 145%; 13290 letter-spacing: -0.1px; 13291 color: var(--bp-color-text); 13292 } 13293 13294 .bp-cart-drawer__taxes { 13295 /* Body / XSmall / Book */ 13296 margin: 0; 13297 font-family: var(--bp-font-body); 13298 font-size: 12px; 13299 font-weight: 400; 13300 line-height: 145%; 13301 letter-spacing: -0.12px; 13302 color: var(--bp-color-text); 13303 } 13304 13305 .bp-cart-drawer__form { margin: 0; } 13306 .bp-cart-drawer__btn { 13307 /* CTA / CTA Regular */ 13308 width: 100%; 13309 height: 52px; 13310 padding: 0 24px; 13311 border: 1px solid var(--bp-color-text); 13312 cursor: pointer; 13313 font-family: var(--bp-font-body); 13314 font-size: 17px; 13315 font-style: normal; 13316 font-weight: 500; 13317 line-height: normal; 13318 letter-spacing: -0.17px; 13319 leading-trim: both; 13320 text-edge: cap; 13321 transition: opacity 0.2s ease; 13322 } 13323 .bp-cart-drawer__btn--primary { 13324 background: var(--bp-color-text); 13325 color: var(--bp-color-cta-text); 13326 } 13327 .bp-cart-drawer__btn--primary:hover { opacity: 0.85; } 13328 /* Disabled checkout (empty / $0 subtotal): dimmed + non-interactive. */ 13329 .bp-cart-drawer__btn--disabled, 13330 .bp-cart-drawer__btn--disabled:hover { 13331 opacity: 0.45; 13332 pointer-events: none; 13333 cursor: not-allowed; 13334 } 13335 .bp-cart-drawer__btn--secondary { 13336 background: var(--bp-color-bg-page); 13337 color: var(--bp-color-text); 13338 } 13339 .bp-cart-drawer__btn--secondary:hover { background: var(--bp-color-bg-cream); } 13340 .bp-cart-drawer__view-bag { 13341 /* CTA / CTA Regular */ 13342 align-self: center; 13343 color: var(--bp-color-text); 13344 font-family: var(--bp-font-body); 13345 font-size: 14px; 13346 font-style: normal; 13347 font-weight: 500; 13348 line-height: normal; 13349 letter-spacing: -0.17px; 13350 leading-trim: both; 13351 text-edge: cap; 13352 text-decoration: underline; 13353 text-underline-offset: 3px; 13354 background: transparent; 13355 border: 0; 13356 padding: 0; 13357 cursor: pointer; 13358 } 13359 13360 @keyframes bpDrawerSlideIn { 13361 from { transform: translateX(100%); } 13362 to { transform: translateX(0); } 13363 } 13364 @keyframes bpDrawerSlideOut { 13365 from { transform: translateX(0); } 13366 to { transform: translateX(100%); } 13367 } 13368</style> 13369
13370<script type="module"> 13371 // --------------------------------------------------------------------------- 13372 // Narvar shipping-protection config (QA 7/22). Narvar's order-sync app embed 13373 // (shopify-app-block, block id 16157100011046449464) emits window.NarvarDPData 13374 // globally, resolving the delivery-protection product via all_products[handle]. 13375 // That hits Shopify's 20-UNIQUE-HANDLE all_products cap on product-heavy pages 13376 // (home/PLP render 20+ cards before the end-of-body embed runs), so its 13377 // variant_id/metafield come out BLANK there â `variant_id: ,` SyntaxError â 13378 // window.NarvarDPData never assigned â widget never renders. PDP/cart resolve 13379 // fewer handles, so Narvar's lookup succeeds there. (A Liquid source here fails 13380 // the SAME cap â confirmed â so these are hardcoded store constants instead.) 13381 // 13382 // ensureNarvarData() patches these into Narvar's OWN broken script on drawer 13383 // open and re-executes it, reusing Narvar's real cart_attributes + per-theme 13384 // settings verbatim. Narvar's own values win when present (the repair no-ops 13385 // when window.NarvarDPData is already set, e.g. PDP/cart). 13386 // 13387 // TODO (long-term): Narvar should source its DP variant/metafield from a shop 13388 // metafield / fixed variant ref (cap-proof), not all_products â then this can 13389 // be removed. If the DP product is ever recreated, update BP_NARVAR_DP_VARIANT 13390 // (or swap to a client-side fetch('/products/narvardeliveryprotection.js')). 13391 const BP_NARVAR_DP_VARIANT = 46514716934310; // narvardeliveryprotection variant 13392 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"}}; 13393 // Narvar's own code does `JSON.parse(metafield)`, so it must be the JSON STRING. 13394 const BP_NARVAR_DP_METAFIELD = JSON.stringify(BP_NARVAR_DP_META_RAW); 13395 13396 // Patch Narvar's blank config on home/PLP (see the full rationale on 13397 // BpCartDrawer.ensureNarvarData). Match Narvar's ASSIGNMENT script (not our 13398 // own references to the global â ours renders earlier and would self-match),
13399 // fill the blank variant_id/metafield, and re-execute so window.NarvarDPData 13400 // is set. Returns true if the global is now defined. No-op on PDP/cart, where 13401 // Narvar populates it itself. 13402 function bpEnsureNarvarData() { 13403 if (window.NarvarDPData) return true; 13404 const scripts = document.querySelectorAll('script:not([src])'); 13405 for (let i = 0; i < scripts.length; i++) { 13406 const txt = scripts[i].textContent || ''; 13407 if (!/window\.NarvarDPData\s*=\s*\{/.test(txt)) continue; // Narvar's assignment only 13408 if (!/variant_id:\s*,/.test(txt)) break; // already populated â nothing to fix 13409 try { 13410 const fixed = txt 13411 .replace(/variant_id:\s*,/, 'variant_id: ' + String(BP_NARVAR_DP_VARIANT) + ',') 13412 // metafield must be the JSON STRING Narvar's `JSON.parse` expects. 13413 .replace(/metafield:\s*JSON\.stringify\(\s*\)/, 'metafield: ' + JSON.stringify(BP_NARVAR_DP_METAFIELD)); 13414 // eslint-disable-next-line no-new-func 13415 new Function(fixed)(); // runs in global scope; assigns window.NarvarDPData 13416 } catch (e) { /* leave undefined */ } 13417 break; 13418 } 13419 return !!window.NarvarDPData; 13420 } 13421 13422 // Run at MODULE LOAD. This module script (in the header) executes 13423 // after DOM parse but BEFORE Narvar's deferred widget bundle at end-of-body 13424 // (deferred scripts run in document order). So setting a valid
13425 // window.NarvarDPData here means Narvar's own bundle reads it and renders the 13426 // widget natively â no drawer-open trigger or narvarCartWidgetInit needed. 13427 // Narvar's inline config script (non-module, ran during parse) has already 13428 // executed by now, so its blank/broken output is present to patch. 13429 try { bpEnsureNarvarData(); } catch (e) { /* non-fatal */ } 13430 13431 // ----- Narvar checkout-CTA casing + whole-dollar price zeros ----- 13432 // Narvar's app injects its checkout buttons ("Checkout", "Checkout Without 13433 // Shipping Protection") with `text-transform: uppercase` (its own 13434 // custom_css). The BP stylesheet override (bp-fonts) couldn't reliably 13435 // out-rank it â load order / re-injection let Narvar's uppercase win, so 13436 // the CTAs read ALL CAPS instead of the "first letter cap" the design 13437 // calls for. Fix it inline with !important, which beats any stylesheet 13438 // rule, the moment each button appears. `capitalize` == "first letter cap" 13439 // and is safe for a title- or lower-cased source label. One observer here 13440 // covers BOTH surfaces: the drawer buttons (CartDrawer-*) and the cart 13441 // page buttons (CartPage-*), since this drawer renders on every page. 13442 // 13443 // Same observer also strips ".00" off whole-dollar prices Narvar renders 13444 // itself (site-wide convention â see bp-htwi's stripPriceZeros): the 13445 // checkout button label ("Checkout - $42.00" once Narvar swaps in the 13446 // protection total) and the Shipping Protection widget price. The 13447 // subtotal is handled differently â see the NARVAR_WIDGET_SELECTORS 13448 // comment below for why. 13449 (function () { 13450 if (window.__bpNarvarCtaCasingWired) return; 13451 window.__bpNarvarCtaCasingWired = true; 13452 var IDS = [ 13453 'CartDrawer-Checkout-DP-With', 'CartDrawer-Checkout-DP-Without', 13454 'CartPage-Checkout-DP-With', 'CartPage-Checkout-DP-Without' 13455 ]; 13456 // The Narvar Shipping Protection mount is a live third-party React app 13457 // that can re-render its internal DOM continuously (toggle state, 13458 // animations). A persistent subtree+characterData observer on it would 13459 // re-run a full text-node walk on every one of those internal 13460 // mutations too, which spirals into a tight synchronous loop and hangs 13461 // the tab â keep this one to a one-shot strip per page-wide childList 13462 // mutation instead (QA 7/27, first crash). 13463 // 13464 // The subtotal element (`.totals__subtotal-value`, Narvar's configured 13465 // `subtotal_selector`) is NOT stripped by this script at all anymore â 13466 // Narvar appears to actively watch + re-assert that exact selector, so 13467 // a characterData observer on it fought Narvar's own logic in an 13468 // infinite write/react loop and froze the tab too (QA 7/27, second 13469 // crash). Narvar now gets its OWN hidden decoy node to own; the visible 13470 // subtotal shoppers see is a separate span we fully control (see 13471 // bp-cart-drawer.liquid's subtotal markup / bp-cart-page.liquid's twin). 13472 var NARVAR_WIDGET_SELECTORS = ['#narvar-cart-drawer-dp-widget', '#narvar-cart-page-dp-widget']; 13473 // Text-node-only walk (mirrors bp-htwi's stripPriceZeros) so element 13474 // structure (icons, nested spans) is left untouched. Idempotent â a 13475 // stripped "$39" has no ".00" left to match. 13476 function stripDotZero(root) { 13477 if (!root) return; 13478 var walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT); 13479 var node; 13480 while ((node = walker.nextNode())) { 13481 if (node.nodeValue && node.nodeValue.indexOf('.00') !== -1) { 13482 node.nodeValue = node.nodeValue.replace(/(\d)\.00\b/g, '$1'); 13483 } 13484 } 13485 } 13486 // The page-wide observer below only watches childList/attributes, so it 13487 // catches an element FIRST APPEARING but not a later direct text-node 13488 // write to it. Give small static price elements (checkout buttons, 13489 // subtotal) their own characterData-watching observer so those later 13490 // writes get caught too. 13491 var watched = new WeakSet(); 13492 function watchPriceText(el) { 13493 if (!el) return; 13494 stripDotZero(el); 13495 if (watched.has(el)) return; 13496 watched.add(el);
13497 try { 13498 new MutationObserver(function () { stripDotZero(el); }) 13499 .observe(el, { childList: true, subtree: true, characterData: true }); 13500 } catch (e) { /* observer unsupported */ } 13501 } 13502 var scheduled = false; 13503 function fixCasing() { 13504 scheduled = false; 13505 for (var i = 0; i < IDS.length; i++) { 13506 var btn = document.getElementById(IDS[i]); 13507 if (!btn) continue; 13508 if (btn.style.textTransform !== 'capitalize') { 13509 btn.style.setProperty('text-transform', 'capitalize', 'important'); 13510 } 13511 watchPriceText(btn); 13512 } 13513 for (var k = 0; k < NARVAR_WIDGET_SELECTORS.length; k++) { 13514 stripDotZero(document.querySelector(NARVAR_WIDGET_SELECTORS[k])); 13515 } 13516 // Site convention: no ".00" on whole-dollar amounts (matches the drawer 13517 // subtotal's formatMoney + the Liquid `money | replace: '.00', ''`). 13518 // Narvar's #checkout-price span (subtotal + protection, shown on the 13519 // DP-With button now that #307 no longer hides it) renders "$40.00" â 13520 // strip the trailing .00 so it reads "$40" like the rest of the cart (QA 13521 // 7/27, Dragana). Guarded on a .00 match so our own edit doesn't loop the 13522 // observer. querySelectorAll (not getElementById) in case Narvar reuses 13523 // the id across the flyout + cart-page buttons. 13524 var priceEls = document.querySelectorAll('[id="checkout-price"]'); 13525 for (var k = 0; k < priceEls.length; k++) { 13526 var txt = priceEls[k].textContent; 13527 if (txt && /\.00(\D|$)/.test(txt)) { 13528 priceEls[k].textContent = txt.replace(/\.00(\D|$)/g, '$1'); 13529 } 13530 } 13531 } 13532 function schedule() { 13533 if (scheduled) return; 13534 scheduled = true; 13535 requestAnimationFrame(fixCasing); 13536 } 13537 // Narvar injects/mutates these buttons asynchronously (on load for the 13538 // cart page, on drawer open for the drawer), so watch for it. `style` 13539 // is intentionally NOT in attributeFilter â our own inline set would 13540 // re-trigger this page-wide pass (the per-element observers above cover 13541 // the text-content case that needed characterData). 13542 try { 13543 new MutationObserver(schedule).observe(document.documentElement, { 13544 childList: true, subtree: true, attributes: true, attributeFilter: ['id', 'class'] 13545 }); 13546 } catch (e) { /* observer unsupported â the initial pass below still runs */ } 13547 fixCasing(); 13548 })(); 13549 13550 // ----- Shipping Protection loading skeleton (QA 7/27, Dragana) ----- 13551 // The SP widget is injected by Narvar's async bundle a few seconds after the 13552 // flyout opens / the cart page loads. A shimmer skeleton holds the box shape 13553 // until then (CSS `:has(.narvar-cart-widget-card)` hides it the instant the 13554 // real box renders). This JS is the belt-and-braces layer: it hides each 13555 // skeleton the moment its sibling mount gets a child (covers browsers without 13556 // `:has()`), and after a grace period hides any skeleton whose mount is still
13557 // empty â Narvar renders NO widget for ineligible carts (non-US / over the 13558 // max order value), and a lingering loading box would be misleading. Covers 13559 // both surfaces (this drawer renders on every page, incl. /cart). Supersedes 13560 // the earlier reserve-space approach (#307). 13561 (function () { 13562 if (window.__bpSpSkeletonWired) return; 13563 window.__bpSpSkeletonWired = true; 13564 function hide(skel) { if (skel) skel.classList.add('bp-sp-skeleton--hidden'); } 13565 function mountFor(skel) { 13566 // The Narvar mount is the skeleton's next element sibling. 13567 var el = skel.nextElementSibling; 13568 return (el && /narvar-cart-(drawer|page)-dp-widget/.test(el.id || '')) ? el : null; 13569 } 13570 var skels = document.querySelectorAll('[data-bp-sp-skeleton]'); 13571 for (var i = 0; i < skels.length; i++) { 13572 (function (skel) { 13573 var mount = mountFor(skel); 13574 if (!mount) { hide(skel); return; } 13575 if (mount.firstChild) { hide(skel); return; } // already populated 13576 try { 13577 var mo = new MutationObserver(function () { 13578 if (mount.firstChild) { hide(skel); mo.disconnect(); } 13579 }); 13580 mo.observe(mount, { childList: true }); 13581 } catch (e) { /* no observer â the timeout below still resolves it */ } 13582 })(skels[i]); 13583 } 13584 // Grace period: drop any skeleton Narvar never filled (ineligible carts). 13585 window.setTimeout(function () { 13586 var s = document.querySelectorAll('[data-bp-sp-skeleton]'); 13587 for (var j = 0; j < s.length; j++) { 13588 var m = s[j].nextElementSibling; 13589 if (!m || !m.firstChild) hide(s[j]); 13590 } 13591 }, 6000); 13592 })(); 13593 13594 // ----- Line item delegation + cart mutation helper ----- 13595 // Registered once per page from the drawer (which always renders), 13596 // not from the line item snippet (which doesn't render when the cart 13597 // is empty, leaving the empty-cart-then-add path with no listeners). 13598 if (!window.__bpCartLineWired) { 13599 window.__bpCartLineWired = true; 13600 13601 document.addEventListener('click', async (e) => { 13602 const line = e.target.closest('[data-bp-cart-line]'); 13603 if (!line) return; 13604 const key = line.dataset.lineKey; 13605 13606 const stepBtn = e.target.closest('[data-bp-qty-step]'); 13607 const removeBtn = e.target.closest('[data-bp-remove]'); 13608 const saveBtn = e.target.closest('[data-bp-save]'); 13609 13610 if (stepBtn) { 13611 const input = line.querySelector('[data-bp-qty-input]'); 13612 const next = Math.max(1, (parseInt(input.value, 10) || 1) + parseInt(stepBtn.dataset.bpQtyStep, 10)); 13613 await window.bpCartChange(key, next); 13614 return; 13615 } 13616 if (removeBtn) { 13617 await window.bpCartChange(key, 0); 13618 return; 13619 } 13620 if (saveBtn) { 13621 // Atlas parity â route the save through window.handleSaveForLater 13622 // (bp-swym-helpers). That fn calls Swym's AddToSmartWishlist, 13623 // removes the line from cart, updates the customer-scoped 13624 // local mirror (`save-for-later-items`), and dispatches the 13625 // wishlist + cart events the drawer + saved-drawer listen to. 13626 try { 13627 const cart = await fetch('/cart.js', { cache: 'no-store', credentials: 'same-origin' }).then((r) => r.json()); 13628 const item = cart.items.find((i) => i.key === key); 13629 if (item) { 13630 const product = { 13631 product_id: item.product_id, 13632 id: item.product_id, 13633 handle: item.handle, 13634 variant_id: item.variant_id, 13635 variant_title: item.variant_title, 13636 variant_price: item.final_price, 13637 variant_compare_at_price: item.original_price, 13638 title: item.product_title, 13639 image: item.image, 13640 quantity: item.quantity, 13641 properties: item.properties, 13642 sku: item.sku, 13643 variant_sku: item.sku, 13644 line_key: item.key, 13645 tags: item.tags 13646 }; 13647 if (typeof window.handleSaveForLater === 'function') { 13648 await window.handleSaveForLater({ preventDefault: () => {} }, product); 13649 } else { 13650 // Fallback if bp-swym-helpers hasn't loaded yet â drop the 13651 // line and stash a minimal snapshot under the legacy key 13652 // so the next page load can migrate it. 13653 const saved = JSON.parse(localStorage.getItem('bp.saved_for_later') || '[]'); 13654 saved.unshift({ 13655 variantId: item.variant_id, productId: item.product_id, key: item.key, 13656 title: item.product_title, variantTitle: item.variant_title, 13657 image: item.image, price: item.final_price, url: item.url, 13658 quantity: item.quantity, properties: item.properties, savedAt: Date.now() 13659 }); 13660 localStorage.setItem('bp.saved_for_later', JSON.stringify(saved.slice(0, 50))); 13661 document.dispatchEvent(new CustomEvent('bp:saved:updated')); 13662 await window.bpCartChange(key, 0); 13663 } 13664 saveBtn.classList.add('is-saved'); 13665 } 13666 } catch (err) { console.error('[bp-cart] save-for-later failed', err); } 13667 return; 13668 } 13669 }); 13670 13671 document.addEventListener('change', (e) => { 13672 const input = e.target.closest('[data-bp-qty-input]'); 13673 if (!input) return; 13674 const line = input.closest('[data-bp-cart-line]'); 13675 if (!line) return; 13676 const next = Math.max(1, parseInt(input.value, 10) || 1); 13677 window.bpCartChange(line.dataset.lineKey, next); 13678 }); 13679 13680 // Cart mutation helper â POSTs to /cart/change.js, then dis
13680patches 13681 // `cart:updated` with the new cart in event.detail so the drawer 13682 // updates line items in place without a page reload. 13683 window.bpCartChange = async (key, quantity) => { 13684 try { 13685 const res = await fetch('/cart/change.js', { 13686 method: 'POST', 13687 headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, 13688 body: JSON.stringify({ id: key, quantity }), 13689 cache: 'no-store', 13690 credentials: 'same-origin' 13691 }); 13692 if (!res.ok) throw new Error('HTTP ' + res.status); 13693 const cart = await res.json(); 13694 document.dispatchEvent(new CustomEvent('cart:updated', { detail: { cart } })); 13695 return cart; 13696 } catch (e) { console.error('[bp-cart] change failed', e); } 13697 }; 13698 } 13699 13700 if (!customElements.get('bp-cart-drawer')) { 13701 class BpCartDrawer extends HTMLElement { 13702 connectedCallback() { 13703 this.dialog = this.querySelector('[data-bp-cart-dialog]'); 13704 this.opener = this.querySelector('[data-bp-cart-open]'); 13705 if (!this.dialog || !this.opener) return; 13706 13707 this.opener.addEventListener('click', (e) => { 13708 e.preventDefault(); 13709 this.open(); 13710 }); 13711 13712 this.dialog.addEventListener('click', (e) => { 13713 if (e.target.closest('[data-bp-cart-close]')) { 13714 e.preventDefault(); 13715 this.close(); 13716 return; 13717 } 13718 // Narvar's Shipping Protection info icon opens an info surface that 13719 // would be clipped by the drawer â close the drawer on click so it 13720 // shows (Narvar's own handler still runs; we don't preventDefault). 13721 if (e.target.closest('.narvar-cart-widget-info-icon')) { 13722 this.close(); 13723 return; 13724 } 13725 if (e.target === this.dialog) this.close(); 13726 }); 13727 13728 this.dialog.addEventListener('cancel', (e) => { 13729 e.preventDefault(); 13730 this.close(); 13731 }); 13732 13733 // Complete-the-Look arrow nav â same pattern as bp-cart-page.liquid. 13734 // Track + buttons are server-rendered empty/present up front (see 13735 // markup above), so wiring at connect time is safe even though the 13736 // track itself is populated later by bp-cart-recommendations.liquid. 13737 const ctlTrack = this.querySelector('[data-bp-ctl-track]'); 13738 const ctlPrev = this.querySelector('[data-bp-ctl-prev]'); 13739 const ctlNext = this.querySelector('[data-bp-ctl-next]'); 13740 if (ctlTrack && ctlPrev && ctlNext) { 13741 const ctlStep = () => Math.max(160, ctlTrack.clientWidth / 4); 13742 ctlPrev.addEventListener('click', () => ctlTrack.scrollBy({ left: -ctlStep(), behavior: 'smooth' })); 13743 ctlNext.addEventListener('click', () => ctlTrack.scrollBy({ left: ctlStep(), behavior: 'smooth' })); 13744 } 13745 13746 // "Recommended for you" (empty-bag) arrow nav â same pattern. The rail is 13747 // a horizontal scroll track with no drag affordance on desktop, so the 13748 // arrows are the way to page through it (QA 8/05, Brooke). 13749 // "Recommended for you" (empty-bag) arrow nav â DELEGATED on the drawer 13750 // so it fires regardless of when the rail is rendered/re-rendered, and 13751 // can't be missed by a connect-time query. `scroll-snap-type: mandatory` 13752 // snaps a programmatic SMOOTH scroll straight back to 0, so we scroll 13753 // instantly (which lands + snaps cleanly) and page by ~2 whole cards so 13754 // the target sits on a snap point (QA 8/05, Brooke). 13755 this.addEventListener('click', (e) => { 13756 const t = e.target; 13757 const dir = (t.closest && t.closest('[data-bp-recs-next]')) ? 1 13758 : (t.closest && t.closest('[data-bp-recs-prev]')) ? -1 : 0; 13759 if (!dir) return; 13760 e.preventDefault(); 13761 const track = this.querySelector('.bp-cart-drawer__recs-track'); 13762 if (!track) return; 13763 const card = track.querySelector('.bp-cart-drawer__recs-card'); 13764 const pitch = card ? card.getBoundingClientRect().width + 12 : track.clientWidth * 0.42; 13765 track.scrollBy({ left: dir * Math.round(pitch) * 2 }); 13766 }); 13767 13768 // Listen for cart updates from anywhere (PDP add, quick-add, etc.). 13769 // BP-internal: `cart:updated` carries the cart in event.detail.cart.
13770 document.addEventListener('cart:updated', (e) => { 13771 if (e.detail && e.detail.cart) this.applyCart(e.detail.cart); 13772 else this.refresh(); 13773 }); 13774 document.addEventListener('product:added', (e) => { 13775 this.open(); 13776 if (e.detail && e.detail.cart) this.applyCart(e.detail.cart); 13777 else this.refresh(); 13778 }); 13779 // Horizon-native: `cart:update` is dispatched by product-form on PDP 13780 // adds, by quick-add, by upsells, etc. Cart object lives in 13781 // event.detail.resource. Open the drawer + sync state. 13782 document.addEventListener('cart:update', (e) => { 13783 const detail = e.detail || {}; 13784 if (detail.data && detail.data.didError) return; 13785 // Source may be 'product-form-component' (PDP), quick-add, or 13786 // cart-line edits. Auto-open only on add-to-cart-style sources. 13787 const source = detail.data && detail.data.source; 13788 const isAdd = source === 'product-form-component' || 13789 source === 'quick-add-component' || 13790 source === 'product-card-component'; 13791 if (isAdd) this.open(); 13792 if (detail.resource) this.applyCart(detail.resource); 13793 else this.refresh(); 13794 }); 13795 // Discount Kit (Helium) dispatches this when it adds/removes a 13796 // GWP line item in the cart. Mirror Atlas's CartFlyout behavior: 13797 // open the drawer so the customer sees the change, then refresh. 13798 document.addEventListener('discount_kit:cart_changed', () => { 13799 this.open(); 13800 this.refresh(); 13801 }); 13802 13803 // Bulletproofing (QA 7/16, Critical): never allow checkout when there 13804 // are no REAL products â only the Narvar shipping-protection add-on can 13805 // linger ($3 orphan). Capture phase so it beats Narvar's own submit 13806 // handler on the injected DP buttons (they share this form). Falls 13807 // through to a full refresh, which clears any orphaned DP line. 13808 const checkoutForm = this.querySelector('#CartDrawer-Form'); 13809 if (checkoutForm) { 13810 checkoutForm.addEventListener('submit', (e) => { 13811 if (this._realCount === 0) { 13812 e.preventDefault(); 13813 e.stopImmediatePropagation(); 13814 this.#showEmptyUI(); 13815 this.refresh(); 13816 } 13817 }, { capture: true }); 13818 } 13819 13820 // Bundle upsell ("Complete the look") is rendered by the shared global 13821 // helper (snippets/bp-cart-bundle-upsell.liquid â window.bpBundleUpsell), 13822 // which self-wires off bp:cart-drawer:opened / bp:cart-lines:rendered / 13823 // cart:updated â no per-surface code here. 13824 // 13825 // Narvar config repair is intentionally NOT run at page load. Doing so 13826 // (and proactively calling narvarCartWidgetInit) double-fired Narvar's 13827 // own auto-init on the PDP and broke its render there. The repair runs 13828 // on drawer open instead (remountNarvar â ensureNarvarData), which is 13829 // the only place the drawer widget is actually needed and leaves 13830 // Narvar's page-load path untouched. 13831 } 13832 13833 open() { 13834 if (this.dialog.open) return; 13835 // Scroll suppression â freeze the page so the only scrollable area is 13836 // the cart body. `<html>` is not the scroller here and showModal() 13837 // alone doesn't stop the page behind the backdrop from scrolling, so 13838 // toggling html overflow did nothing. Pin the body in place at its 13839 // current offset (position:fixed) â the exact technique Horizon's 13840 // dialog.js uses. Restored + scroll position re-applied on close. 13841 const existingTop = document.body.style.top; 13842 const existingPosition = document.body.style.position; 13843 if (existingPosition === 'fixed' && existingTop) { 13844 this._lockScrollY = Math.abs(parseInt(existingTop, 10)) || 0; 13845 } else { 13846 this._lockScrollY = window.scrollY; 13847 } 13848 13849 document.body.style.width = '100%'; 13850 document.body.style.position = 'fixed'; 13851 document.body.style.top = `-${this._lockScrollY}px`;
13852 13853 if (typeof this.dialog.showModal === 'function') this.dialog.showModal(); 13854 else this.dialog.setAttribute('open', ''); 13855 // Notify the cart Complete-the-Look snippet (and anyone else 13856 // watching) that the drawer is now visible. The CTL snippet 13857 // re-syncs on this so cards appear the first time the drawer 13858 // opens, even when the cart was already populated server-side 13859 // and no cart mutation event has fired since. 13860 document.dispatchEvent(new CustomEvent('bp:cart-drawer:opened')); 13861 13862 // Narvar shipping-protection widget. Narvar's cart-widget script is 13863 // loaded on every page, but it only AUTO-renders on pages it detects as 13864 // a cart context (looks for `<cart-drawer>` + a `/cart` URL). Lana's 13865 // drawer is `<bp-cart-drawer>`, so on home / PLP the widget never 13866 // appeared. remountNarvar() calls Narvar's exposed init on open so it 13867 // renders into the drawer mount anywhere (QA 7/21). 13868 this.remountNarvar(); 13869 } 13870 13871 ensureNarvarData() { 13872 // ROOT CAUSE (QA 7/21): Narvar's app-embed injects an end-of-body 13873 // script that sets window.NarvarDPData with variant_id and metafield 13874 // printed from the Liquid `product` object plus a static settings block. 13875 // On non-product pages (home, PLP) `product` is nil, so it renders 13876 // `variant_id: ,` (a bare comma â SyntaxError that aborts the whole 13877 // script before the assignment) AND `metafield: JSON.stringify()` 13878 // (evaluates to undefined). window.NarvarDPData is left unset, so the 13879 // widget has no config and never renders. On PDP/cart both are populated 13880 // â valid JS â it works. That is the "PDP+cart yes, home+PLP no" split. 13881 // 13882 // Both blank values are STORE CONSTANTS â the narvardeliveryprotection 13883 // product's variant + its narvar.dp_config metafield (the InsureShield 13884 // config the widget needs for its title/description/premium). We source 13885 // them in Liquid (BP_NARVAR_DP_VARIANT / BP_NARVAR_DP_METAFIELD) and 13886 // patch them into Narvar's OWN broken script, then re-execute it so the 13887 // rest â Narvar's real cart_attributes + per-theme settings â is reused 13888 // verbatim (we can't recompute the cart_attributes quote/aid blob). 13889 // 13890 // Narvar's own values take precedence: this no-ops when NarvarDPData is 13891 // already set (PDP/cart), and the `variant_id: ,` guard skips any valid 13892 // (populated) script. Runs on drawer OPEN only â a load-time re-run that 13893 // also called narvarCartWidgetInit double-fired Narvar's auto-init on the 13894 // PDP and broke its render, so we leave Narvar's page-load path alone. 13895 // Delegates to the module-level bpEnsureNarvarData (already run once at 13896 // module load). Re-invoked on drawer open as a belt-and-suspenders in 13897 // case Narvar's config script landed after our load-time pass. 13898 return bpEnsureNarvarData(); 13899 } 13900 13901 remountNarvar() { 13902 // Narvar's cart-widget (React) observes the document and renders its 13903 // shipping-protection widget into #narvar-cart-drawer-dp-widget when it 13904 // detects the mount + a valid config. It auto-renders on the PDP + /cart 13905 // but not home/PLP â because window.NarvarDPData is unset there (see 13906 // ensureNarvarData). Repair the config first, then poll its exposed init 13907 // (window.narvarCartWidgetInit) so it renders into the (existing) drawer 13908 // mount on open, beating the async-load race ("open immediately = empty, 13909 // wait ~2s = loads"). 13910 // 13911 // NON-DESTRUCTIVE: do NOT remove/replace the mount. Removing it yanked 13912 // the node out from under Narvar mid-render and broke the PDP/cart cases 13913 // that already worked â leave the mount in place and only invoke init. 13914 this.ensureNarvarData(); 13915 const filled = () => { 13916 const w = this.querySelector('#narvar-cart-drawer-dp-widget'); 13917 return !w || w.children.length > 0; 13918 }; 13919 if (filled()) return; 13920 13921 let tries = 0; 13922 const MAX_TRIES = 24; // 24 Ã 250ms â 6s 13923 const tick = () => { 13924 if (filled() || !this.dialog.open) return; // done, or drawer closed 13925 if (typeof window.narvarCartWidgetInit === 'function') { 13926 try { window.narvarCartWidgetInit(); } catch (e) { /* keep retrying */ } 13927 } 13928 if (++tries < MAX_TRIES) setTimeout(tick, 250); 13929 }; 13930 requestAnimationFrame(tick); // start polling next frame 13931 } 13932 13933 close() { 13934 if (this._closing || !this.dialog.open) return; 13935 this._closing = true; 13936 this.dialog.classList.add('is-closing'); 13937 const onEnd = () => { 13938 this.dialog.classList.remove('is-closing'); 13939 this._closing = false;
13940 try { this.dialog.close(); } catch (_) { this.dialog.removeAttribute('open'); } 13941 // Release the body scroll lock and restore the pre-open scroll 13942 // position (position:fixed had reset it to 0 visually via top offset). 13943 document.body.style.width = ''; 13944 document.body.style.position = ''; 13945 document.body.style.top = ''; 13946 if (this._lockScrollY != null) { 13947 window.scrollTo({ top: this._lockScrollY, behavior: 'instant' }); 13948 this._lockScrollY = null; 13949 } 13950 }; 13951 this.dialog.addEventListener('animationend', onEnd, { once: true }); 13952 setTimeout(() => { if (this._closing) onEnd(); }, 350); 13953 } 13954 13955 async refresh() { 13956 try { 13957 const res = await fetch('/cart.js', { 13958 headers: { Accept: 'application/json' }, 13959 cache: 'no-store', 13960 credentials: 'same-origin' 13961 }); 13962 const cart = await res.json(); 13963 this.applyCart(cart); 13964 } catch (e) { console.error('[bp-cart-drawer] refresh failed', e); } 13965 } 13966 13967 applyCart(cart) { 13968 // The Narvar Shipping Protection line (SKU narvardeliveryprotection) 13969 // is an add-on, not a product the shopper chose â it must never count 13970 // toward the bag, and it must not keep the cart from reading as empty. 13971 const INSURANCE_SKU = 'narvardeliveryprotection'; 13972 const items = Array.isArray(cart.items) ? cart.items : []; 13973 const insuranceLine = items.find((i) => (i.sku || '').toLowerCase() === INSURANCE_SKU); 13974 const realCount = items.reduce( 13975 (n, i) => ((i.sku || '').toLowerCase() === INSURANCE_SKU ? n : n + i.quantity), 13976 0 13977 ); 13978 13979 // When every real product has been removed but the cart still carries 13980 // lines â the Narvar Shipping Protection add-on, which Narvar re-adds 13981 // while its toggle is on, so removing just that ONE line races the 13982 // re-add and it lingers with a $3 total you can still check out (QA 13983 // 7/16, Critical) â clear the WHOLE cart. /cart/clear drops every line 13984 // AND the cart attributes Narvar keys its toggle off, so the insurance 13985 // can't come back. Guarded so the resulting empty cart:updated doesn't 13986 // loop; return early so we never paint the transient "$3, no items" 13987 // state (which was also letting the checkout button show a price over 13988 // an empty bag). 13989 this._realCount = realCount; 13990 if (realCount === 0 && items.length > 0 && !this._clearingCart) { 13991 this._clearingCart = true; 13992 // Optimistically paint the empty state NOW. Without this the drawer 13993 // kept showing the stale items + footer + Narvar button/protection 13994 // during the async clear round-trip, so an "empty bag" could still 13995 // show "Checkout - $68" and a $3 protection line (QA 7/16, Critical). 13996 this.#showEmptyUI(); 13997 fetch('/cart/clear.js', { 13998 method: 'POST', 13999 headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, 14000 cache: 'no-store', 14001 credentials: 'same-origin' 14002 }) 14003 .then((r) => r.json()) 14004 .then((c) => document.dispatchEvent(new CustomEvent('cart:updated', { detail: { cart: c } }))) 14005 .catch((e) => console.error('[bp-cart-drawer] clear failed', e)) 14006 .finally(() => { this._clearingCart = false; }); 14007 return; 14008 } 14009 14010 // Count bubble + trigger count â reflect real products only. 14011 const bubble = this.querySelector('[data-bp-cart-bubble]'); 14012 const triggerCount = this.querySelector('[data-bp-cart-trigger-count]'); 14013 if (bubble) bubble.textContent = realCount; 14014 if (triggerCount) { 14015 triggerCount.textContent = realCount; 14016 triggerCount.toggleAttribute('hidden', realCount === 0); 14017 } 14018 // a11y: announce the new cart count via Horizon's existing status 14019 // live region (header-actions.liquid) â it was rendered but never 14020 // written to, so cart changes were silent to screen readers. 14021 try { 14022 const live = document.querySelector('[data-testid="cart-count-live-region"]'); 14023 // Only announce on an actual change â the first applyCart() primes 14024 // _bpLastCount silently so a page-load / drawer-open render with no 14025 // change doesn't speak the count. 14026 if (live && this._bpLastCount !== undefined && realCount !== this._bpLastCount) { 14027 live.textContent = realCount === 1
14028 ? '1 item in your bag' 14029 : realCount + ' items in your bag'; 14030 } 14031 this._bpLastCount = realCount; 14032 } catch (_) { /* non-fatal */ } 14033 // Subtotal = merchandise only. cart.total_price INCLUDES the Narvar 14034 // Shipping Protection line (SKU narvardeliveryprotection); once Narvar 14035 // adds that line (e.g. after the checkout round-trip) total_price jumps 14036 // to products+protection while the rows still show products only, so 14037 // the Subtotal read as a "lie" ($372.42 instead of $360, QA 8/04, 14038 // Dragana). Sum the non-protection lines â same formula as the Liquid 14039 // render + the visible row prices; protection stays in its own box. 14040 const bpMerchSubtotal = cart.items.reduce( 14041 (sum, i) => ((i.sku || '').toLowerCase() === 'narvardeliveryprotection' ? sum : sum + i.final_line_price), 14042 0 14043 ); 14044 const subtotal = this.querySelector('[data-bp-cart-subtotal]'); 14045 if (subtotal) subtotal.textContent = this.formatMoney(bpMerchSubtotal); 14046 14047 // Disable checkout when there's nothing to pay for ($0 subtotal). Covers 14048 // the primary Checkout button plus any Narvar-injected DP checkout 14049 // buttons that share the form, so a $0 bag can never start checkout. 14050 const noSubtotal = !(bpMerchSubtotal > 0); 14051 this.querySelectorAll( 14052 '.bp-cart-drawer__btn--primary, #CartDrawer-Form [name="checkout"], #narvar-cart-drawer-dp-buttons button, #narvar-cart-drawer-dp-buttons a' 14053 ).forEach((btn) => { 14054 if ('disabled' in btn) btn.disabled = noSubtotal; 14055 btn.toggleAttribute('aria-disabled', noSubtotal); 14056 btn.classList.toggle('bp-cart-drawer__btn--disabled', noSubtotal); 14057 }); 14058 14059 // Per-line updates: walk every existing line and either update qty/price 14060 // in place or remove it if its product is genuinely gone. 14061 // 14062 // Match by line key first, then fall back to VARIANT id. The server- 14063 // rendered `data-line-key` () doesn't always byte-match the 14064 // AJAX cart's `item.key`; when it didn't, the line was treated as "gone" 14065 // â it faded out and syncItemsList re-added it, so a simple qty step made 14066 // the row disappear and reappear. Matching by variant keeps the row and 14067 // updates it in place (and re-syncs its key so later updates match 14068 // exactly). existingKeys tracks the RESOLVED cart keys so hasNewItems 14069 // below can't false-positive off the same mismatch and re-render. 14070 const byKey = new Map(cart.items.map((i) => [i.key, i])); 14071 const byVariant = new Map(); 14072 cart.items.forEach((i) => { 14073 const arr = byVariant.get(i.variant_id) || []; 14074 arr.push(i); 14075 byVariant.set(i.variant_id, arr); 14076 }); 14077 const existingKeys = new Set(); 14078 this.querySelectorAll('[data-bp-cart-line]').forEach((line) => { 14079 let item = byKey.get(line.dataset.lineKey); 14080 if (!item) { 14081 const vid = parseInt(line.dataset.variant, 10); 14082 const bucket = byVariant.get(vid); 14083 if (bucket && bucket.length) { 14084 item = bucket.shift(); // consume one line of this variant 14085 line.dataset.lineKey = item.key; // re-sync so future updates key-match 14086 } 14087 } 14088 if (!item) { 14089 line.style.transition = 'opacity 0.2s ease, transform 0.2s ease'; 14090 line.style.opacity = '0'; 14091 line.style.transform = 'translateX(8px)'; 14092 setTimeout(() => line.remove(), 220); 14093 return; 14094 } 14095 existingKeys.add(item.key); 14096 const qty = line.querySelector('[data-bp-qty-input]'); 14097 if (qty && qty.value !== String(item.quantity)) qty.value = item.quantity; 14098 const price = line.querySelector('[data-bp-line-price]'); 14099 if (price) price.textContent = this.formatMoney(item.final_line_price); 14100 // Original price â struck through, shown only while a discount 14101 // (promo code, etc.) actually lowers the line. Mirrors the 14102 // Liquid render's hidden-by-default state (bp-cart-line-item.liquid) 14103 // so applying/removing a code updates it live without a refetch. 14104 const compare = line.querySelector('[data-bp-line-compare]'); 14105 if (compare) { 14106 const hasDiscount = item.original_line_price > item.final_line_price; 14107 compare.hidden = !hasDiscount; 14108 if (hasDiscount) compare.textContent = this.formatMoney(item.original_line_price); 14109 } 14110 }); 14111 14112 // If any item in the cart doesn't have a row in the drawer yet 14113 // (e.g., PDP add introduced a new line), fetch a fresh render of 14114 // the header section and swap in the new items list HTML. 14115 // Exclude the insurance line â it never gets a drawer row, so counting 14116 // it here would trigger a needless re-render fetch on every cart update. 14117 const hasNewItems = items.some( 14118 (i) => (i.sku || '').toLowerCase() !== INSURANCE_SKU && !existingKeys.has(i.key) 14119 ); 14120 if (hasNewItems) this.syncItemsList(); 14121 14122 // Empty-state vs items-list + footer/CTL visibility. 14123 const itemsList = this.querySelector('[data-bp-cart-items]'); 14124 const emptyState = this.querySelector('[data-bp-cart-empty]'); 14125 const foot = this.querySelector('.bp-cart-drawer__foot'); 14126 const ctl = this.querySelector('[data-bp-ctl]'); 14127 const isEmpty = realCount === 0; 14128 if (itemsList) itemsList.toggleAttribute('hidden', isEmpty); 14129 if (emptyState) emptyState.toggleAttribute('hidden', !isEmpty); 14130 if (foot) foot.toggleAttribute('hidden', isEmpty); 14131 if (ctl) ctl.toggleAttribute('hidden', isEmpty); 14132 14133 // Bundle upsell ("Complete the look") is owned by the shared global 14134 // helper window.bpBundleUpsell (snippets/bp-cart-bundle-upsell.liquid), 14135 // which self-renders off cart:updated / bp:cart-lines:rendered â nothing 14136 // needed here. 14137 } 14138 14139 // Force the drawer's empty presentation immediately. Used optimistically 14140 // while /cart/clear round-trips (so no stale items / Narvar checkout price 14141 // / $3 protection line flashes over an empty bag) and as the submit-guard 14142 // fallback. Zeroes counts + subtotal and hides the footer + CTL. 14143 #showEmptyUI() { 14144 this._realCount = 0; 14145 const bubble = this.querySelector('[data-bp-cart-bubble]'); 14146 const triggerCount = this.querySelector('[data-bp-cart-trigger-count]'); 14147 if (bubble) bubble.textContent = '0'; 14148 if (triggerCount) { triggerCount.textContent = '0'; triggerCount.setAttribute('hidden', ''); } 14149 const subtotal = this.querySelector('[data-bp-cart-subtotal]'); 14150 if (subtotal) subtotal.textContent = this.formatMoney(0); 14151 const itemsList = this.querySelector('[data-bp-cart-items]'); 14152 const emptyState = this.querySelector('[data-bp-cart-empty]'); 14153 const foot = this.querySelector('.bp-cart-drawer__foot'); 14154 const ctl = this.querySelector('[data-bp-ctl]'); 14155 if (itemsList) itemsList.setAttribute('hidden', ''); 14156 if (emptyState) emptyState.removeAttribute('hidden'); 14157 if (foot) foot.setAttribute('hidden', ''); 14158 if (ctl) ctl.setAttribute('hidden', ''); 14159 } 14160 14161 async syncItemsList() { 14162 try { 14163 let html = ''; 14164 14165 // 1. Try Shopify Section Rendering API. Faster + lighter when it works. 14166 // Walk every ancestor section wrapper and ask each one in parallel â 14167 // one of them is the section that renders the cart drawer. 14168 const sectionWrappers = []; 14169 let el = this.parentElement; 14170 while (el) { 14171 if (el.id && el.id.startsWith('shopify-section-')) sectionWrappers.push(el.i
14171d.replace(/^shopify-section-/, '')); 14172 el = el.parentElement; 14173 } 14174 14175 for (const sectionId of sectionWrappers) { 14176 try { 14177 const res = await fetch(`${window.location.pathname}?sections=${sectionId}`, { 14178 headers: { Accept: 'application/json' }, 14179 cache: 'no-store', 14180 credentials: 'same-origin' 14181 }); 14182 if (!res.ok) continue; 14183 const json = await res.json(); 14184 const candidate = json[sectionId]; 14185 if (candidate && candidate.includes('data-bp-cart-items')) { 14186 html = candidate; 14187 break; 14188 } 14189 } catch (_) { /* try next */ } 14190 } 14191 14192 // 2. Fallback: fetch the full page HTML and extract the drawer items. 14193 // Bigger payload but guaranteed to include the drawer markup. 14194 if (!html) { 14195 const res = await fetch(window.location.pathname, { 14196 cache: 'no-store', 14197 credentials: 'same-origin' 14198 }); 14199 if (!res.ok) return; 14200 html = await res.text(); 14201 } 14202 14203 const doc = new DOMParser().parseFromString(html, 'text/html'); 14204 const freshList = doc.querySelector('[data-bp-cart-items]'); 14205 const currentList = this.querySelector('[data-bp-cart-items]'); 14206 if (freshList && currentList) { 14207 currentList.innerHTML = freshList.innerHTML; 14208 currentList.hidden = false; 14209 // The cart lines are the only place bp_style exists on the 14210 // client (/cart.js carries no metafields), and `cart:updated` 14211 // fires the moment /cart/change.js returns â well before this 14212 // section fetch lands. Anything that reads [data-bp-style] 14213 // (Complete the Look's in-bag exclusion) would otherwise be 14214 // looking at the PRE-mutation lines and miss the item just 14215 // added. Announce that the lines are actually in the DOM. 14216 document.dispatchEvent(new CustomEvent('bp:cart-lines:rendered')); 14217 } 14218 } catch (e) { console.error('[bp-cart-drawer] syncItemsList failed', e); } 14219 } 14220 14221 formatMoney(cents) { 14222 // Drop the .00 on whole-dollar prices (site-wide convention). Intl 14223 // adds the thousands separator so a JS-updated total matches the 14224 // Liquid `money | replace: '.00', ''` render (QA 7/24). 14225 return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }) 14226 .format(cents / 100).replace(/\.00$/, ''); 14227 } 14228 } 14229 customElements.define('bp-cart-drawer', BpCartDrawer); 14230 } 14231</script>
14231 14232 14233 14234 14235 <span 14236 ref="liveRegion" 14237 class="visually-hidden" 14238 role="status" 14239 data-testid="cart-count-live-region" 14240 ></span> 14241</header-actions> 14242
14243<script 14244 type="module" 14245 src="//www.bostonproper.com/cdn/shop/t/1516/assets/header-actions.js?v=121308165565653895611790192827" 14246 fetchpriority="low" 14247></script>
14247 14248 14249 14250 14251 14252 14253 14254 </div> 14255 </div> 14256 </div> 14257 14258 14259 14260 14261 14262 14263 14264 14265 14266 14267 14268 <div class="header__row header__navigation-bar-row color-scheme-1"> 14269 14270 14271 14272 14273 14274 14275<style data-shopify> 14276 .header__underlay { 14277 --color-submenu: rgb(254 255 250 / 1.0); 14278 } 14279</style> 14280 14281 14282 14283 14284 </div> 14285 14286</header-component> 14287
14288<script 14289 src="//www.bostonproper.com/cdn/shop/t/1516/assets/header.js?v=36718054510661947891790192827" 14290 type="module" 14291></script>
14291 14292 14293 14294 14295 14296
14296<script type="module"> 14297 import { hydrate } from '@theme/section-hydration'; 14298 const url = new URL(window.location.href); 14299 url.searchParams.delete('page'); 14300 hydrate('sections--29508264624294__header_section', url); 14301 </script>
14301 14302 14303 14304 14305</header> 14306<!-- END sections: header-group --> 14307 </div> 14308 14309
14309<script> 14310 // Inline header height and menu style calculations to prevent layout shift 14311 // Note: Updates in calculateHeaderGroupHeight(), updateTransparentHeaderOffset() and setHeaderMenuStyle() utilities.js should be kept in sync with this function 14312 (function setHeaderHeighCustomProperties() { 14313 /* 14314 * Header calculation functions for maintaining CSS variables 14315 * Mimic calculateHeaderGroupHeight() in utilities.js 14316 */ 14317 const header = document.querySelector('header-component'); 14318 const headerGroup = document.querySelector('#header-group'); 14319 const hasHeaderSection = headerGroup?.querySelector('.header-section'); 14320 14321 if (!header || !headerGroup) return; 14322 14323 const headerTopRow = header.querySelector('.header__row--top'); 14324 const headerHeight = header.offsetHeight; 14325 14326 // Calculate the total height of the header group 14327 let headerGroupHeight = 0; 14328 const children = headerGroup.children; 14329 for (let i = 0; i < children.length; i++) { 14330 const element = children[i]; 14331 if (element === header || !(element instanceof HTMLElement)) continue; 14332 headerGroupHeight += element.offsetHeight; 14333 } 14334 14335 // Check for transparent header special case 14336 if (header.hasAttribute('transparent') && header.parentElement?.nextElementSibling) { 14337 headerGroupHeight += headerHeight; 14338 } 14339 14340 // Set CSS variables 14341 document.body.style.setProperty('--header-height', `${headerHeight}px`); 14342 document.body.style.setProperty('--header-group-height', `${headerGroupHeight}px`); 14343 14344 if (headerTopRow) { 14345 window.requestAnimationFrame(function () { 14346 document.body.style.setProperty('--top-row-height', `${headerTopRow.offsetHeight}px`); 14347 }); 14348 } 14349 14350 /** 14351 * Updates CSS custom properties for transparent header offset calculation 14352 * Mimic updateTransparentHeaderOffset() in utilities.js 14353 */ 14354 14355 if (!hasHeaderSection || !header?.hasAttribute('transparent')) { 14356 document.body.style.setProperty('--transparent-header-offset-boolean', '0'); 14357 return; 14358 } 14359 14360 const hasImmediateSection = hasHeaderSection.nextElementSibling?.classList.contains('shopify-section'); 14361 14362 const shouldApplyOffset = !hasImmediateSection ? '1' : '0'; 14363 document.body.style.setProperty('--transparent-header-offset-boolean', shouldApplyOffset); 14364 })(); 14365 14366 (function setHeaderMenuStyle() { 14367 const headerComponent = document.querySelector('#header-component'); 14368 if (headerComponent) { 14369 const isTouchDevice = 'ontouchstart' in window && navigator.maxTouchPoints > 0; 14370 const overflowList = headerComponent?.querySelector('overflow-list'); 14371 const hasReachedMinimum = overflowList && overflowList.hasAttribute('minimum-reached'); 14372 headerComponent.dataset.menuStyle = isTouchDevice || hasReachedMinimum ? 'drawer' : 'menu'; 14373 } 14374 })(); 14375 14376 /* Boston Proper: force drawer mode below 1024px (mobile + tablet). 14377 Above 1024px we DO NOT force 'menu' â we let Horizon's overflow-list 14378 logic in setHeaderMenuStyle() (assets/utilities.js) decide. That logic 14379 flips to 'drawer' at intermediate desktop widths where menu items can't 14380 fit (e.g. the Shopify theme editor iframe at ~1500px), preventing the 14381 right-side action icons from being pushed off-screen. 14382 14383 The MutationObserver only re-asserts when we're below the breakpoint â 14384 so Horizon's debounced resize handler (header-menu.js:47-49) can switch 14385 the dataset freely on desktop, but can't undo our drawer mode on mobile. */ 14386 (function bpResponsiveMenuStyle() { 14387 const headerComponent = document.querySelector('#header-component'); 14388 if (!headerComponent) return; 14389 const mq = window.matchMedia('(min-width: 1024px)'); 14390 const isTouchDevice = 'ontouchstart' in window && navigator.maxTouchPoints > 0; 14391 function shouldForceDrawer() { 14392 return isTouchDevice || !mq.matches; 14393 } 14394 function enforce() { 14395 if (!shouldForceDrawer()) return; // desktop: let Horizon decide 14396 if (headerComponent.dataset.menuStyle !== 'drawer') { 14397 headerComponent.dataset.menuStyle = 'drawer'; 14398 } 14399 } 14400 function onChange() { 14401 enforce(); 14402 if (!shouldForceDrawer()) { 14403 // Crossing up to desktop â let Horizon recompute now. 14404 window.dispatchEvent(new Event('resize')); 14405 } 14406 } 14407 if (mq.addEventListener) { 14408 mq.addEventListener('change', onChange); 14409 } else if (mq.addListener) { 14410 mq.addListener(onChange); 14411 } 14412 new MutationObserver(enforce).observe(headerComponent, { 14413 attributes: true, 14414 attributeFilter: ['data-menu-style'] 14415 }); 14416 enforce(); 14417 })(); 14418 14419 /* Boston Proper: compact-nav state machine. 14420 14421 Behavior (per design): the resting nav is IN FLOW and scrolls 14422 away with the page. Once it has fully scrolled out of view, a 14423 compact fixed bar takes over. Positioning + variant styles live 14424 in snippets/bp-fonts.liquid, keyed off data-bp-nav. 14425 14426 ââ Why this is not Horizon's data-sticky-state ââââââââââââââ 14427 Horizon's #observeStickyPosition writes data-sticky-state from 14428 an IntersectionObserver on the header itself. The compact 14429 variant changes the header's height AND its position, so keying 14430 it off that flag makes the styles perturb the geometry that 14431 produces the flag: observer writes -> header resizes/unpins -> 14432 observer re-fires -> writes the opposite -> the header strobes 14433 between variants mid-scroll. Measured 2026-07-14 in Chrome: at 14434 threshold: 1, isIntersecting is false at ratio 0.9888 and true 14435 at ratio 1, so Horizon's flag flips at exactly rect.top === 0 â 14436 the one offset where a header pinned at top: -1px hands off 14437 from in-flow to pinned, and precisely where the strobe showed. 14438 14439 This machine reads window.scrollY instead. Because 14440 .header-section reserves the resting height via 14441 --bp-header-rest-h even while the child is fixed, engaging the 14442 compact bar reflows nothing, so scrollY cannot be perturbed by 14443 the state it produces. The loop is broken at the source rather 14444 than damped. The dead band below is belt-and-braces for 14445 sub-pixel scroll noise at the threshold. 14446 14447 Horizon still writes data-sticky-state; it only drives opacity 14448 and view-transition-name now (sections/header.liquid:562-577), 14449 no geometry, so the two writers can't interact. */ 14450 (function bpCompactNav() { 14451 const header = document.querySelector('#header-component[sticky="always"]'); 14452 if (!header) return; 14453 const section = header.closest('.header-section'); 14454 if (!section) return; 14455 14456 const DEAD_BAND = 8; 14457 let restBottom = 0; 14458 let rafId = null; 14459 14460 /* The resting height is only measurable while the header is in 14461 its resting layout â when compact it is fixed and shrunken. 14462 Drop to rest, measure, restore. Runs on load + resize only, 14463 never per scroll frame, so the forced reflow is not on the 14464 hot path. */ 14465 function measure() { 14466 const wasCompact = header.dataset.bpNav === 'compact'; 14467 if (wasCompact) header.dataset.bpNav = 'rest'; 14468 14469 const restHeight = header.offsetHeight; 14470 section.style.setProperty('--bp-header-rest-h', restHeight + 'px'); 14471 /* Document-space bottom edge of the resting header. section is 14472 static and its reserved height never changes, so this is 14473 stable regardless of the current state. */ 14474 restBottom = section.getBoundingClientRect().top + window.scrollY + restHeight; 14475 14476 if (wasCompact) header.dataset.bpNav = 'compact'; 14477 } 14478
14479 function update() { 14480 rafId = null; 14481 const y = window.scrollY; 14482 const isCompact = header.dataset.bpNav === 'compact'; 14483 if (!isCompact && y >= restBottom) { 14484 header.dataset.bpNav = 'compact'; 14485 } else if (isCompact && y < restBottom - DEAD_BAND) { 14486 header.dataset.bpNav = 'rest'; 14487 } 14488 } 14489 14490 function onScroll() { 14491 if (rafId !== null) return; 14492 rafId = window.requestAnimationFrame(update); 14493 } 14494 14495 function onResize() { 14496 measure(); 14497 onScroll(); 14498 } 14499 14500 document.addEventListener('scroll', onScroll, { passive: true }); 14501 window.addEventListener('resize', onResize, { passive: true }); 14502 14503 header.dataset.bpNav = 'rest'; 14504 measure(); 14505 update(); 14506 /* Fonts/images landing after first paint change the resting 14507 height; re-measure once the page has settled. */ 14508 window.addEventListener('load', onResize, { once: true }); 14509 })(); 14510 14511 /* Boston Proper: a11y patch for the third-party promo-bar iframe 14512 (id "PBarNextFrame*" â the free-gift/promo bar app embed, e.g. 14513 Discount Kit). The vendor injects this iframe client-side with 14514 no title/aria-label, which fails the axe "frame-title" rule. 14515 We don't control that markup, so we watch for the iframe and 14516 label it the moment it lands in the DOM (works whether it's 14517 already present, or the app mounts/remounts it later). */ 14518 (function bpLabelPromoBarFrame() { 14519 const SELECTOR = 'iframe[id^="PBarNextFrame"]'; 14520 14521 function label(frame) { 14522 if (!frame || frame.hasAttribute('title')) return; 14523 frame.setAttribute('title', 'Store promotion'); 14524 } 14525 14526 const existing = document.querySelector(SELECTOR); 14527 if (existing) label(existing); 14528 14529 new MutationObserver(function (mutations) { 14530 for (const mutation of mutations) { 14531 for (const node of mutation.addedNodes) { 14532 if (!(node instanceof Element)) continue; 14533 if (node.matches(SELECTOR)) { 14534 label(node); 14535 } else { 14536 const frame = node.querySelector && node.querySelector(SELECTOR); 14537 if (frame) label(frame); 14538 } 14539 } 14540 } 14541 }).observe(document.documentElement, { childList: true, subtree: true }); 14542 })(); 14543 </script>
14543 14544 14545 <main 14546 id="MainContent" 14547 class="content-for-layout" 14548 role="main" 14549 tabindex="-1" 14550 data-page-transition-enabled="false" 14551 data-product-transition="false" 14552 data-template="blog" 14553 > 14554 <div id="shopify-section-template--29508271177894__main" class="shopify-section"><bp-blog class="bp-blog" data-section-id="template--29508271177894__main"><section class="bp-blog__hero"> 14555 <div class="bp-blog__hero-head"> 14556 <h1 class="bp-blog__title">styleEDIT</h1> 14557 14558 <nav class="bp-blog__tags" aria-label="Blog tags"><a class="bp-blog__tag-link" href="/blogs/styleedit/tagged/how-to-wear-it" >How To Wear It</a><a class="bp-blog__tag-link" href="/blogs/styleedit/tagged/whats-trending" >What's Trending</a><a class="bp-blog__tag-link" href="/blogs/styleedit/tagged/women-we-admire" >Women We Admire</a><a class="bp-blog__tag-link bp-blog__tag-link--all" href="/blogs/styleedit" >Read All</a> 14559 </nav> 14560 </div><div class="bp-blog__feature" data-feature> 14561 <div class="bp-blog__feature-track" data-feature-track><article class="bp-blog__feature-slide is-active" data-feature-slide> 14562 <div class="bp-blog__feature-meta"><span class="bp-blog__feature-tag">HOW TO WEAR IT</span><h2 class="bp-blog__feature-title"> 14563 <a href="/blogs/styleedit/defy-all-expectations-why-style-doesn-t-expire-it-evolves">Defy All Expectations: Why Style Doesnât Expire. It Evolves.</a> 14564 </h2> 14565 <time class="bp-blog__feature-date" datetime="2026-09-03"> 14566 September 3, 2026 14567 </time> 14568 <a class="bp-blog__feature-cta" href="/blogs/styleedit/defy-all-expectations-why-style-doesn-t-expire-it-evolves">Read More</a> 14569 </div> 14570 14571 <a class="bp-blog__feature-image" href="/blogs/styleedit/defy-all-expectations-why-style-doesn-t-expire-it-evolves" tabindex="-1" aria-hidden="true"><img src="//www.bostonproper.com/cdn/shop/articles/blog_featured-img.jpg?v=1788466643&width=1200" alt="Defy All Expectations: Why Style Doesnât Expire. It Evolves." srcset="//www.bostonproper.com/cdn/shop/articles/blog_featured-img.jpg?v=1788466643&width=600 600w, //www.bostonproper.com/cdn/shop/articles/blog_featured-img.jpg?v=1788466643&width=900 900w, //www.bostonproper.com/cdn/shop/articles/blog_featured-img.jpg?v=1788466643&width=1200 1200w" width="1200" height="857" loading="lazy" sizes="(min-width: 1024px) 50vw, 100vw"> 14572</a> 14573</article> 14574 14575<article class="bp-blog__feature-slide is-active" data-feature-slide> 14576 <div class="bp-blog__feature-meta"><h2 class="bp-blog__feature-title"> 14577 <a href="/blogs/styleedit/fall-style-give-away">Dress to Defy Style Giveaway</a> 14578 </h2> 14579 <time class="bp-blog__feature-date" datetime="2026-08-28"> 14580 August 28, 2026 14581 </time> 14582 <a class="bp-blog__feature-cta" href="/blogs/styleedit/fall-style-give-away">Read More</a> 14583 </div> 14584 14585 <a class="bp-blog__feature-image" href="/blogs/styleedit/fall-style-give-away" tabindex="-1" aria-hidden="true"><img src="//www.bostonproper.com/cdn/shop/articles/Image_c207f908-196c-484c-9aad-16914d07df79.png?v=1787924889&width=1200" alt="Dress to Defy Style Giveaway" srcset="//www.bostonproper.com/cdn/shop/articles/Image_c207f908-196c-484c-9aad-16914d07df79.png?v=1787924889&width=600 600w, //www.bostonproper.com/cdn/shop/articles/Image_c207f908-196c-484c-9aad-16914d07df79.png?v=1787924889&width=900 900w, //www.bostonproper.com/cdn/shop/articles/Image_c207f908-196c-484c-9aad-16914d07df79.png?v=1787924889&width=1200 1200w" width="1200" height="800" loading="lazy" sizes="(min-width: 1024px) 50vw, 100vw"> 14586</a> 14587</article> 14588 14589<article class="bp-blog__feature-slide is-active" data-feature-slide> 14590 <div class="bp-blog__feature-meta"><span class="bp-blog__feature-tag">HOW TO WEAR IT</span><h2 class="bp-blog__feature-title"> 14591 <a href="/blogs/styleedit/confident-prints-florals-stripes-subtle-statements-that-own-every-room">Confident Prints: Florals, Stripes & Subtle Statements That Own Every Room</a> 14592 </h2> 14593 <time class="bp-blog__feature-date" datetime="2026-07-14"> 14594 July 14, 2026 14595 </time> 14596 <a class="bp-blog__feature-cta" href="/blogs/styleedit/confident-prints-florals-stripes-subtle-statements-that-own-every-room">Read More</a> 14597 </div> 14598 14599 <a class="bp-blog__feature-image" href="/blogs/styleedit/confident-prints-florals-stripes-subtle-statements-that-own-every-room" tabindex="-1" aria-hidden="true"><img src="//www.bostonproper.com/cdn/shop/articles/10408__featured-img_prints_508ea217-b586-44fa-baa1-d1f36ec7fc6c.jpg?v=1784047418&width=1200" alt="Confident Prints: Florals, Stripes & Subtle Statements That Own Every Room" srcset="//www.bostonproper.com/cdn/shop/articles/10408__featured-img_prints_508ea217-b586-44fa-baa1-d1f36ec7fc6c.jpg?v=1784047418&width=600 600w, //www.bostonproper.com/cdn/shop/articles/10408__featured-img_prints_508ea217-b586-44fa-baa1-d1f36ec7fc6c.jpg?v=1784047418&width=900 900w, //www.bostonproper.com/cdn/shop/articles/10408__featured-img_prints_508ea217-b586-44fa-baa1-d1f36ec7fc6c.jpg?v=1784047418&width=1200 1200w" width="1200" height="857" loading="lazy" sizes="(min-width: 1024px) 50vw, 100vw"> 14600</a> 14601</article> 14602 14603</div><button type="button" class="bp-blog__feature-arrow bp-blog__feature-arrow--prev" data-feature-prev aria-label="Previous featured post"> 14604 <svg width="14" height="20" viewBox="14 10 12 20" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> 14605 <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"/> 14606 <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"/> 14607 </svg> 14608 </button> 14609 <button type="button" class="bp-blog__feature-arrow bp-blog__feature-arrow--next" data-feature-next aria-label="Next featured post"> 14610 <svg width="14" height="20" viewBox="14 10 12 20" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> 14611 <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"/> 14612 <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"/> 14613 </svg> 14614 </button> 14615 14616 <div class="bp-blog__feature-progress" aria-hidden="true"> 14617 <div class="bp-blog__feature-progress-bar" data-feature-progress style="--progress: 33%;"></div> 14618 </div></div></section><section class="bp-blog__grid-wrap"><div class="bp-blog__grid"><article class="bp-blog__card"> 14619 <a class="bp-blog__card-image" href="/blogs/styleedit/defy-all-expectations-why-style-doesn-t-expire-it-evolves"><img src="//www.bostonproper.com/cdn/shop/articles/blog_featured-img.jpg?v=1788466643&width=800" alt="Defy All Expectations: Why Style Doesnât Expire. It Evolves." srcset="//www.bostonproper.com/cdn/shop/articles/blog_featured-img.jpg?v=1788466643&width=400 400w, //www.bostonproper.com/cdn/shop/articles/blog_featured-img.jpg?v=1788466643&width=600 600w, //www.bostonproper.com/cdn/shop/articles/blog_featured-img.jpg?v=1788466643&width=800 800w" width="800" height="571" loading="lazy" sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"> 14620</a> 14621 <div class="bp-blog__card-body"><span class="bp-blog__card-tag">HOW TO WEAR IT</span>
14621<h3 class="bp-blog__card-title"> 14622 <a href="/blogs/styleedit/defy-all-expectations-why-style-doesn-t-expire-it-evolves">Defy All Expectations: Why Style Doesnât Expire. It Evolves.</a> 14623 </h3> 14624 <p class="bp-blog__card-meta"><span class="bp-blog__card-author">Lauren Thomas</span> 14625 <span class="bp-blog__card-sep" aria-hidden="true">|</span><time datetime="2026-09-03"> 14626 Sep 3, 2026 14627 </time> 14628 </p> 14629 </div> 14630 </article><article class="bp-blog__card"> 14631 <a class="bp-blog__card-image" href="/blogs/styleedit/fall-style-give-away"><img src="//www.bostonproper.com/cdn/shop/articles/Image_c207f908-196c-484c-9aad-16914d07df79.png?v=1787924889&width=800" alt="Dress to Defy Style Giveaway" srcset="//www.bostonproper.com/cdn/shop/articles/Image_c207f908-196c-484c-9aad-16914d07df79.png?v=1787924889&width=400 400w, //www.bostonproper.com/cdn/shop/articles/Image_c207f908-196c-484c-9aad-16914d07df79.png?v=1787924889&width=600 600w, //www.bostonproper.com/cdn/shop/articles/Image_c207f908-196c-484c-9aad-16914d07df79.png?v=1787924889&width=800 800w" width="800" height="534" loading="lazy" sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"> 14632</a> 14633 <div class="bp-blog__card-body"><h3 class="bp-blog__card-title"> 14634 <a href="/blogs/styleedit/fall-style-give-away">Dress to Defy Style Giveaway</a> 14635 </h3> 14636 <p class="bp-blog__card-meta"><span class="bp-blog__card-author">Matt Verrecchia</span> 14637 <span class="bp-blog__card-sep" aria-hidden="true">|</span><time datetime="2026-08-28"> 14638 Aug 28, 2026 14639 </time> 14640 </p> 14641 </div> 14642 </article><article class="bp-blog__card"> 14643 <a class="bp-blog__card-image" href="/blogs/styleedit/confident-prints-florals-stripes-subtle-statements-that-own-every-room"><img src="//www.bostonproper.com/cdn/shop/articles/10408__featured-img_prints_508ea217-b586-44fa-baa1-d1f36ec7fc6c.jpg?v=1784047418&width=800" alt="Confident Prints: Florals, Stripes & Subtle Statements That Own Every Room" srcset="//www.bostonproper.com/cdn/shop/articles/10408__featured-img_prints_508ea217-b586-44fa-baa1-d1f36ec7fc6c.jpg?v=1784047418&width=400 400w, //www.bostonproper.com/cdn/shop/articles/10408__featured-img_prints_508ea217-b586-44fa-baa1-d1f36ec7fc6c.jpg?v=1784047418&width=600 600w, //www.bostonproper.com/cdn/shop/articles/10408__featured-img_prints_508ea217-b586-44fa-baa1-d1f36ec7fc6c.jpg?v=1784047418&width=800 800w" width="800" height="571" loading="lazy" sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"> 14644</a> 14645 <div class="bp-blog__card-body"><span class="bp-blog__card-tag">HOW TO WEAR IT</span><h3 class="bp-blog__card-title"> 14646 <a href="/blogs/styleedit/confident-prints-florals-stripes-subtle-statements-that-own-every-room">Confident Prints: Florals, Stripes & Subtle Statements That Own Every Room</a> 14647 </h3> 14648 <p class="bp-blog__card-meta"><span class="bp-blog__card-author">Lauren Thomas</span> 14649 <span class="bp-blog__card-sep" aria-hidden="true">|</span><time datetime="2026-07-14"> 14650 Jul 14, 2026 14651 </time> 14652 </p> 14653 </div> 14654 </article><article class="bp-blog__card"> 14655 <a class="bp-blog__card-image" href="/blogs/styleedit/court-to-cocktails-the-new-summer-dress-code"><img src="//www.bostonproper.com/cdn/shop/articles/10408__featured-img_pickleball_8f3b56fa-fdcc-47d0-9e6f-6ce65edb7f3f.jpg?v=1784041773&width=800" alt="Court to Cocktails: The New Summer Dress Code" srcset="//www.bostonproper.com/cdn/shop/articles/10408__featured-img_pickleball_8f3b56fa-fdcc-47d0-9e6f-6ce65edb7f3f.jpg?v=1784041773&width=400 400w, //www.bostonproper.com/cdn/shop/articles/10408__featured-img_pickleball_8f3b56fa-fdcc-47d0-9e6f-6ce65edb7f3f.jpg?v=1784041773&width=600 600w, //www.bostonproper.com/cdn/shop/articles/10408__featured-img_pickleball_8f3b56fa-fdcc-47d0-9e6f-6ce65edb7f3f.jpg?v=1784041773&width=800 800w" width="800" height="571" loading="lazy" sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"> 14656</a> 14657 <div class="bp-blog__card-body"><span class="bp-blog__card-tag">HOW TO WEAR IT</span>
14657<h3 class="bp-blog__card-title"> 14658 <a href="/blogs/styleedit/court-to-cocktails-the-new-summer-dress-code">Court to Cocktails: The New Summer Dress Code</a> 14659 </h3> 14660 <p class="bp-blog__card-meta"><span class="bp-blog__card-author">Lauren Thomas</span> 14661 <span class="bp-blog__card-sep" aria-hidden="true">|</span><time datetime="2026-07-14"> 14662 Jul 14, 2026 14663 </time> 14664 </p> 14665 </div> 14666 </article><article class="bp-blog__card"> 14667 <a class="bp-blog__card-image" href="/blogs/styleedit/the-details-defining-summer-fashion"><img src="//www.bostonproper.com/cdn/shop/articles/10408__featured-img_details-summer_611c2091-816c-4634-880e-3c91a0269665.jpg?v=1783629577&width=800" alt="The Details Defining Summer Fashion" srcset="//www.bostonproper.com/cdn/shop/articles/10408__featured-img_details-summer_611c2091-816c-4634-880e-3c91a0269665.jpg?v=1783629577&width=400 400w, //www.bostonproper.com/cdn/shop/articles/10408__featured-img_details-summer_611c2091-816c-4634-880e-3c91a0269665.jpg?v=1783629577&width=600 600w, //www.bostonproper.com/cdn/shop/articles/10408__featured-img_details-summer_611c2091-816c-4634-880e-3c91a0269665.jpg?v=1783629577&width=800 800w" width="800" height="571" loading="lazy" sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"> 14668</a> 14669 <div class="bp-blog__card-body"><span class="bp-blog__card-tag">HOW TO WEAR IT</span><h3 class="bp-blog__card-title"> 14670 <a href="/blogs/styleedit/the-details-defining-summer-fashion">The Details Defining Summer Fashion</a> 14671 </h3> 14672 <p class="bp-blog__card-meta"><span class="bp-blog__card-author">Lauren Thomas</span> 14673 <span class="bp-blog__card-sep" aria-hidden="true">|</span><time datetime="2026-07-09"> 14674 Jul 9, 2026 14675 </time> 14676 </p> 14677 </div> 14678 </article><article class="bp-blog__card"> 14679 <a class="bp-blog__card-image" href="/blogs/styleedit/denim-dresses-are-back-here-s-how-to-wear-them-now"><img src="//www.bostonproper.com/cdn/shop/articles/10408_featured-img_denim-dress_a1129fa2-9c70-4013-92a1-6070669a4e63.jpg?v=1783626977&width=800" alt="Denim Dresses Are Back. Hereâs How to Wear Them Now" srcset="//www.bostonproper.com/cdn/shop/articles/10408_featured-img_denim-dress_a1129fa2-9c70-4013-92a1-6070669a4e63.jpg?v=1783626977&width=400 400w, //www.bostonproper.com/cdn/shop/articles/10408_featured-img_denim-dress_a1129fa2-9c70-4013-92a1-6070669a4e63.jpg?v=1783626977&width=600 600w, //www.bostonproper.com/cdn/shop/articles/10408_featured-img_denim-dress_a1129fa2-9c70-4013-92a1-6070669a4e63.jpg?v=1783626977&width=800 800w" width="800" height="571" loading="lazy" sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"> 14680</a> 14681 <div class="bp-blog__card-body"><span class="bp-blog__card-tag">HOW TO WEAR IT</span><h3 class="bp-blog__card-title"> 14682 <a href="/blogs/styleedit/denim-dresses-are-back-here-s-how-to-wear-them-now">Denim Dresses Are Back. Hereâs How to Wear Them Now</a> 14683 </h3> 14684 <p class="bp-blog__card-meta"><span class="bp-blog__card-author">Lauren Thomas</span> 14685 <span class="bp-blog__card-sep" aria-hidden="true">|</span><time datetime="2026-07-09"> 14686 Jul 9, 2026 14687 </time> 14688 </p> 14689 </div> 14690 </article><article class="bp-blog__card"> 14691 <a class="bp-blog__card-image" href="/blogs/styleedit/what-to-wear-to-a-summer-wedding-outfits-by-venue"><img src="//www.bostonproper.com/cdn/shop/articles/10395__featured-img_wedding_c4fe87d5-8404-470d-9f4f-6bc11b765fbb.jpg?v=1780410849&width=800" alt="What to Wear to a Summer Wedding: Outfits by Venue" srcset="//www.bostonproper.com/cdn/shop/articles/10395__featured-img_wedding_c4fe87d5-8404-470d-9f4f-6bc11b765fbb.jpg?v=1780410849&width=400 400w, //www.bostonproper.com/cdn/shop/articles/10395__featured-img_wedding_c4fe87d5-8404-470d-9f4f-6bc11b765fbb.jpg?v=1780410849&width=600 600w, //www.bostonproper.com/cdn/shop/articles/10395__featured-img_wedding_c4fe87d5-8404-470d-9f4f-6bc11b765fbb.jpg?v=1780410849&width=800 800w" width="800" height="571" loading="lazy" sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"> 14692</a> 14693 <div class="bp-blog__card-body"><span class="bp-blog__card-tag">HOW TO WEAR IT</span>
14693<h3 class="bp-blog__card-title"> 14694 <a href="/blogs/styleedit/what-to-wear-to-a-summer-wedding-outfits-by-venue">What to Wear to a Summer Wedding: Outfits by Venue</a> 14695 </h3> 14696 <p class="bp-blog__card-meta"><span class="bp-blog__card-author">Lauren Thomas</span> 14697 <span class="bp-blog__card-sep" aria-hidden="true">|</span><time datetime="2026-06-02"> 14698 Jun 2, 2026 14699 </time> 14700 </p> 14701 </div> 14702 </article><article class="bp-blog__card"> 14703 <a class="bp-blog__card-image" href="/blogs/styleedit/best-travel-outfits-for-women-beyond-travel-pieces-that-do-more-than-travel"><img src="//www.bostonproper.com/cdn/shop/articles/10395__featured-img_travel.jpg?v=1780410114&width=800" alt="Best Travel Outfits for Women: Beyond Travel Pieces That Do More Than Travel" srcset="//www.bostonproper.com/cdn/shop/articles/10395__featured-img_travel.jpg?v=1780410114&width=400 400w, //www.bostonproper.com/cdn/shop/articles/10395__featured-img_travel.jpg?v=1780410114&width=600 600w, //www.bostonproper.com/cdn/shop/articles/10395__featured-img_travel.jpg?v=1780410114&width=800 800w" width="800" height="571" loading="lazy" sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"> 14704</a> 14705 <div class="bp-blog__card-body"><span class="bp-blog__card-tag">HOW TO WEAR IT</span><h3 class="bp-blog__card-title"> 14706 <a href="/blogs/styleedit/best-travel-outfits-for-women-beyond-travel-pieces-that-do-more-than-travel">Best Travel Outfits for Women: Beyond Travel Pieces That Do More Than Travel</a> 14707 </h3> 14708 <p class="bp-blog__card-meta"><span class="bp-blog__card-author">Lauren Thomas</span> 14709 <span class="bp-blog__card-sep" aria-hidden="true">|</span><time datetime="2026-06-02"> 14710 Jun 2, 2026 14711 </time> 14712 </p> 14713 </div> 14714 </article><article class="bp-blog__card"> 14715 <a class="bp-blog__card-image" href="/blogs/styleedit/white-neutrals-browns-the-new-power-palette"><img src="//www.bostonproper.com/cdn/shop/articles/10361_blog_neutrals_cover.jpg?v=1774896266&width=800" alt="White, Neutrals & Browns: The New Power Palette" srcset="//www.bostonproper.com/cdn/shop/articles/10361_blog_neutrals_cover.jpg?v=1774896266&width=400 400w, //www.bostonproper.com/cdn/shop/articles/10361_blog_neutrals_cover.jpg?v=1774896266&width=600 600w, //www.bostonproper.com/cdn/shop/articles/10361_blog_neutrals_cover.jpg?v=1774896266&width=800 800w" width="800" height="367" loading="lazy" sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"> 14716</a> 14717 <div class="bp-blog__card-body"><span class="bp-blog__card-tag">HOW TO WEAR IT</span><h3 class="bp-blog__card-title"> 14718 <a href="/blogs/styleedit/white-neutrals-browns-the-new-power-palette">White, Neutrals & Browns: The New Power Palette</a> 14719 </h3> 14720 <p class="bp-blog__card-meta"><span class="bp-blog__card-author">Lauren Thomas</span> 14721 <span class="bp-blog__card-sep" aria-hidden="true">|</span><time datetime="2026-03-30"> 14722 Mar 30, 2026 14723 </time> 14724 </p> 14725 </div> 14726 </article><article class="bp-blog__card"> 14727 <a class="bp-blog__card-image" href="/blogs/styleedit/how-to-wear-denim-on-denim"><img src="//www.bostonproper.com/cdn/shop/articles/10361_blog_denim_cover_26116560-ea46-4c93-9446-034fb50c1d19.jpg?v=1774896250&width=800" alt="How to Wear Denim on Denim" srcset="//www.bostonproper.com/cdn/shop/articles/10361_blog_denim_cover_26116560-ea46-4c93-9446-034fb50c1d19.jpg?v=1774896250&width=400 400w, //www.bostonproper.com/cdn/shop/articles/10361_blog_denim_cover_26116560-ea46-4c93-9446-034fb50c1d19.jpg?v=1774896250&width=600 600w, //www.bostonproper.com/cdn/shop/articles/10361_blog_denim_cover_26116560-ea46-4c93-9446-034fb50c1d19.jpg?v=1774896250&width=800 800w" width="800" height="367" loading="lazy" sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"> 14728</a> 14729 <div class="bp-blog__card-body"><span class="bp-blog__card-tag">HOW TO WEAR IT</span>
14729<h3 class="bp-blog__card-title"> 14730 <a href="/blogs/styleedit/how-to-wear-denim-on-denim">How to Wear Denim on Denim</a> 14731 </h3> 14732 <p class="bp-blog__card-meta"><span class="bp-blog__card-author">Lauren Thomas</span> 14733 <span class="bp-blog__card-sep" aria-hidden="true">|</span><time datetime="2026-03-30"> 14734 Mar 30, 2026 14735 </time> 14736 </p> 14737 </div> 14738 </article><article class="bp-blog__card"> 14739 <a class="bp-blog__card-image" href="/blogs/styleedit/swimwear-that-meets-you-where-you-are"><img src="//www.bostonproper.com/cdn/shop/articles/featured-img_spring-trans-swim_5d2d3e38-c17c-4f74-b985-a4bc0fb0a424.jpg?v=1770216176&width=800" alt="Swimwear That Meets You Where You Are" srcset="//www.bostonproper.com/cdn/shop/articles/featured-img_spring-trans-swim_5d2d3e38-c17c-4f74-b985-a4bc0fb0a424.jpg?v=1770216176&width=400 400w, //www.bostonproper.com/cdn/shop/articles/featured-img_spring-trans-swim_5d2d3e38-c17c-4f74-b985-a4bc0fb0a424.jpg?v=1770216176&width=600 600w, //www.bostonproper.com/cdn/shop/articles/featured-img_spring-trans-swim_5d2d3e38-c17c-4f74-b985-a4bc0fb0a424.jpg?v=1770216176&width=800 800w" width="800" height="571" loading="lazy" sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"> 14740</a> 14741 <div class="bp-blog__card-body"><span class="bp-blog__card-tag">HOW TO WEAR IT</span><h3 class="bp-blog__card-title"> 14742 <a href="/blogs/styleedit/swimwear-that-meets-you-where-you-are">Swimwear That Meets You Where You Are</a> 14743 </h3> 14744 <p class="bp-blog__card-meta"><span class="bp-blog__card-author">Brooke Creteau</span> 14745 <span class="bp-blog__card-sep" aria-hidden="true">|</span><time datetime="2026-02-04"> 14746 Feb 4, 2026 14747 </time> 14748 </p> 14749 </div> 14750 </article><article class="bp-blog__card"> 14751 <a class="bp-blog__card-image" href="/blogs/styleedit/proper-women-strength-style-and-holli-kenley"><img src="//www.bostonproper.com/cdn/shop/articles/featured-img_holli_5132bf4c-8993-4aa3-8281-a0cae35c538d.jpg?v=1768510696&width=800" alt="Proper Women: Strength, Style, and Holli Kenley" srcset="//www.bostonproper.com/cdn/shop/articles/featured-img_holli_5132bf4c-8993-4aa3-8281-a0cae35c538d.jpg?v=1768510696&width=400 400w, //www.bostonproper.com/cdn/shop/articles/featured-img_holli_5132bf4c-8993-4aa3-8281-a0cae35c538d.jpg?v=1768510696&width=600 600w, //www.bostonproper.com/cdn/shop/articles/featured-img_holli_5132bf4c-8993-4aa3-8281-a0cae35c538d.jpg?v=1768510696&width=800 800w" width="800" height="571" loading="lazy" sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"> 14752</a> 14753 <div class="bp-blog__card-body"><span class="bp-blog__card-tag">WOMEN WE ADMIRE</span><h3 class="bp-blog__card-title"> 14754 <a href="/blogs/styleedit/proper-women-strength-style-and-holli-kenley">Proper Women: Strength, Style, and Holli Kenley</a> 14755 </h3> 14756 <p class="bp-blog__card-meta"><span class="bp-blog__card-author">Lauren Thomas</span> 14757 <span class="bp-blog__card-sep" aria-hidden="true">|</span><time datetime="2026-01-07"> 14758 Jan 7, 2026 14759 </time> 14760 </p> 14761 </div> 14762 </article></div><nav class="bp-blog__pagination" aria-label="Pagination"><span class="bp-blog__page bp-blog__page--arrow is-disabled" aria-hidden="true"> 14763 <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M9 3L5 7l4 4" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg> 14764 </span><span class="bp-blog__page is-current" aria-current="page">1</span><a class="bp-blog__page" href="/blogs/styleedit?page=2">2</a><a class="bp-blog__page" href="/blogs/styleedit?page=3">3</a><span class="bp-blog__page bp-blog__page--ellipsis">…</span><a class="bp-blog__page" href="/blogs/styleedit?page=12">12</a><a class="bp-blog__page bp-blog__page--arrow" href="/blogs/styleedit?page=2" aria-label="Next page"> 14765 <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true"> 14766 <path d="M5 3l4 4-4 4" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/> 14767 </svg> 14768 </a></nav></section></bp-blog> 14769 14770 14771 14772 14773 14774 14775</div> 14776 </main> 14777 14778 <footer> 14779 <!-- BEGIN sections: footer-group --> 14780<div id="shopify-section-sections--29508264493222__bp_footer_main" class="shopify-section shopify-section-group-footer-group section-wrapper"><bp-footer 14781 class="bp-footer" 14782 data-section-id="sections--29508264493222__bp_footer_main" 14783 style=" 14784 --bp-footer-heading-color: #171609; 14785 --bp-footer-body-color: #595750; 14786 --bp-footer-link-color: #595750; 14787 --bp-footer-social-border: #e1e0d4; 14788 "><div class="bp-footer__top"> 14789 14790 <!-- Newsletter + Social: mobile copy (visible < 1024px only) --> 14791 <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 14792 type="button" 14793 class="bp-footer__signup-btn klaviyo_form_trigger_footer" 14794 data-bp-klaviyo-form-id="X8v8qM" 14795 >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"> 14796 <a 14797 href="https://www.instagram.com/bostonproperofficial/" 14798 class="bp-footer__social-icon" 14799 target="_blank" 14800 rel="noopener noreferrer" 14801 aria-label="Instagram" 14802 ><svg class="bp-footer__social-svg" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"> 14803 14804 14805<path 14806 fill-rule="evenodd" 14807 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" 14808 clip-rule="evenodd" 14809 /></svg></a> 14810 </span><span role="listitem"> 14811 <a 14812 href="https://www.tiktok.com/@bostonproperofficial" 14813 class="bp-footer__social-icon" 14814 target="_blank" 14815 rel="noopener noreferrer" 14816 aria-label="Tiktok" 14817 ><svg class="bp-footer__social-svg" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"> 14818 14819 14820<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> 14821 </span><span role="listitem"> 14822 <a 14823 href="https://www.youtube.com/@bostonproper" 14824 class="bp-footer__social-icon" 14825 target="_blank" 14826 rel="noopener noreferrer" 14827 aria-label="Youtube" 14828 ><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"> 14829 <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"/> 14830 </svg></a> 14831 </span><span role="listitem"> 14832 <a 14833 href="https://www.facebook.com/bostonproper" 14834 class="bp-footer__social-icon" 14835 target="_blank" 14836 rel="noopener noreferrer" 14837 aria-label="Facebook" 14838 ><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"> 14839 <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"/> 14840 </svg></a> 14841 </span><span role="listitem"> 14842 <a 14843 href="https://www.pinterest.com/bostonproper/" 14844 class="bp-footer__social-icon" 14845 target="_blank" 14846 rel="noopener noreferrer" 14847 aria-label="Pinterest" 14848 ><svg class="bp-footer__social-svg" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"> 14849 14850 14851<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
1485113 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> 14852 </span></div></div> 14853 14854 <!-- Nav columns: up to 3 top-level items from the selected menu --> 14855 <nav class="bp-footer__nav" aria-label="Footer navigation"><div class="bp-footer__col"> 14856 <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> 14857 <a href="/pages/catalog-request" class="bp-footer__link">Request a Catalog</a> 14858 </li><li> 14859 <a href="/pages/coupons-promotions" class="bp-footer__link">Coupons & Promotions</a> 14860 </li><li> 14861 <a href="/pages/digital-catalog" class="bp-footer__link">Online Catalog</a> 14862 </li><li> 14863 <a href="https://www.bostonproper.com/products/gift-card" class="bp-footer__link">Purchase a Gift Card</a> 14864 </li><li> 14865 <a href="/pages/check-gift-card-balance" class="bp-footer__link">Check Gift Card Balance</a> 14866 </li><li> 14867 <a href="/blogs/styleedit" class="bp-footer__link">styleEDIT Blog</a> 14868 </li><li> 14869 <a href="/pages/refer-a-friend" class="bp-footer__link">Give $20, Get $20</a> 14870 </li></ul></div><div class="bp-footer__col"> 14871 <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> 14872 <a href="/pages/about-us" class="bp-footer__link">About Us</a> 14873 </li><li> 14874 <a href="/pages/careers" class="bp-footer__link">Careers</a> 14875 </li><li> 14876 <a href="https://www.ascendpartner.com/affiliate/registration" class="bp-footer__link">Affiliate Program</a> 14877 </li><li> 14878 <a href="https://www.bostonproper.com/pages/accessibility-statement" class="bp-footer__link">Accessibility Statement</a> 14879 </li><li> 14880 <a href="/pages/use-of-ai" class="bp-footer__link">Use of AI</a> 14881 </li></ul></div><div class="bp-footer__col"> 14882 <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> 14883 <a href="/pages/customer-service" class="bp-footer__link">Customer Care</a> 14884 </li><li> 14885 <a href="/pages/order-lookup" class="bp-footer__link">Order Status</a> 14886 </li><li> 14887 <a href="https://www.bostonproper.com/pages/shipping-returns" class="bp-footer__link">Shipping</a> 14888 </li><li> 14889 <a href="https://www.bostonproper.com/pages/size-chart" class="bp-footer__link">Size Chart</a> 14890 </li><li> 14891 <a href="/pages/proper-insider-rewards" class="bp-footer__link">Proper Insider Rewards</a> 14892 </li><li> 14893 <a href="/pages/marketplace-faqs" class="bp-footer__link">Brands We Love Marketplace</a> 14894 </li><li> 14895 <a href="https://www.bostonproper.com/pages/returns-exchanges" class="bp-footer__link">Returns & Exchanges</a> 14896 </li><li>
14897 <a href="/pages/charity" class="bp-footer__link">Style Meets Purpose</a> 14898 </li><li> 14899 <a href="https://www.facebook.com/groups/4044543892348249/" class="bp-footer__link">Join Our Signature Circle</a> 14900 </li></ul></div></nav> 14901 14902 <!-- Newsletter + Social: desktop copy (visible >= 1024px only) --> 14903 <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 14904 type="button" 14905 class="bp-footer__signup-btn klaviyo_form_trigger_footer" 14906 data-bp-klaviyo-form-id="X8v8qM" 14907 >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"> 14908 <a 14909 href="https://www.instagram.com/bostonproperofficial/" 14910 class="bp-footer__social-icon" 14911 target="_blank" 14912 rel="noopener noreferrer" 14913 aria-label="Instagram" 14914 ><svg class="bp-footer__social-svg" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"> 14915 14916 14917<path 14918 fill-rule="evenodd" 14919 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" 14920 clip-rule="evenodd" 14921 /></svg></a> 14922 </span><span role="listitem"> 14923 <a 14924 href="https://www.tiktok.com/@bostonproperofficial" 14925 class="bp-footer__social-icon" 14926 target="_blank" 14927 rel="noopener noreferrer" 14928 aria-label="Tiktok" 14929 ><svg class="bp-footer__social-svg" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"> 14930 14931 14932<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> 14933 </span><span role="listitem"> 14934 <a 14935 href="https://www.youtube.com/@bostonproper" 14936 class="bp-footer__social-icon" 14937 target="_blank" 14938 rel="noopener noreferrer" 14939 aria-label="Youtube" 14940 ><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"> 14941 <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"/> 14942 </svg></a> 14943 </span><span role="listitem"> 14944 <a 14945 href="https://www.facebook.com/bostonproper" 14946 class="bp-footer__social-icon" 14947 target="_blank" 14948 rel="noopener noreferrer" 14949 aria-label="Facebook" 14950 ><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"> 14951 <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"/> 14952 </svg></a> 14953 </span><span role="listitem"> 14954 <a 14955 href="https://www.pinterest.com/bostonproper/" 14956 class="bp-footer__social-icon" 14957 target="_blank" 14958 rel="noopener noreferrer" 14959 aria-label="Pinterest" 14960 ><svg class="bp-footer__social-svg" aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"> 14961 14962 14963<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
1496313 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> 14964 </span></div></div> 14965 14966 </div><!-- /.bp-footer__top --> 14967 14968 <!-- Full-bleed brand wordmark --> 14969 <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.
14969045-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
14969)"/><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> 14970 14971 <!-- Policy bar: copyright left, links right --> 14972 <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> 14973 <a href="/pages/shipping-returns" class="bp-footer__policy-link">Shipping Policy</a> 14974 <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> 14975 </div> 14976 14977 14978</bp-footer> 14979 14980 14981 14982 14983 14984 14985</div> 14986<!-- END sections: footer-group --> 14987 </footer> 14988 14989 14990
14991<script 14992 src="//www.bostonproper.com/cdn/shop/t/1516/assets/dialog.js?v=150888536568694194021790192827" 14993 type="module" 14994></script>
14994 14995
14996<script 14997 src="//www.bostonproper.com/cdn/shop/t/1516/assets/predictive-search.js?v=174099676085626643091790192827" 14998 type="module" 14999 fetchpriority="low" 15000></script>
15000 15001 15002<dialog-component 15003 id="search-modal" 15004 class="search-modal" 15005 15006> 15007 <dialog 15008 ref="dialog" 15009 on:click="/closeDialogOnClickOutside" 15010 on:keydown="/closeDialogOnEscapePress" 15011 class="search-modal__content dialog-modal" 15012 scroll-lock 15013 aria-labelledby="search-modal-heading" 15014 > 15015 <h2 15016 id="search-modal-heading" 15017 class="visually-hidden" 15018 > 15019 Search 15020 </h2> 15021 <predictive-search-component 15022 class="predictive-search color-scheme-1" 15023 style="--product-corner-radius: 0px; --card-corner-radius: 4px;" 15024 data-section-id="predictive-search" 15025 data-testid="search-component--modal" 15026 role="search" 15027 aria-label="Search" 15028 > 15029 <form 15030 action="/search" 15031 method="get" 15032 role="search" 15033 class="predictive-search-form" 15034 ref="form" 15035 on:keydown="/onSearchKeyDown" 15036 > 15037 <div 15038 class="predictive-search-form__header" 15039 > 15040 <div class="predictive-search-form__header-inner"> 15041 <label 15042 for="cmdk-input" 15043 class="visually-hidden" 15044 >Search</label> 15045 <input 15046 class="search-input" 15047 id="cmdk-input" 15048 type="search" 15049 name="q" 15050 role="combobox" 15051 aria-expanded="false" 15052 aria-owns="predictive-search-results" 15053 aria-controls="predictive-search-results" 15054 aria-haspopup="listbox" 15055 aria-autocomplete="list" 15056 autocomplete="off" 15057 placeholder="Search" 15058 ref="searchInput" 15059 on:input="/search" 15060 on:keydown="/onSearchKeyDown" 15061 > 15062 <input 15063 name="options[prefix]" 15064 type="hidden" 15065 value="last" 15066 > 15067 <span class="svg-wrapper predictive-search__icon"> 15068 <svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg"> 15069<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"/> 15070<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"/> 15071</svg> 15072 15073 </span> 15074 <button 15075 type="button" 15076 class="button-unstyled predictive-search__reset-button" 15077 ref="resetButton" 15078 hidden 15079 on:click="/resetSearch" 15080 > 15081 Clear 15082 </button> 15083 </div> 15084 <button 15085 type="button" 15086 class="button predictive-search__close-modal-button" 15087 aria-label="Close dialog" 15088 on:click="dialog-component/closeDialog" 15089 ref="closeModalButton" 15090 > 15091 <span class="svg-wrapper"> 15092 <svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"> 15093 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 15094 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 15095</svg> 15096 15097 </span> 15098 </button> 15099 </div> 15100 15101 <div class="predictive-search-form__content-wrapper"> 15102 <div 15103 class="predictive-search-form__content" 15104 ref="predictiveSearchResults" 15105 on:click="/handleModalClick" 15106 > 15107 15108<div 15109 id="predictive-search-results" 15110 class="predictive-search-dropdown" 15111 role="listbox"
15112 aria-expanded="true" 15113 style="--color-shadow: rgb(var(--color-foreground-rgb) / 0.1);" 15114> 15115 15116 <div class="predictive-search-results__inner"> 15117 15118 15119 15120 15121 15122 <div 15123 id="predictive-search-products" 15124 class="predictive-search-results__products" 15125 15126 data-testid="search-component-default--modal" 15127 15128> 15129 15130 <h4 class="predictive-search-results__title"> 15131 Products 15132 </h4> 15133 <ul 15134 class="predictive-search-results__list predictive-search-results__wrapper-products list-unstyled" 15135 > 15136 15137 15138 <li 15139 class="predictive-search-results__card predictive-search-results__card--product" 15140 ref="resultsItems[]" 15141 > 15142 <product-card class="bp-card-host"> 15143 <article 15144 class="bp-card" 15145 data-product-id="15399681392806" 15146 data-product-url="/products/leopard-print-skirt-brown-multi" 15147 data-bp-card-secondary-hover="true" 15148 data-bp-card-qv-dest="drawer" 15149 data-bp-card-qv-vis-d="hover" 15150 data-bp-card-qv-vis-m="shown" 15151 data-bp-card-qb-style="button" 15152 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_e449d9f8-fa91-4b71-a931-89e5295d2d60.jpg?v=1790318066\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": 63 } }' 15153 > 15154 <div class="bp-card__media"> 15155 <a class="bp-card__media-link" href="/products/leopard-print-skirt-brown-multi" aria-label="Leopard Print Skirt Brown Multi" ref="productCardLink"><img 15156 class="bp-card__image bp-card__image--primary" 15157 src="//www.bostonproper.com/cdn/shop/files/2DO3390_SET_e449d9f8-fa91-4b71-a931-89e5295d2d60.jpg?v=1790318066&width=720" 15158 srcset="//www.bostonproper.com/cdn/shop/files/2DO3390_SET_e449d9f8-fa91-4b71-a931-89e5295d2d60.jpg?v=1790318066&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DO3390_SET_e449d9f8-fa91-4b71-a931-89e5295d2d60.jpg?v=1790318066&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DO3390_SET_e449d9f8-fa91-4b71-a931-89e5295d2d60.jpg?v=1790318066&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DO3390_SET_e449d9f8-fa91-4b71-a931-89e5295d2d60.jpg?v=1790318066&width=1080 1080w" 15159 sizes="(min-width: 1024px) 25vw, 50vw" 15160 width="1639" 15161 height="2048" 15162 alt="Leopard Print Skirt Brown Multi" 15163 loading="lazy" 15164 data-bp-card-image-primary 15165 ><img 15166 class="bp-card__image bp-card__image--secondary" 15167 src="//www.bostonproper.com/cdn/shop/files/2_dead2446-d579-467e-97bd-b826507a5f69.jpg?v=1790318067&width=720" 15168 srcset="//www.bostonproper.com/cdn/shop/files/2_dead2446-d579-467e-97bd-b826507a5f69.jpg?v=1790318067&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_dead2446-d579-467e-97bd-b826507a5f69.jpg?v=1790318067&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_dead2446-d579-467e-97bd-b826507a5f69.jpg?v=1790318067&width=720 720w" 15169 sizes="(min-width: 1024px) 25vw, 50vw" 15170 width="1639" 15171 height="2048" 15172 alt="" 15173 loading="lazy" 15174 aria-hidden="true" 15175 data-bp-card-image-secondary 15176 ></a><div class="bp-card__badges" data-bp-card-badges></div><button 15177 type="button" 15178 class="bp-card__quick" 15179 aria-label="Quick add Leopard Print Skirt Brown Multi" 15180 data-product-id="15399681392806" 15181 data-bp-card-qv-trigger 15182 > 15183 <svg viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> 15184 <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
15184028 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"/> 15185 <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"/> 15186 </svg> 15187 </button><div class="bp-card__quick-add"> 15188 15189<quick-add-component 15190 class="quick-add color-scheme-1 " 15191 ref="quickAdd" 15192 data-product-title="Leopard Print Skirt Brown Multi" 15193 data-quick-add-button="choose" 15194 data-product-options-count="2" 15195> 15196 <product-form-component 15197 data-section-id="bp-card" 15198 data-product-id="15399681392806" 15199 on:submit="/handleSubmit" 15200 class="quick-add__product-form-component" 15201 > 15202 <div 15203 class="visually-hidden" 15204 aria-live="assertive" 15205 role="status" 15206 aria-atomic="true" 15207 ref="liveRegion" 15208 ></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 15209 type="hidden" 15210 name="id" 15211 ref="variantId" 15212 value="56779671077030" 15213 15214 > 15215 <input 15216 type="hidden" 15217 name="quantity" 15218 value="1" 15219 > 15220 15221 <add-to-cart-component 15222 ref="addToCartButtonContainer" 15223 data-product-variant-media="//www.bostonproper.com/cdn/shop/files/2DO3390_SET_e449d9f8-fa91-4b71-a931-89e5295d2d60.jpg?v=1790318066&width=100" 15224 data-add-to-cart-animation="true" 15225> 15226 <button 15227 15228 type="submit" 15229 name="add" 15230 ref="addToCartButton" 15231 on:click="/handleClick" 15232 class="button button quick-add__button quick-add__button--add add-to-cart-button" 15233 15234 15235 > 15236 <span 15237 class="add-to-cart-text" 15238 > 15239 15240 <span 15241 aria-hidden="true" 15242 class="svg-wrapper add-to-cart-icon" 15243 ><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> 15244</span> 15245
15246 <span class="add-to-cart-text__content is-visually-hidden-mobile"> 15247 <span> 15248 <span>Add</span> 15249 </span> 15250 </span> 15251 </span> 15252 15253 <span class="add-to-cart__added"> 15254 <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"> 15255 <g class="check"> 15256 <circle class="ring" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 15257 <path class="tick" d="M9 12.75L11.25 15L15 9.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 15258 </g> 15259 <g class="burst"> 15260 <g style="--index: 0;"> 15261 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15262 </g> 15263 <g style="--index: 1;"> 15264 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15265 </g> 15266 <g style="--index: 2;"> 15267 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15268 </g> 15269 <g style="--index: 3;"> 15270 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15271 </g> 15272 <g style="--index: 4;"> 15273 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15274 </g> 15275 <g style="--index: 5;"> 15276 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15277 </g> 15278 <g style="--index: 6;"> 15279 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15280 </g> 15281 <g style="--index: 7;"> 15282 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15283 </g> 15284 </g> 15285</svg> 15286</span> 15287 </span> 15288 </button> 15289</add-to-cart-component> 15290 15291 15292 <button 15293 class="button quick-add__button quick-add__button--choose add-to-cart-button" 15294 15295 type="button" 15296 name="add" 15297 on:click="quick-add-component/handleClick" 15298 > 15299 <span 15300 class="add-to-cart-text" 15301 > 15302 15303 <span 15304 aria-hidden="true" 15305 class="svg-wrapper add-to-cart-icon" 15306 ><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> 15307</span> 15308 <span class="add-to-cart-text__content is-visually-hidden-mobile"> 15309 <span> 15310 15311 <span> 15312 Choose 15313 </span> 15314 </span> 15315 </span> 15316 </span> 15317 </button><input type="hidden" name="product-id" value="15399681392806" /></form></product-form-component> 15318</quick-add-component> 15319 15320 15321 15322</div></div> 15323 15324 <div class="bp-card__body"><h3 class="bp-card__title"> 15325 <a href="/products/leopard-print-skirt-brown-multi">Leopard Print Skirt</a> 15326 </h3> 15327 15328 <div class="bp-card__price-row"><span class="bp-card__price">$110</span> 15329 <s class="bp-card__compare" hidden></s></div></div> 15330 </article> 15331</product-card> 15332 15333 </li> 15334 15335 <li 15336 class="predictive-search-results__card predictive-search-results__card--product" 15337 ref="resultsItems[]" 15338 > 15339 <product-card class="bp-card-host"> 15340 <article 15341 class="bp-card" 15342 data-product-id="15399681360038" 15343 data-product-url="/products/metallic-zebra-printed-dress-tan-multi" 15344 data-bp-card-secondary-hover="true" 15345 data-bp-card-qv-dest="drawer" 15346 data-bp-card-qv-vis-d="hover" 15347 data-bp-card-qv-vis-m="shown" 15348 data-bp-card-qb-style="button" 15349 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_
15349SET_3e78a356-4a13-44de-871d-1d9f536a1a85.jpg?v=1790318054\u0026width=720", "category": "Dresses", "product_type":null, "selected_variant": { "id": 56779670782118, "sku": "2DO0590006", "price": 129.0, "compare_at_price": 180.0, "option1": "Tan Multi", "option2": "6", "product_id": 15399681360038, "available": true, "inventory_quantity": 50 } }' 15350 > 15351 <div class="bp-card__media"> 15352 <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 15353 class="bp-card__image bp-card__image--primary" 15354 src="//www.bostonproper.com/cdn/shop/files/2DO0590_SET_3e78a356-4a13-44de-871d-1d9f536a1a85.jpg?v=1790318054&width=720" 15355 srcset="//www.bostonproper.com/cdn/shop/files/2DO0590_SET_3e78a356-4a13-44de-871d-1d9f536a1a85.jpg?v=1790318054&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DO0590_SET_3e78a356-4a13-44de-871d-1d9f536a1a85.jpg?v=1790318054&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DO0590_SET_3e78a356-4a13-44de-871d-1d9f536a1a85.jpg?v=1790318054&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DO0590_SET_3e78a356-4a13-44de-871d-1d9f536a1a85.jpg?v=1790318054&width=1080 1080w" 15356 sizes="(min-width: 1024px) 25vw, 50vw" 15357 width="1639" 15358 height="2048" 15359 alt="Metallic Zebra Printed Dress Tan Multi" 15360 loading="lazy" 15361 data-bp-card-image-primary 15362 ><img 15363 class="bp-card__image bp-card__image--secondary" 15364 src="//www.bostonproper.com/cdn/shop/files/2_a7042052-cb79-4a3a-bc67-beabd9416119.jpg?v=1790318054&width=720" 15365 srcset="//www.bostonproper.com/cdn/shop/files/2_a7042052-cb79-4a3a-bc67-beabd9416119.jpg?v=1790318054&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_a7042052-cb79-4a3a-bc67-beabd9416119.jpg?v=1790318054&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_a7042052-cb79-4a3a-bc67-beabd9416119.jpg?v=1790318054&width=720 720w" 15366 sizes="(min-width: 1024px) 25vw, 50vw" 15367 width="1639" 15368 height="2048" 15369 alt="" 15370 loading="lazy" 15371 aria-hidden="true" 15372 data-bp-card-image-secondary 15373 ></a><div class="bp-card__badges" data-bp-card-badges></div><button 15374 type="button" 15375 class="bp-card__quick" 15376 aria-label="Quick add Metallic Zebra Printed Dress Tan Multi" 15377 data-product-id="15399681360038" 15378 data-bp-card-qv-trigger 15379 > 15380 <svg viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> 15381 <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"/> 15382 <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"/> 15383 </svg> 15384 </button><div class="bp-card__quick-add"> 15385 15386<quick-add-component 15387 class="quick-add color-scheme-1 " 15388 ref="quickAdd" 15389 data-product-title="Metallic Zebra Printed Dress Tan Multi" 15390 data-quick-add-button="choose" 15391 data-product-options-count="2" 15392> 15393 <product-form-component 15394 data-section-id="bp-card" 15395 data-product-id="15399681360038" 15396 on:submit="/handleSubmit" 15397 class="quick-add__product-form-component" 15398 > 15399 <div 15400 class="visually-hidden"
15401 aria-live="assertive" 15402 role="status" 15403 aria-atomic="true" 15404 ref="liveRegion" 15405 ></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 15406 type="hidden" 15407 name="id" 15408 ref="variantId" 15409 value="56779670782118" 15410 15411 > 15412 <input 15413 type="hidden" 15414 name="quantity" 15415 value="1" 15416 > 15417 15418 <add-to-cart-component 15419 ref="addToCartButtonContainer" 15420 data-product-variant-media="//www.bostonproper.com/cdn/shop/files/2DO0590_SET_3e78a356-4a13-44de-871d-1d9f536a1a85.jpg?v=1790318054&width=100" 15421 data-add-to-cart-animation="true" 15422> 15423 <button 15424 15425 type="submit" 15426 name="add" 15427 ref="addToCartButton" 15428 on:click="/handleClick" 15429 class="button button quick-add__button quick-add__button--add add-to-cart-button" 15430 15431 15432 > 15433 <span 15434 class="add-to-cart-text" 15435 > 15436 15437 <span 15438 aria-hidden="true" 15439 class="svg-wrapper add-to-cart-icon" 15440 ><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> 15441</span> 15442 15443 <span class="add-to-cart-text__content is-visually-hidden-mobile"> 15444 <span> 15445 <span>Add</span> 15446 </span> 15447 </span> 15448 </span> 15449 15450 <span class="add-to-cart__added"> 15451 <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"> 15452 <g class="check"> 15453 <circle class="ring" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 15454 <path class="tick" d="M9 12.75L11.25 15L15 9.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 15455 </g> 15456 <g class="burst"> 15457 <g style="--index: 0;"> 15458 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15459 </g> 15460 <g style="--index: 1;"> 15461 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15462 </g> 15463 <g style="--index: 2;"> 15464 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15465 </g> 15466 <g style="--index: 3;"> 15467 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15468 </g> 15469 <g style="--index: 4;"> 15470 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15471 </g> 15472 <g style="--index: 5;"> 15473 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15474 </g> 15475 <g style="--index: 6;"> 15476 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15477 </g> 15478 <g style="--index: 7;"> 15479 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15480 </g> 15481 </g> 15482</svg> 15483</span> 15484 </span> 15485 </button> 15486</add-to-cart-component> 15487 15488 15489 <button 15490 class="button quick-add__button quick-add__button--choose add-to-cart-button" 15491 15492 type="button" 15493 name="add" 15494 on:click="quick-add-component/handleClick" 15495 > 15496 <span 15497 class="add-to-cart-text" 15498 > 15499
15500 <span 15501 aria-hidden="true" 15502 class="svg-wrapper add-to-cart-icon" 15503 ><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> 15504</span> 15505 <span class="add-to-cart-text__content is-visually-hidden-mobile"> 15506 <span> 15507 15508 <span> 15509 Choose 15510 </span> 15511 </span> 15512 </span> 15513 </span> 15514 </button><input type="hidden" name="product-id" value="15399681360038" /></form></product-form-component> 15515</quick-add-component> 15516 15517 15518 15519</div></div> 15520 15521 <div class="bp-card__body"><h3 class="bp-card__title"> 15522 <a href="/products/metallic-zebra-printed-dress-tan-multi">Metallic Zebra Printed Dress</a> 15523 </h3> 15524 15525 <div class="bp-card__price-row"><span class="bp-card__price">$129</span> 15526 <s class="bp-card__compare">$180</s><span class="bp-card__promo">Limited time! Up to 35% off. Price as marked</span></div></div> 15527 </article> 15528</product-card> 15529 15530 </li> 15531 15532 <li 15533 class="predictive-search-results__card predictive-search-results__card--product" 15534 ref="resultsItems[]" 15535 > 15536 <product-card class="bp-card-host"> 15537 <article 15538 class="bp-card" 15539 data-product-id="15366923452582" 15540 data-product-url="/products/mock-neck-intarsia-flare-sleeve-tunic-west-side-paisley" 15541 data-bp-card-secondary-hover="true" 15542 data-bp-card-qv-dest="drawer" 15543 data-bp-card-qv-vis-d="hover" 15544 data-bp-card-qv-vis-m="shown" 15545 data-bp-card-qb-style="button" 15546 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_499b9b85-0db7-4637-8d16-16c878e06144.jpg?v=1790318077\u0026width=720", "category": "Sweater Tops", "product_type":null, "selected_variant": { "id": 56658234933414, "sku": "2DM9540400", "price": 69.0, "compare_at_price": 100.0, "option1": "West Side Paisley", "option2": "XXS", "product_id": 15366923452582, "available": true, "inventory_quantity": 5 } }' 15547 > 15548 <div class="bp-card__media"> 15549 <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 15550 class="bp-card__image bp-card__image--primary" 15551 src="//www.bostonproper.com/cdn/shop/files/2DM9540_SET_499b9b85-0db7-4637-8d16-16c878e06144.jpg?v=1790318077&width=720" 15552 srcset="//www.bostonproper.com/cdn/shop/files/2DM9540_SET_499b9b85-0db7-4637-8d16-16c878e06144.jpg?v=1790318077&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DM9540_SET_499b9b85-0db7-4637-8d16-16c878e06144.jpg?v=1790318077&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DM9540_SET_499b9b85-0db7-4637-8d16-16c878e06144.jpg?v=1790318077&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DM9540_SET_499b9b85-0db7-4637-8d16-16c878e06144.jpg?v=1790318077&width=1080 1080w" 15553 sizes="(min-width: 1024px) 25vw, 50vw" 15554 width="1639" 15555 height="2048" 15556 alt="Mock Neck Intarsia Flare Sleeve Tunic West Side Paisley" 15557 loading="lazy" 15558 data-bp-card-image-primary 15559 ><img 15560 class="bp-card__image bp-card__image--secondary" 15561 src="//www.bostonproper.com/cdn/shop/files/2_00a39f4d-0849-463b-8461-326fe573f6a1.jpg?v=1790318077&width=720" 15562 srcset="//www.bostonproper.com/cdn/shop/files/2_00a39f4d-0849-463b-8461-326fe573f6a1.jpg?v=1790318077&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_00a39f4d-0849-463b-8461-326fe573f6a1.jpg?v=1790318077&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_00a39f4d-0849-463b-8461-326fe573f6a1.jpg?v=1790318077&width=720 720w" 15563 sizes="(min-width: 1024px) 25vw, 50vw" 15564 width="1639" 15565 height="2048" 15566 alt="" 15567 loading="lazy" 15568 aria-hidden="true" 15569 data-bp-card-image-secondary 15570 ></a><div class="bp-card__badges" data-bp-card-badges></div><button 15571 type="button" 15572 class="bp-card__quick" 15573 aria-label="Quick add Mock Neck Intarsia Flare Sleeve Tunic West Side Paisley" 15574 data-product-id="15366923452582" 15575 data-bp-card-qv-trigger 15576 > 15577 <svg viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> 15578 <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
15578028 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"/> 15579 <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"/> 15580 </svg> 15581 </button><div class="bp-card__quick-add"> 15582 15583<quick-add-component 15584 class="quick-add color-scheme-1 " 15585 ref="quickAdd" 15586 data-product-title="Mock Neck Intarsia Flare Sleeve Tunic West Side Paisley" 15587 data-quick-add-button="choose" 15588 data-product-options-count="2" 15589> 15590 <product-form-component 15591 data-section-id="bp-card" 15592 data-product-id="15366923452582" 15593 on:submit="/handleSubmit" 15594 class="quick-add__product-form-component" 15595 > 15596 <div 15597 class="visually-hidden" 15598 aria-live="assertive" 15599 role="status" 15600 aria-atomic="true" 15601 ref="liveRegion" 15602 ></div><form method="post" action="/cart/add" id="QuickAdd-ProductForm-15366923452582-" 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 15603 type="hidden" 15604 name="id" 15605 ref="variantId" 15606 value="56658234933414" 15607 15608 > 15609 <input 15610 type="hidden" 15611 name="quantity" 15612 value="1" 15613 > 15614 15615 <add-to-cart-component 15616 ref="addToCartButtonContainer" 15617 data-product-variant-media="//www.bostonproper.com/cdn/shop/files/2DM9540_SET_499b9b85-0db7-4637-8d16-16c878e06144.jpg?v=1790318077&width=100" 15618 data-add-to-cart-animation="true" 15619> 15620 <button 15621 15622 type="submit" 15623 name="add" 15624 ref="addToCartButton" 15625 on:click="/handleClick" 15626 class="button button quick-add__button quick-add__button--add add-to-cart-button" 15627 15628 15629 > 15630 <span 15631 class="add-to-cart-text" 15632 > 15633 15634 <span 15635 aria-hidden="true" 15636 class="svg-wrapper add-to-cart-icon" 15637 ><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> 15638</span> 15639
15640 <span class="add-to-cart-text__content is-visually-hidden-mobile"> 15641 <span> 15642 <span>Add</span> 15643 </span> 15644 </span> 15645 </span> 15646 15647 <span class="add-to-cart__added"> 15648 <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"> 15649 <g class="check"> 15650 <circle class="ring" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 15651 <path class="tick" d="M9 12.75L11.25 15L15 9.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 15652 </g> 15653 <g class="burst"> 15654 <g style="--index: 0;"> 15655 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15656 </g> 15657 <g style="--index: 1;"> 15658 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15659 </g> 15660 <g style="--index: 2;"> 15661 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15662 </g> 15663 <g style="--index: 3;"> 15664 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15665 </g> 15666 <g style="--index: 4;"> 15667 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15668 </g> 15669 <g style="--index: 5;"> 15670 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15671 </g> 15672 <g style="--index: 6;"> 15673 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15674 </g> 15675 <g style="--index: 7;"> 15676 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15677 </g> 15678 </g> 15679</svg> 15680</span> 15681 </span> 15682 </button> 15683</add-to-cart-component> 15684 15685 15686 <button 15687 class="button quick-add__button quick-add__button--choose add-to-cart-button" 15688 15689 type="button" 15690 name="add" 15691 on:click="quick-add-component/handleClick" 15692 > 15693 <span 15694 class="add-to-cart-text" 15695 > 15696 15697 <span 15698 aria-hidden="true" 15699 class="svg-wrapper add-to-cart-icon" 15700 ><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> 15701</span> 15702 <span class="add-to-cart-text__content is-visually-hidden-mobile"> 15703 <span> 15704 15705 <span> 15706 Choose 15707 </span> 15708 </span> 15709 </span> 15710 </span> 15711 </button><input type="hidden" name="product-id" value="15366923452582" /></form></product-form-component> 15712</quick-add-component> 15713 15714 15715 15716</div></div> 15717 15718 <div class="bp-card__body"><h3 class="bp-card__title"> 15719 <a href="/products/mock-neck-intarsia-flare-sleeve-tunic-west-side-paisley">Mock Neck Intarsia Flare Sleeve Tunic</a> 15720 </h3> 15721 15722 <div class="bp-card__price-row"><span class="bp-card__price">$69</span> 15723 <s class="bp-card__compare">$100</s><span class="bp-card__promo">Limited time! Up to 35% off. Price as marked</span></div></div> 15724 </article> 15725</product-card> 15726 15727 </li> 15728 15729 <li 15730 class="predictive-search-results__card predictive-search-results__card--product" 15731 ref="resultsItems[]" 15732 > 15733 <product-card class="bp-card-host"> 15734 <article 15735 class="bp-card" 15736 data-product-id="15336227864742" 15737 data-product-url="/products/knit-suede-drape-front-jacket-stone" 15738 data-bp-card-secondary-hover="true" 15739 data-bp-card-qv-dest="drawer" 15740 data-bp-card-qv-vis-d="hover" 15741 data-bp-card-qv-vis-m="shown" 15742 data-bp-card-qb-style="button" 15743 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=1790318159\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 } }' 15744 > 15745 <div class="bp-card__media"> 15746 <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 15747 class="bp-card__image bp-card__image--primary" 15748 src="//www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1790318159&width=720" 15749 srcset="//www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1790318159&width=360 360w, //www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1790318159&width=540 540w, //www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1790318159&width=720 720w, //www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1790318159&width=1080 1080w" 15750 sizes="(min-width: 1024px) 25vw, 50vw" 15751 width="1639" 15752 height="2048" 15753 alt="Knit Suede Drape Front Jacket Stone" 15754 loading="lazy" 15755 data-bp-card-image-primary 15756 ><img 15757 class="bp-card__image bp-card__image--secondary" 15758 src="//www.bostonproper.com/cdn/shop/files/2_94315d5c-6ff8-48ec-ab66-ed64157b7e3d.jpg?v=1790318159&width=720" 15759 srcset="//www.bostonproper.com/cdn/shop/files/2_94315d5c-6ff8-48ec-ab66-ed64157b7e3d.jpg?v=1790318159&width=360 360w, //www.bostonproper.com/cdn/shop/files/2_94315d5c-6ff8-48ec-ab66-ed64157b7e3d.jpg?v=1790318159&width=540 540w, //www.bostonproper.com/cdn/shop/files/2_94315d5c-6ff8-48ec-ab66-ed64157b7e3d.jpg?v=1790318159&width=720 720w" 15760 sizes="(min-width: 1024px) 25vw, 50vw" 15761 width="1639" 15762 height="2048" 15763 alt="" 15764 loading="lazy" 15765 aria-hidden="true" 15766 data-bp-card-image-secondary 15767 ></a><div class="bp-card__badges" data-bp-card-badges></div><button 15768 type="button" 15769 class="bp-card__quick" 15770 aria-label="Quick add Knit Suede Drape Front Jacket Stone" 15771 data-product-id="15336227864742" 15772 data-bp-card-qv-trigger 15773 > 15774 <svg viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> 15775 <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
15775028 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"/> 15776 <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"/> 15777 </svg> 15778 </button><div class="bp-card__quick-add"> 15779 15780<quick-add-component 15781 class="quick-add color-scheme-1 " 15782 ref="quickAdd" 15783 data-product-title="Knit Suede Drape Front Jacket Stone" 15784 data-quick-add-button="choose" 15785 data-product-options-count="2" 15786> 15787 <product-form-component 15788 data-section-id="bp-card" 15789 data-product-id="15336227864742" 15790 on:submit="/handleSubmit" 15791 class="quick-add__product-form-component" 15792 > 15793 <div 15794 class="visually-hidden" 15795 aria-live="assertive" 15796 role="status" 15797 aria-atomic="true" 15798 ref="liveRegion" 15799 ></div><form method="post" action="/cart/add" id="QuickAdd-ProductForm-15336227864742-" 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 15800 type="hidden" 15801 name="id" 15802 ref="variantId" 15803 value="56545549123750" 15804 15805 > 15806 <input 15807 type="hidden" 15808 name="quantity" 15809 value="1" 15810 > 15811 15812 <add-to-cart-component 15813 ref="addToCartButtonContainer" 15814 data-product-variant-media="//www.bostonproper.com/cdn/shop/files/2DR1780_SET.jpg?v=1790318159&width=100" 15815 data-add-to-cart-animation="true" 15816> 15817 <button 15818 15819 type="submit" 15820 name="add" 15821 ref="addToCartButton" 15822 on:click="/handleClick" 15823 class="button button quick-add__button quick-add__button--add add-to-cart-button" 15824 15825 15826 > 15827 <span 15828 class="add-to-cart-text" 15829 > 15830 15831 <span 15832 aria-hidden="true" 15833 class="svg-wrapper add-to-cart-icon" 15834 ><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> 15835</span> 15836
15837 <span class="add-to-cart-text__content is-visually-hidden-mobile"> 15838 <span> 15839 <span>Add</span> 15840 </span> 15841 </span> 15842 </span> 15843 15844 <span class="add-to-cart__added"> 15845 <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"> 15846 <g class="check"> 15847 <circle class="ring" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 15848 <path class="tick" d="M9 12.75L11.25 15L15 9.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 15849 </g> 15850 <g class="burst"> 15851 <g style="--index: 0;"> 15852 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15853 </g> 15854 <g style="--index: 1;"> 15855 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15856 </g> 15857 <g style="--index: 2;"> 15858 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15859 </g> 15860 <g style="--index: 3;"> 15861 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15862 </g> 15863 <g style="--index: 4;"> 15864 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15865 </g> 15866 <g style="--index: 5;"> 15867 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15868 </g> 15869 <g style="--index: 6;"> 15870 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15871 </g> 15872 <g style="--index: 7;"> 15873 <line class="line" stroke-linecap="round" pathLength="1" x1="12" y1="8.5" x2="12" y2="15.5" stroke="currentColor"/> 15874 </g> 15875 </g> 15876</svg> 15877</span> 15878 </span> 15879 </button> 15880</add-to-cart-component> 15881 15882 15883 <button 15884 class="button quick-add__button quick-add__button--choose add-to-cart-button" 15885 15886 type="button" 15887 name="add" 15888 on:click="quick-add-component/handleClick" 15889 > 15890 <span 15891 class="add-to-cart-text" 15892 > 15893 15894 <span 15895 aria-hidden="true" 15896 class="svg-wrapper add-to-cart-icon" 15897 ><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> 15898</span> 15899 <span class="add-to-cart-text__content is-visually-hidden-mobile"> 15900 <span> 15901 15902 <span> 15903 Choose 15904 </span> 15905 </span> 15906 </span> 15907 </span> 15908 </button><input type="hidden" name="product-id" value="15336227864742" /></form></product-form-component> 15909</quick-add-component> 15910 15911 15912 15913</div></div> 15914 15915 <div class="bp-card__body"><h3 class="bp-card__title"> 15916 <a href="/products/knit-suede-drape-front-jacket-stone">Knit Suede Drape Front Jacket</a> 15917 </h3> 15918 15919 <div class="bp-card__price-row"><span class="bp-card__price">$125</span> 15920 <s class="bp-card__compare" hidden></s></div><ul class="bp-card__swatches" role="list" aria-label="Available colors"> 15921 <li class="bp-card__swatch-item"><button 15922 type="button" 15923 class="bp-card__swatch" 15924 aria-label="Blue" 15925 15926 data-bp-card-swatch-image="https://media.bostonproper.com/s/bostonproper/2DR1730_SET?w=720" 15927 data-bp-card-swatch-hover="https://media.bostonproper.com/s/bostonproper/2DR1730_SET/2?w=720" 15928 data-bp-variant-url="/products/knit-suede-drape-front-jacket-blue" 15929 data-bp-swatch-price="$125" 15930 15931 > 15932 <img 15933 class="bp-card__swatch-img" 15934 src="https://media.bostonproper.com/i/bostonproper/2DR1730_2?$poiswatch$&img404=2DR1730_1" 15935 alt="" 15936 aria-hidden="true" 15937 width="23" 15938 height="23" 15939 loading="lazy" 15940 > 15941 </button></li><li class="bp-card__swatch-item"><button 15942 type="button" 15943 class="bp-card__swatch bp-card__swatch--active" 15944 aria-label="Stone" 15945 aria-current="true" 15946 data-bp-card-swatch-image="https://media.bostonproper.com/s/bostonproper/2DR1780_SET?w=720" 15947 data-bp-card-swatch-hover="https://media.bostonproper.com/s/bostonproper/2DR1780_SET/2?w=720" 15948 data-bp-variant-url="/products/knit-suede-drape-front-jacket-stone" 15949 data-bp-swatch-price="$125" 15950 15951 > 15952 <img 15953 class="bp-card__swatch-img" 15954 src="https://media.bostonproper.com/i/bostonproper/2DR1780_2?$poiswatch$&img404=2DR1780_1" 15955 alt="" 15956 aria-hidden="true" 15957 width="23" 15958 height="23" 15959 loading="lazy" 15960 > 15961 </button></li> 15962</ul></div> 15963 </article> 15964</product-card> 15965 15966 </li> 15967 15968 </ul> 15969 15970</div> 15971 15972 15973 15974 </div> 15975 15976</div> 15977</div> 15978 15979 <div class="predictive-search-form__footer"> 15980 <button 15981 class="button predictive-search__search-button" 15982 ref="viewAllButton" 15983 > 15984 View all 15985 </button> 15986 </div> 15987 </div> 15988 </form> 15989 </predictive-search-component> 15990 </dialog> 15991</dialog-component> 15992 15993 15994 15995<bp-search-drawer 15996 class="bp-sd" 15997 aria-hidden="true" 15998 inert 15999 data-search-url="/search" 16000 data-br-enabled="1" 16001> 16002 <div class="bp-sd__panel"> 16003 <form class="bp-sd__form" action="/search" method="get"> 16004 <input type="hidden" name="options[prefix]" value="last"> 16005 16006 <div class="bp-sd__header">
16007 <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"> 16008<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"/> 16009<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"/> 16010</svg> 16011</span> 16012 <input 16013 type="search" 16014 name="q" 16015 id="bp-sd-input" 16016 class="bp-sd__input" 16017 placeholder="Search" 16018 autocomplete="off" 16019 aria-label="Search" 16020 role="combobox" 16021 aria-expanded="false" 16022 aria-controls="bp-sp-products" 16023 aria-autocomplete="list" 16024 > 16025 <button type="button" class="bp-sd__clear" hidden>Clear</button> 16026 </div><p class="visually-hidden" role="status" aria-live="polite" data-bp-search-status></p><div class="bp-sp"> 16027 <div class="bp-sp__body"> 16028 16029 <aside class="bp-sp__sidebar" data-br-sidebar> 16030 <div class="bp-sp__group"> 16031 <h3 class="bp-sp__group-title">Suggestions</h3><ul class="bp-sp__links" role="list"> 16032 <li><a class="bp-sp__link" href="/search?q=dresses" data-bp-search="dresses">dresses</a></li> 16033 <li><a class="bp-sp__link" href="/search?q=swimwear" data-bp-search="swimwear">swimwear</a></li> 16034 <li><a class="bp-sp__link" href="/search?q=tops" data-bp-search="tops">tops</a></li> 16035 <li><a class="bp-sp__link" href="/search?q=summer+dresses" data-bp-search="summer dresses">summer dresses</a></li> 16036 </ul> 16037 </div> 16038 16039 <div class="bp-sp__group"> 16040 <h3 class="bp-sp__group-title">Category</h3> 16041 <ul class="bp-sp__links" role="list"> 16042 <li><a class="bp-sp__link" href="/collections/dresses">Dresses</a></li> 16043 <li><a class="bp-sp__link" href="/collections/swimwear">Swimwear</a></li> 16044 <li><a class="bp-sp__link" href="/collections/tops">Tops</a></li> 16045 <li><a class="bp-sp__link" href="/collections/sale">Sale</a></li> 16046 <li><a class="bp-sp__link" href="/collections/new-arrivals">New Arrivals</a></li> 16047 </ul> 16048 </div> 16049 </aside> 16050 16051 <div class="bp-sp__products" id="bp-sp-products" data-br-products data-bp-track-list-name="Search Results" hidden></div> 16052 16053 </div> 16054</div> 16055</form> 16056 </div> 16057</bp-search-drawer> 16058 16059 16060 16061 16062 16063 16064 16065 <div id="shopify-section-bp-quick-drawer" class="shopify-section"> 16066 16067 16068 16069
16070<script 16071 src="//www.bostonproper.com/cdn/shop/t/1516/assets/gift-card-recipient-form.js?v=129634859299628245901790192827" 16072 type="module" 16073 fetchpriority="low" 16074></script>
16074 16075 16076<quick-add-dialog id="quick-add-dialog"> 16077 <dialog 16078 class="quick-add-modal bp-qd dialog-modal color-scheme-1" 16079 ref="dialog" 16080 scroll-lock 16081 aria-label="Quick view" 16082 > 16083 <button 16084 ref="closeButton" 16085 on:click="/closeDialog" 16086 class="button button-unstyled close-button quick-add-modal__close bp-qd__close" 16087 aria-label="Close dialog" 16088 ><svg aria-hidden="true" width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"> 16089 <path d="M12 2L2 12" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 16090 <path d="M12 12L2 2" stroke="currentColor" stroke-width="var(--icon-stroke-width)" stroke-linecap="round" stroke-linejoin="round"/> 16091</svg> 16092</button> 16093 16094 <div class="bp-qd__layout"> 16095 <aside class="bp-qd__media-slot" data-bp-qd-media-slot></aside> 16096 16097 <div class="bp-qd__main"> 16098 <div 16099 id="quick-add-modal-content" 16100 class="quick-add-modal__content bp-qd__body" 16101 ></div> 16102 16103 <footer class="bp-qd__cta-slot" data-bp-qd-cta-slot><p class="bp-qd__pay-in-4" data-bp-qd-pay-in-4> 16104 Pay in full or in 4 interest-free installments with 16105 <img class="bp-qd__shop-pay-mark" src="//www.bostonproper.com/cdn/shop/t/1516/assets/bp-shop-pay-logo.svg?v=68994295948588378181790192827" alt="Shop Pay" width="42" height="10" loading="lazy" style="width:auto;height:12px;"> 16106 </p> 16107 </footer> 16108 </div> 16109 </div> 16110 </dialog> 16111</quick-add-dialog> 16112 16113 16114 16115 16116 16117 16118</div> 16119 16120 16121
16122<script> 16123(function () { 16124 var SERVER_COLOR = ""; 16125 // Product scopes: main PDP + quick-add / quick-view drawer, so a title's 16126 // colour comes from ITS OWN product's label, not another on the page. 16127 var SCOPE_SEL = '.product-details, .product-information, #quick-add-modal-content, .quick-add-modal, .quick-add-modal__content, .bp-qd__body, dialog[open]'; 16128 function colorFor(el) { 16129 var scope = el.closest(SCOPE_SEL) || document; 16130 // Use the SELECTED colour, not the label text â bp-color-siblings mutates 16131 // [data-bp-active-color] on swatch HOVER (preview), which would make us 16132 // strip the wrong colour and flash the full title back. The active swatch 16133 // only changes on real selection / in-place swap, so it's stable. 16134 var active = scope.querySelector( 16135 '.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]' 16136 ); 16137 var sel = active && active.getAttribute('data-bp-color-name'); 16138 if (sel && sel.trim()) return sel.trim(); 16139 return SERVER_COLOR || ''; 16140 } 16141 function strip(title, color) { 16142 if (!title || !color) return title; 16143 var c = String(color).replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 16144 var re = new RegExp('\\s*[-\\u2013\\u2014]?\\s*' + c + '\\s*$', 'i'); 16145 var out = String(title).replace(re, '').trim(); 16146 return out || title; 16147 } 16148 function titleEls() { 16149 var sels = [ 16150 '.product-information h1', 16151 '.product-details h1', 16152 '[id^="ProductInformation"] h1', 16153 '.view-product-title a', 16154 '[ref="productTitleLink"] [role="heading"]', 16155 // Quick-add / quick-view drawer main title. The drawer's controller 16156 // (sections/bp-quick-drawer.liquid wrapTitleLink) wraps the morphed 16157 // <h1> text-block in an <a href="{pdp}">, so the colour lives in 16158 // "<h1 data-bp-qd-placed><a>Everyday Hoop Gold</a></h1>". apply() skips 16159 // container elements (the h1 now has an <a> child), so target the inner 16160 // <a> leaf directly. Also match the pre-wrap <h1> (text leaf, before the 16161 // controller runs) and the un-relocated node still in #quick-add-modal- 16162 // content, so whichever timing wins gets stripped. 16163 '.bp-qd__body h1 a', 16164 '.bp-qd__body h1', 16165 '#quick-add-modal-content h1 a', 16166 '#quick-add-modal-content h1' 16167 ]; 16168 var seen = [], out = []; 16169 sels.forEach(function (s) { 16170 document.querySelectorAll(s).forEach(function (el) { 16171 if (seen.indexOf(el) < 0) { seen.push(el); out.push(el); } 16172 }); 16173 }); 16174 return out; 16175 } 16176 function apply() { 16177 titleEls().forEach(function (t) { 16178 if (t.children && t.children.length > 0) return; // text-only leaves 16179 var color = colorFor(t); 16180 if (!color) return; 16181 if (t.getAttribute('data-bp-full-title') == null) { 16182 t.setAttribute('data-bp-full-title', (t.textContent || '').trim()); 16183 } 16184 var full = t.getAttribute('data-bp-full-title') || (t.textContent || '').trim(); 16185 var clean = strip(full, color); 16186 if (clean && clean !== (t.textContent || '').trim()) t.textContent = clean; 16187 }); 16188 } 16189 // Reveal the PDP title once we've had a pass at stripping it. bp-fonts.liquid 16190 // hides '.product-information h1 / .product-details h1' until this attribute 16191 // is set, so the full "â¦Colour" title never paints before it's cleaned. 16192 // Always reveal (even if there was no colour to strip) so a plain title is 16193 // never left hidden; the CSS also has a 1.2s fail-safe reveal. 16194 function revealTitles() { 16195 document 16196 .querySelectorAll('.product-information h1, .product-details h1') 16197 .forEach(function (h) { h.setAttribute('data-bp-title-ready', ''); }); 16198 } 16199 function boot() { 16200 apply(); 16201 revealTitles(); 16202 var tries = 0; 16203 var iv = setInterval(function () { apply(); if (++tries > 24) clearInterval(iv); }, 300); 16204 if (document.body) { 16205 var obs = new MutationObserver(function () { apply(); }); 16206 obs.observe(document.body, { childList: true, subtree: true, characterData: true }); 16207 setTimeout(function () { obs.disconnect(); }, 10000); 16208 } 16209 } 16210 if (document.readyState !== 'loading') boot(); 16211 else document.addEventListener('DOMContentLoaded', boot); 16212 // In-place colour swap / quick-view open re-render titles + labels. 16213 document.addEventListener('bp:pdp:swapped', boot); 16214 document.addEventListener('click', function (e) { 16215 if (e.target.closest && (e.target.closest('[data-bp-swatch]') || e.target.closest('[data-bp-card-qv-trigger]') || e.target.closest('.quick-add__button'))) 16216 setTimeout(boot, 120); 16217 }, true); 16218})(); 16219</script>
16219 16220 16221 16222 <dialog 16223 class="bp-size-chart" 16224 id="bp-size-chart-drawer" 16225 data-bp-size-chart-drawer 16226 aria-labelledby="bp-size-chart-title" 16227 > 16228 <div class="bp-size-chart__inner"> 16229 <header class="bp-size-chart__head"> 16230 <h2 id="bp-size-chart-title" class="bp-size-chart__title">Size Chart</h2> 16231 <button 16232 type="button" 16233 class="bp-size-chart__close" 16234 data-bp-size-chart-close 16235 aria-label="Close size chart" 16236 > 16237 <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> 16238 <line x1="18" y1="6" x2="6" y2="18"/> 16239 <line x1="6" y1="6" x2="18" y2="18"/> 16240 </svg> 16241 </button> 16242 </header> 16243 16244 <div class="bp-size-chart__tabs" role="tablist" aria-label="Size guide tabs"> 16245 <button 16246 type="button" 16247 class="bp-size-chart__tab is-active" 16248 role="tab" 16249 aria-selected="true" 16250 aria-controls="bp-size-chart-pane-chart" 16251 data-bp-size-chart-tab="chart" 16252 >Size Chart</button> 16253 <button 16254 type="button" 16255 class="bp-size-chart__tab" 16256 role="tab" 16257 aria-selected="false" 16258 aria-controls="bp-size-chart-pane-htm" 16259 data-bp-size-chart-tab="htm" 16260 >How to Measure</button> 16261 </div> 16262 16263 <div class="bp-size-chart__body"> 16264 <section 16265 id="bp-size-chart-pane-chart" 16266 class="bp-size-chart__pane is-active" 16267 role="tabpanel" 16268 data-bp-size-chart-pane="chart" 16269 ><p>Â </p> 16270<div class="modal-sizechart"><br></div> 16271<div class="flex-measuring-text size-measuring-section modal-sizechart" style="margin: 10px 0 10px;"> 16272<h4>Size Chart</h4> 16273<p class="hide-desktop">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> 16274<p>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.</p> 16275</div> 16276<div class="customerservice--sizecharts" style="margin-top: 10px;"> 16277<div class="modal-sizechart customerservice--sizecharts"> 16278<div class="flex-chart"> 16279<h3>Measurements</h3> 16280<table class="table table-bordered table-size-chart"> 16281<thead> 16282<tr> 16283<th colspan="2">US SIZE</th> 16284<th>BUST</th> 16285<th>WAIST</th> 16286<th>HIPS</th> 16287</tr> 16288</thead> 16289<tbody> 16290<tr> 16291<td class="sizechart-col1">XXS</td> 16292<td class="sizechart-colX">0</td> 16293<td class="sizechart-colX">31.5"</td> 16294<td class="sizechart-colX">24"</td> 16295<td class="sizechart-colX">34"</td> 16296</tr> 16297<tr> 16298<td class="sizechart-col1">XS</td> 16299<td class="sizechart-colX">2</td> 16300<td class="sizechart-colX">32.5"</td> 16301<td class="sizechart-colX">25"</td> 16302<td class="sizechart-colX">35"</td> 16303</tr> 16304<tr> 16305<td class="sizechart-col1">XS</td> 16306<td class="sizechart-colX">4</td> 16307<td class="sizechart-colX">33.5"</td> 16308<td class="sizechart-colX">26"</td> 16309<td class="sizechart-colX">36"</td> 16310</tr> 16311<tr> 16312<td class="sizechart-col1">S</td> 16313<td class="sizechart-colX">6</td> 16314<td class="sizechart-colX">34.5"</td> 16315<td class="sizechart-colX">27"</td> 16316<td class="sizechart-colX">37"</td> 16317</tr> 16318<tr> 16319<td class="sizechart-col1">S</td> 16320<td class="sizechart-colX">8</td> 16321<td class="sizechart-colX">35.5"</td> 16322<td class="sizechart-colX">28"</td> 16323<td class="sizechart-colX">38"</td> 16324</tr> 16325<tr> 16326<td class="sizechart-col1">M</td> 16327<td class="sizechart-colX">10</td> 16328<td class="sizechart-colX">36.5"</td> 16329<td class="sizechart-colX">29"</td> 16330<td class="sizechart-colX">39"</td> 16331</tr> 16332<tr> 16333<td class="sizechart-col1">M</td> 16334<td class="sizechart-colX">12</td> 16335<td class="sizechart-colX">38"</td> 16336<td class="sizechart-colX">30.5"</td> 16337<td class="sizechart-colX">40.5"</td> 16338</tr> 16339<tr> 16340<td class="sizechart-col1">L</td> 16341<td class="sizechart-colX">14</td> 16342<td class="sizechart-colX">39.5"</td> 16343<td class="sizechart-colX">32"</td> 16344<td class="sizechart-colX">42"</td> 16345</tr> 16346<tr> 16347<td class="sizechart-col1">L</td> 16348<td class="sizechart-colX">16</td> 16349<td class="sizechart-colX">41"</td> 16350<td class="sizechart-colX">33.5"</td> 16351<td class="sizechart-colX">43.5"</td> 16352</tr> 16353<tr> 16354<td class="sizechart-col1">XL</td> 16355<td class="sizechart-colX">18</td> 16356<td class="sizechart-colX">43"</td> 16357<td class="sizechart-colX">35.5"</td> 16358<td class="sizechart-colX">45.5"</td> 16359</tr> 16360</tbody> 16361</table> 16362</div> 16363<div class="flex-chart"> 16364<h3>Dress & Skirt Lengths</h3> 16365<table class="table table-bordered table-size-chart"> 16366<thead> 16367<tr> 16368<th>DESCRIPTION</th> 16369<th>DRESS</th> 16370<th>SKIRT</th> 16371</tr> 16372</thead> 16373<tbody> 16374<tr> 16375<td class="sizechart-colX">Mid thigh</td> 16376<td class="sizechart-colX">35"</td> 16377<td class="sizechart-colX">18"</td> 16378</tr> 16379<tr> 16380<td class="sizechart-colX">Above the knee</td> 16381<td class="sizechart-colX">37"</td> 16382<td class="sizechart-colX">20"</td> 16383</tr> 16384<tr> 16385<td class="sizechart-colX">At the knee</td> 16386<td class="sizechart-colX">38" -39"</td> 16387<td class="sizechart-colX">22"</td> 16388</tr> 16389<tr> 16390<td class="sizechart-colX">Below the knee</td> 16391<td class="sizechart-colX">40" - 41"</td> 16392<td class="sizechart-colX">23" - 24"</td> 16393</tr> 16394<tr> 16395<td class="sizechart-colX">Midi</td> 16396<td class="sizechart-colX">44" - 45"</td> 16397<td class="sizechart-colX">28"</td> 16398</tr> 16399<tr> 16400<td class="sizechart-colX">Ankle</td> 16401<td class="sizechart-colX">54" - 55"</td> 16402<td class="sizechart-colX">38"</td> 16403</tr> 16404<tr> 16405<td class="sizechart-colX">Maxi</td> 16406<td class="sizechart-colX">57" - 58"</td> 16407<td class="sizechart-colX">40"</td> 16408</tr> 16409</tbody> 16410</table> 16411</div> 16412</div> 16413<div style="display: none;" class="modal-measuring"> 16414<div> 16415<div class="flex-measuring-text" style="margin-top: 0px;"> 16416<h4>Measuring For The Perfect Size</h4> 16417<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> 16418</div> 16419<div class="flex-measuring"> 16420<div class="customerservice--sizecharts-model"><img src="https://media.bostonproper.com/i/bostonproper/silhouette_v2-01"></div> 16421<div> 16422<ul> 16423<li> 16424<strong>Bust:</strong> Measure around the fullest part of the bust, arms relaxed at your side.</li> 16425<li> 16426<strong>Waist:</strong> Measure around waist smallest point with tape slightly loosened for c
16426omfort.</li> 16427<li> 16428<strong>Hips:</strong> With feet together, measure around the fullest part of hip and rear, usually 7" - 9" below the waist.</li> 16429<li> 16430<strong>Inseam:</strong> Measure a similar style of pants that fit well. Measure from the crotch seam to the hem.</li> 16431<li> 16432<strong>Length:</strong> Lengths are measured at the front, starting from where the shoulder meets the neck.</li> 16433</ul> 16434</div> 16435</div> 16436</div> 16437</div> 16438</div> 16439<div> 16440<div> 16441<p>For additional information, please click on full sizing details below or contact the Customer Care team with any questions you may have.</p> 16442</div> 16443<div class="richtext-cta-container richtext-cta-container--small"> 16444<div class="richtext-cta-container"> 16445<a style="margin-right: 20px;" href="/pages/size-chart" class="button button--secondary richtext-cta__button"><em class="blog-title"><b>Full a SIZING DETAILS</b></em></a> <a href="/pages/contact-us" class="button button--secondary richtext-cta__button"><em class="blog-title"><b>CONTACT CUSTOMER CARE</b></em></a> 16446</div> 16447</div> 16448</div> 16449</section> 16450 16451 <section 16452 id="bp-size-chart-pane-htm" 16453 class="bp-size-chart__pane bp-size-chart__pane--htm" 16454 role="tabpanel" 16455 data-bp-size-chart-pane="htm" 16456 hidden 16457 ><figure class="bp-size-chart__measure-fig"> 16458 <img class="bp-size-chart__measure-img" 16459 src="//www.bostonproper.com/cdn/shop/t/1516/assets/bp-size-chart-measure.png?v=70142022341375340491790192827" 16460 alt="Measurement diagram showing bust, waist, hips, and inseam points on a model"> 16461 </figure><h3>Measuring for the Perfect Size</h3> 16462<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> 16463<ul> 16464<li> 16465<strong>Bust:</strong> Measure around the fullest part of the bust, arms relaxed at your side.</li> 16466<li> 16467<strong>Waist:</strong> Measure around waist smallest point with tape slightly loosened for comfort.</li> 16468<li> 16469<strong>Hips:</strong> With feet together, measure around the fullest part of hip and rear, usually 7" - 9" below the waist.</li> 16470<li> 16471<strong>Inseam:</strong> Measure a similar style of pants that fit well. Measure from the crotch seam to the hem.</li> 16472<li> 16473<strong>Length:</strong> Lengths are measured at the front, starting from where the shoulder meets the neck.</li> 16474</ul> 16475<p><a class="btn" href="/pages/size-chart">Full Sizing Details</a></p> 16476<p><a class="btn" href="/pages/contact-us">Contact Customer Care</a></p> 16477</section> 16478 </div> 16479 </div> 16480 </dialog> 16481 16482
16482<script> 16483 (function () { 16484 const dialog = document.getElementById('bp-size-chart-drawer'); 16485 if (!dialog) return; 16486 16487 const openDialog = () => { 16488 try { 16489 if (typeof dialog.showModal === 'function') dialog.showModal(); 16490 else dialog.setAttribute('open', ''); 16491 } catch (_) { 16492 dialog.setAttribute('open', ''); 16493 } 16494 document.body.classList.add('bp-size-chart-open'); 16495 }; 16496 const closeDialog = () => { 16497 try { if (typeof dialog.close === 'function') dialog.close(); else dialog.removeAttribute('open'); } 16498 catch (_) { dialog.removeAttribute('open'); } 16499 document.body.classList.remove('bp-size-chart-open'); 16500 }; 16501 16502 document.addEventListener('click', (e) => { 16503 const t = e.target.closest('[data-bp-size-chart-open]'); 16504 if (!t) return; 16505 e.preventDefault(); 16506 openDialog(); 16507 }); 16508 16509 dialog.addEventListener('click', (e) => { 16510 if (e.target.closest('[data-bp-size-chart-close]')) { closeDialog(); return; } 16511 const tab = e.target.closest('[data-bp-size-chart-tab]'); 16512 if (tab) { 16513 const key = tab.getAttribute('data-bp-size-chart-tab'); 16514 dialog.querySelectorAll('[data-bp-size-chart-tab]').forEach((t) => { 16515 const active = t === tab; 16516 t.classList.toggle('is-active', active); 16517 t.setAttribute('aria-selected', active ? 'true' : 'false'); 16518 }); 16519 dialog.querySelectorAll('[data-bp-size-chart-pane]').forEach((p) => { 16520 const match = p.getAttribute('data-bp-size-chart-pane') === key; 16521 p.classList.toggle('is-active', match); 16522 if (match) p.removeAttribute('hidden'); 16523 else p.setAttribute('hidden', ''); 16524 }); 16525 return; 16526 } 16527 if (e.target === dialog) closeDialog(); 16528 }); 16529 dialog.addEventListener('close', () => { 16530 document.body.classList.remove('bp-size-chart-open'); 16531 }); 16532 })(); 16533 </script>
16533 16534 16535 <style> 16536 dialog.bp-size-chart { 16537 margin: 0; 16538 padding: 0; 16539 border: 0; 16540 max-width: none; 16541 max-height: none; 16542 width: min(640px, 100vw); 16543 height: 100dvh; 16544 inset: 0 0 0 auto; 16545 background: var(--bp-color-cta-text, #FDFFFA); 16546 color: var(--bp-color-text, #171609); 16547 box-shadow: -16px 0 48px rgba(0, 0, 0, 0.12); 16548 overflow: hidden; 16549 transform: translateX(100%); 16550 transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1); 16551 } 16552 dialog.bp-size-chart[open] { transform: translateX(0); } 16553 dialog.bp-size-chart::backdrop { 16554 background: rgba(0, 0, 0, 0.32); 16555 animation: bp-size-chart-fade 0.28s ease forwards; 16556 } 16557 @keyframes bp-size-chart-fade { from { opacity: 0; } to { opacity: 1; } } 16558 body.bp-size-chart-open { overflow: hidden; } 16559 16560 .bp-size-chart__inner { 16561 display: flex; 16562 flex-direction: column; 16563 height: 100%; 16564 width: 100%; 16565 } 16566 .bp-size-chart__head { 16567 flex: 0 0 auto; 16568 display: flex; 16569 align-items: center; 16570 justify-content: space-between; 16571 gap: 16px; 16572 padding: 20px 24px; 16573 border-bottom: 1px solid rgba(23, 22, 9, 0.08); 16574 } 16575 @media (max-width: 767px) { 16576 .bp-size-chart__head { padding: 18px 20px; } 16577 .bp-size-chart__title { font-size: 22px; } 16578 } 16579 .bp-size-chart__title { 16580 margin: 0; 16581 color: inherit; 16582 font-family: var(--bp-font-display); 16583 font-size: 28px; 16584 font-weight: 300; 16585 line-height: 120%; 16586 letter-spacing: -0.56px; 16587 } 16588 .bp-size-chart__close { 16589 background: transparent; 16590 border: 0; 16591 padding: 8px; 16592 cursor: pointer; 16593 color: inherit; 16594 line-height: 0; 16595 border-radius: 50%; 16596 } 16597 .bp-size-chart__close:hover { background: rgba(23, 22, 9, 0.06); } 16598 16599 .bp-size-chart__tabs { 16600 flex: 0 0 auto; 16601 display: flex; 16602 gap: 0; 16603 padding: 0; 16604 border-bottom: 1px solid rgba(23, 22, 9, 0.08); 16605 } 16606 .bp-size-chart__tab { 16607 flex: 1 1 0; 16608 background: transparent; 16609 border: 0; 16610 padding: 12px 8px 14px; 16611 cursor: pointer; 16612 font-family: var(--bp-font-body); 16613 font-size: 14px; 16614 font-weight: 500; 16615 line-height: 145%; 16616 letter-spacing: -0.14px; 16617 color: var(--bp-color-body-copy, #74736B); 16618 text-align: center; 16619 position: relative; 16620 transition: color 0.15s ease; 16621 } 16622 .bp-size-chart__tab.is-active { 16623 color: var(--bp-color-text, #171609); 16624 font-weight: 700; 16625 } 16626 .bp-size-chart__tab.is-active::after { 16627 content: ''; 16628 position: absolute; 16629 left: 0; 16630 right: 0; 16631 bottom: -1px; 16632 height: 1.5px; 16633 background: var(--bp-color-text, #171609); 16634 } 16635 .bp-size-chart__tab:hover:not(.is-active) { color: var(--bp-color-text, #171609); } 16636 16637 .bp-size-chart__pane[hidden] { display: none; } 16638 16639 .bp-size-chart__body { 16640 flex: 1 1 0; 16641 min-height: 0; 16642 padding: 24px; 16643 overflow-y: auto; 16644 overflow-x: hidden; 16645 font-family: var(--bp-font-body); 16646 font-size: 14px; 16647 line-height: 145%; 16648 letter-spacing: -0.14px; 16649 color: var(--bp-color-text, #171609); 16650 box-sizing: border-box; 16651 } 16652 .bp-size-chart__body *, 16653 .bp-size-chart__body *::before, 16654 .bp-size-chart__body *::after { 16655 box-sizing: border-box; 16656 max-width: 100%; 16657 } 16658 .bp-size-chart__body img { height: auto; } 16659 @media (max-width: 767px) { 16660 .bp-size-chart__body { padding: 20px; } 16661 } 16662 16663 /* Subheaders inside resolved page content. Body-font / 660 / 16664 uppercase per Figma â admins can mark these up as h2/h3/h4 16665 in the Shopify page editor and the drawer styles them 16666 consistently. */ 16667 .bp-size-chart__body h2, 16668 .bp-size-chart__body h3, 16669 .bp-size-chart__body h4 { 16670 margin: 24px 0 12px; 16671 font-family: var(--bp-font-body); 16672 font-size: 13px; 16673 font-weight: 700; 16674 line-height: 145%; 16675 letter-spacing: 0.06em; 16676 text-transform: uppercase; 16677 color: var(--bp-color-text, #171609); 16678 } 16679 .bp-size-chart__body > section > :first-child { margin-top: 0; } 16680 16681 .bp-size-chart__body p { margin: 0 0 12px; } 16682 .bp-size-chart__body ul, 16683 .bp-size-chart__body ol { 16684 margin: 8px 0 16px; 16685 padding-left: 20px; 16686 } 16687 .bp-size-chart__body li { 16688 margin: 0 0 8px; 16689 padding-left: 4px; 16690 } 16691 .bp-size-chart__body li::marker { color: var(--bp-color-text, #171609); } 16692 16693 /* Tables â !important on width so a page that ships table with 16694 inline width attribute (or wrapped in <center>) still fills 16695 the drawer. center-aligned cells match the Figma. */ 16696 .bp-size-chart__body table { 16697 width: 100% !important; 16698 max-width: 100% !important; 16699 min-width: 0 !important; 16700 border-collapse: collapse; 16701 margin: 12px 0 24px; 16702 font-family: var(--bp-font-body); 16703 display: table !important; 16704 } 16705 .bp-size-chart__body th, 16706 .bp-size-chart__body td { 16707 padding: 12px 14px; 16708 text-align: center; 16709 border-bottom: 1px solid rgba(23, 22, 9, 0.08); 16710 font-size: 14px; 16711 line-height: 145%; 16712 letter-spacing: -0.14px; 16713 color: var(--bp-color-text, #171609); 16714 } 16715 .bp-size-chart__body th { 16716 font-weight: 700; 16717 text-transform: uppercase; 16718 letter-spacing: 0.06em; 16719 font-size: 12px; 16720 background: var(--bp-color-bg-cream, #F7F6EA); 16721 border-bottom: 1px solid rgba(23, 22, 9, 0.12); 16722 } 16723 16724 /* How-to-Measure pane â figure floats left, list flows beside. 16725 Stacks on mobile. */ 16726 .bp-size-chart__pane--htm .bp-size-chart__measure-fig { 16727 margin: 0 20px 16px 0; 16728 float: left; 16729 shape-outside: margin-box; 16730 width: 42%; 16731 max-width: 220px; 16732 } 16733 .bp-size-chart__pane--htm .bp-size-chart__measure-img { 16734 display: block; 16735 width: 100%; 16736 height: auto; 16737 } 16738 .bp-size-chart__pane--htm > :first-child:not(figure) { margin-top: 0; } 16739 @media (max-width: 599px) { 16740 .bp-size-chart__pane--htm .bp-size-chart__measure-fig { 16741 float: none; 16742 width: 100%; 16743 max-width: 280px; 16744 margin: 12px auto 16px; 16745 } 16746 } 16747 16748 /* Tame the Shopify-Page admin "FULL SIZING DETAILS" + "CONTACT 16749 CUSTOMER CARE" anchors â Figma renders them as outlined 16750 buttons (white bg, dark border, dark text), full-width, 16751 stacked, hover flips to filled dark. */ 16752 .bp-size-chart__body a.btn, 16753 .bp-size-chart__body a.button, 16754 .bp-size-chart__body a[class*="button"], 16755 .bp-size-chart__body a[href*="full-sizing"], 16756 .bp-size-chart__body a[href*="customer-care"], 16757 .bp-size-chart__body a[href*="customer-service"], 16758 .bp-size-chart__body button { 16759 display: flex !important; 16760 align-items: center !important; 16761 justify-content: center !important; 16762 width: 100% !important; 16763 max-width: 100% !important; 16764 min-height: 48px !important; 16765 padding: 12px 18px !important; 16766 margin: 10px 0 0 !important; 16767 font-family: var(--bp-font-body) !important; 16768 font-size: 14px !important; 16769 font-weight: 500 !important; 16770 letter-spacing: -0.14px !important; 16771 line-height: 145% !important; 16772 text-transform: none !important; 16773 font-style: normal !important; 16774 border-radius: 0 !important; 16775 background: transparent !important; 16776 color: var(--bp-color-text, #171609) !important; 16777 border: 1px solid var(--bp-color-text, #171609) !important; 16778 text-decoration: none !important; 16779 white-space: normal !important; 16780 transition: background-color 0.15s ease, color 0.15s ease; 16781 } 16782 .bp-size-chart__body a.btn:hover, 16783 .bp-size-chart__body a.button:hover, 16784 .bp-size-chart__body a[class*="button"]:hover, 16785 .bp-size-chart__body a[href*="full-sizing"]:hover, 16786 .bp-size-chart__body a[href*="customer-care"]:hover, 16787 .bp-size-chart__body a[href*="customer-service"]:hover, 16788 .bp-size-chart__body button:hover { 16789 background: var(--bp-color-text, #171609) !important; 16790 color: var(--bp-color-cta-text, #FDFFFA) !important; 16791 } 16792 16793 @media (prefers-reduced-motion: reduce) { 16794 dialog.bp-size-chart { transition: none; } 16795 } 16796 </style> 16797 16798 <dialog 16799 class="bp-notify" 16800 id="bp-notify-drawer" 16801 data-bp-notify-drawer 16802 data-klaviyo-company="VZrTML" 16803 data-klaviyo-company-dev="WgMT43" 16804 data-klaviyo-list="WFEsDC" 16805 data-klaviyo-list-dev="VDxyUk" 16806 aria-labelledby="bp-notify-title" 16807> 16808 <form class="bp-notify__inner" data-bp-notify-form> 16809 <button 16810 type="button" 16811 class="bp-notify__close" 16812 data-bp-notify-close 16813 aria-label="Close" 16814 > 16815 <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> 16816 <line x1="18" y1="6" x2="6" y2="18"/> 16817 <line x1="6" y1="6" x2="18" y2="18"/> 16818 </svg> 16819 </button><div class="bp-notify__body" data-bp-notify-state="form"> 16820 <h2 id="bp-notify-title" class="bp-notify__title">Join the Waitlist</h2> 16821 <p class="bp-notify__copy">Be first in line if your size makes a comeback.</p> 16822 16823 <label class="bp-notify__field">
16824 <span class="bp-notify__label">Email address</span> 16825 <input 16826 type="email" 16827 required 16828 autocomplete="email" 16829 data-bp-notify-email 16830 id="bp-notify-email" 16831 aria-describedby="bp-notify-error" 16832 > 16833 </label> 16834 16835 <label class="bp-notify__opt"> 16836 <input type="checkbox" data-bp-notify-optin> 16837 <span>Add me to your email list.</span> 16838 </label> 16839 16840 <button type="submit" class="bp-notify__submit" data-bp-notify-submit> 16841 Notify me when it's back 16842 </button> 16843 16844 <p class="bp-notify__legal"> 16845 By joining the waitlist, you accept our 16846 <a href="/policies/terms-of-service">Terms</a> 16847 & 16848 <a href="/policies/privacy-policy">Privacy policy</a>. 16849 </p> 16850 16851 <p class="bp-notify__error" id="bp-notify-error" data-bp-notify-error role="alert" hidden></p> 16852 </div><div class="bp-notify__body bp-notify__body--success" data-bp-notify-state="success" role="status" hidden> 16853 <h3 class="bp-notify__success-title">You're on the List</h3> 16854 <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> 16855 <button type="button" class="bp-notify__submit bp-notify__submit--success" data-bp-notify-close>Keep Shopping</button> 16856 </div> 16857 </form> 16858</dialog> 16859
16860<script> 16861 (function () { 16862 const LOG = '[bp-notify]'; 16863 const dialog = document.getElementById('bp-notify-drawer'); 16864 if (!dialog) return; 16865 16866 const form = dialog.querySelector('[data-bp-notify-form]'); 16867 const emailInput = dialog.querySelector('[data-bp-notify-email]'); 16868 const optinInput = dialog.querySelector('[data-bp-notify-optin]'); 16869 const errorEl = dialog.querySelector('[data-bp-notify-error]'); 16870 const submitBtn = dialog.querySelector('[data-bp-notify-submit]'); 16871 const formState = dialog.querySelector('[data-bp-notify-state="form"]'); 16872 const successState = dialog.querySelector('[data-bp-notify-state="success"]'); 16873 // Prod vs dev Klaviyo account is decided by the LIVE browser host, not 16874 // server-side: prod + staging share one Shopify store (identical 16875 // shop.domain), so only the URL the shopper is actually on distinguishes 16876 // them. Mirrors Atlas's isProd (src/v2/scripts/utils.js) â exact host 16877 // allowlist, top-frame host, localhost via "127". staging.bostonproper.com 16878 // is NOT prod, so it uses the dev company (WgMT43) and stops 404-ing. 16879 let bpHost = ''; 16880 try { bpHost = window.top.location.host; } catch (_) { bpHost = window.location.host; } 16881 const isProd = bpHost === 'bostonproper.com' 16882 || bpHost === 'www.bostonproper.com' 16883 || bpHost === 'bostonproper.myshopify.com' 16884 || bpHost.includes('127'); 16885 const company = isProd ? dialog.dataset.klaviyoCompany : (dialog.dataset.klaviyoCompanyDev || dialog.dataset.klaviyoCompany); 16886 const listId = isProd ? dialog.dataset.klaviyoList : (dialog.dataset.klaviyoListDev || dialog.dataset.klaviyoList); 16887 16888 let currentVariantId = null; 16889 16890 const openDialog = (variantId) => { 16891 currentVariantId = variantId || window.bpCurrentVariantId || null; 16892 console.log(LOG, 'open, variantId=', currentVariantId); 16893 resetState(); 16894 try { dialog.showModal(); } catch (_) { dialog.setAttribute('open', ''); } 16895 document.body.classList.add('bp-notify-open'); 16896 if (emailInput) setTimeout(() => emailInput.focus(), 60); 16897 }; 16898 const closeDialog = () => { 16899 try { dialog.close(); } catch (_) { dialog.removeAttribute('open'); } 16900 document.body.classList.remove('bp-notify-open'); 16901 }; 16902 const resetState = () => { 16903 if (emailInput) emailInput.value = ''; 16904 if (optinInput) optinInput.checked = false; 16905 if (errorEl) { errorEl.hidden = true; errorEl.textContent = ''; } 16906 if (formState) formState.hidden = false; 16907 if (successState) successState.hidden = true; 16908 if (submitBtn) { submitBtn.disabled = false; submitBtn.textContent = 'Notify Me'; } 16909 }; 16910 16911 const klaviyoHeaders = { 16912 accept: 'application/vnd.api+json', 16913 revision: '2025-07-15', 16914 'content-type': 'application/vnd.api+json', 16915 }; 16916 16917 const submitBackInStock = async (email, variantId) => { 16918 const url = `https://a.klaviyo.com/client/back-in-stock-subscriptions/?company_id=${company}`; 16919 const body = JSON.stringify({ 16920 data: { 16921 type: 'back-in-stock-subscription', 16922 attributes: { 16923 channels: ['EMAIL'], 16924 profile: { data: { type: 'profile', attributes: { email } } }, 16925 }, 16926 relationships: { 16927 variant: { data: { type: 'catalog-variant', id: `$shopify:::$default:::${variantId}` } }, 16928 }, 16929 }, 16930 }); 16931 return fetch(url, { method: 'POST', headers: klaviyoHeaders, body }); 16932 }; 16933 const submitNewsletter = async (email) => { 16934 const url = `https://a.klaviyo.com/client/subscriptions/?company_id=${company}`; 16935 const body = JSON.stringify({ 16936 data: { 16937 type: 'subscription', 16938 attributes: { 16939 profile: { data: { type: 'profile', attributes: { email } } }, 16940 custom_source: 'Back-in-Stock Waitlist Modal', 16941 }, 16942 relationships: { 16943 list: { data: { type: 'list', id: listId } }, 16944 }, 16945 }, 16946 }); 16947 return fetch(url, { method: 'POST', headers: klaviyoHeaders, body }); 16948 }; 16949 16950 // --- delegated open --- 16951 document.addEventListener('click', (e) => { 16952 const t = e.target.closest('[data-bp-notify-open]'); 16953 if (!t) return; 16954 e.preventDefault(); 16955 const vid = t.getAttribute('data-bp-notify-variant-id'); 16956 openDialog(vid); 16957 }); 16958 16959 // --- close --- 16960 dialog.addEventListener('click', (e) => { 16961 if (e.target.closest('[data-bp-notify-close]')) { closeDialog(); return; } 16962 if (e.target === dialog) closeDialog(); 16963 }); 16964 dialog.addEventListener('close', () => document.body.classList.remove('bp-notify-open')); 16965 16966 // --- submit --- 16967 form.addEventListener('submit', async (e) => { 16968 e.preventDefault(); 16969 const email = (emailInput.value || '').trim(); 16970 if (!email) return; 16971 if (!currentVariantId) { 16972 errorEl.textContent = 'We could not detect which variant to subscribe you to. Please re-select your size and try again.'; 16973 errorEl.hidden = false;
16974 return; 16975 } 16976 submitBtn.disabled = true; 16977 submitBtn.textContent = 'Submittingâ¦'; 16978 errorEl.hidden = true; 16979 try { 16980 const res = await submitBackInStock(email, currentVariantId); 16981 console.log(LOG, 'BIS response', res.status); 16982 if (res.status === 202 || res.ok) { 16983 if (optinInput && optinInput.checked) { 16984 try { await submitNewsletter(email); } catch (e2) { console.error(LOG, 'newsletter error', e2); } 16985 } 16986 if (formState) formState.hidden = true; 16987 if (successState) successState.hidden = false; 16988 } else { 16989 errorEl.textContent = 'Something went wrong. Please try again.'; 16990 errorEl.hidden = false; 16991 } 16992 } catch (err) { 16993 console.error(LOG, 'BIS error', err); 16994 errorEl.textContent = 'Network error. Please try again.'; 16995 errorEl.hidden = false; 16996 } finally { 16997 submitBtn.disabled = false; 16998 submitBtn.textContent = "Notify me when it's back"; 16999 } 17000 }); 17001 })(); 17002</script>
17002 17003 17004<style> 17005 /* Figma reference: centered modal (not right-side drawer), cream 17006 background, Signifier serif heading, underline-only input, dark 17007 full-width CTA, small legal copy with inline links. */ 17008 dialog.bp-notify { 17009 margin: auto; 17010 padding: 0; 17011 border: 0; 17012 width: min(560px, calc(100vw - 32px)); 17013 max-width: 560px; 17014 max-height: calc(100dvh - 32px); 17015 background: var(--bp-color-cta-text, #FDFFFA); 17016 color: var(--bp-color-text, #171609); 17017 box-shadow: 0 24px 64px rgba(0, 0, 0, 0.18); 17018 box-sizing: border-box; 17019 opacity: 0; 17020 transform: scale(0.96); 17021 transition: opacity 0.2s ease, transform 0.2s ease; 17022 } 17023 dialog.bp-notify[open] { opacity: 1; transform: scale(1); } 17024 dialog.bp-notify::backdrop { background: rgba(0, 0, 0, 0.4); } 17025 body.bp-notify-open { overflow: hidden; } 17026 17027 .bp-notify__inner { 17028 position: relative; 17029 padding: 56px 56px 40px; 17030 } 17031 @media (max-width: 749px) { 17032 .bp-notify__inner { padding: 48px 24px 32px; } 17033 } 17034 17035 .bp-notify__close { 17036 position: absolute; 17037 top: 16px; 17038 right: 16px; 17039 background: transparent; 17040 border: 0; 17041 padding: 8px; 17042 cursor: pointer; 17043 color: var(--bp-color-text); 17044 line-height: 0; 17045 border-radius: 50%; 17046 transition: background 0.15s ease; 17047 } 17048 .bp-notify__close:hover { background: rgba(23, 22, 9, 0.06); } 17049 17050 .bp-notify__body { 17051 display: flex; 17052 flex-direction: column; 17053 gap: 16px; 17054 font-family: var(--bp-font-body); 17055 font-size: 14px; 17056 line-height: 145%; 17057 text-align: center; 17058 } 17059 /* `.bp-notify__body { display: flex }` has the same specificity as the UA 17060 `[hidden] { display: none }` rule but is authored later, so it won the 17061 cascade and the success state showed ALONGSIDE the form (both visible at 17062 once â QA 7/21). Re-assert display:none for the hidden state so only the 17063 active state (form, then success after submit) shows. */ 17064 .bp-notify__body[hidden] { display: none; } 17065 .bp-notify__body--success { gap: 20px; align-items: center; } 17066 17067 .bp-notify__title { 17068 margin: 0; 17069 font-family: var(--bp-font-display); 17070 font-size: 32px; 17071 font-weight: 300; 17072 line-height: 120%; 17073 letter-spacing: -0.64px; 17074 color: var(--bp-color-text); 17075 } 17076 .bp-notify__copy { 17077 margin: 0 0 8px; 17078 color: var(--bp-color-body-copy, #74736B); 17079 font-size: 14px; 17080 line-height: 145%; 17081 } 17082 17083 /* Underline-only input â matches Figma. */ 17084 .bp-notify__field { display: flex; flex-direction: column; gap: 4px; text-align: left; margin-top: 8px; } 17085 .bp-notify__label { 17086 font-size: 14px; 17087 font-weight: 500; 17088 color: var(--bp-color-text); 17089 letter-spacing: -0.14px; 17090 } 17091 .bp-notify__field input[type="email"] { 17092 width: 100%; 17093 box-sizing: border-box; 17094 border: 0; 17095 border-bottom: 1px solid rgba(23, 22, 9, 0.32); 17096 background: transparent; 17097 padding: 8px 0; 17098 font-family: var(--bp-font-body); 17099 font-size: 14px; 17100 color: var(--bp-color-text); 17101 border-radius: 0; 17102 } 17103 .bp-notify__field input[type="email"]:focus { 17104 outline: none; 17105 border-bottom-color: var(--bp-color-text); 17106 } 17107 .bp-notify__field input[type="email"]:focus-visible { 17108 outline: 2px solid var(--bp-color-text); 17109 outline-offset: 2px; 17110 } 17111 17112 .bp-notify__opt { 17113 display: inline-flex; 17114 align-items: center; 17115 gap: 10px; 17116 cursor: pointer; 17117 text-align: left; 17118 margin-top: 4px; 17119 font-size: 14px; 17120 } 17121 .bp-notify__opt input[type="checkbox"] { 17122 width: 18px; 17123 height: 18px; 17124 accent-color: var(--bp-color-text); 17125 flex: 0 0 auto; 17126 } 17127 17128 .bp-notify__submit { 17129 width: 100%; 17130 background: var(--bp-color-text, #171609); 17131 color: var(--bp-color-cta-text, #FDFFFA); 17132 border: 0; 17133 height: 52px; 17134 padding: 0 24px; 17135 font-family: var(--bp-font-body); 17136 font-size: 17px; 17137 font-weight: 500; 17138 line-height: normal; 17139 letter-spacing: -0.17px; 17140 cursor: pointer; 17141 margin-top: 8px; 17142 transition: opacity 0.2s ease; 17143 } 17144 .bp-notify__submit:hover { opacity: 0.85; } 17145 .bp-notify__submit[disabled] { opacity: 0.55; cursor: wait; } 17146 17147 /* Success-state submit is sized to content (not full-width) â the 17148 "Keep Shopping" CTA in the Figma is a centered fit-content 17149 button, not an edge-to-edge primary. */ 17150 .bp-notify__submit--success { 17151 width: auto; 17152 padding: 0 32px; 17153 margin-top: 4px; 17154 } 17155 17156 .bp-notify__legal { 17157 margin: 4px 0 0; 17158 font-size: 12px; 17159 color: var(--bp-color-body-copy, #74736B); 17160 line-height: 145%; 17161 letter-spacing: -0.12px; 17162 } 17163 .bp-notify__legal a { 17164 color: var(--bp-color-text); 17165 text-decoration: underline; 17166 text-underline-offset: 2px; 17167 } 17168 17169 .bp-notify__error {
17170 margin: 0; 17171 color: var(--bp-color-promo, #B5341B); 17172 font-size: 13px; 17173 } 17174 .bp-notify__success-title { 17175 margin: 0; 17176 font-family: var(--bp-font-display); 17177 font-size: 32px; 17178 font-weight: 300; 17179 letter-spacing: -0.64px; 17180 line-height: 120%; 17181 color: var(--bp-color-text); 17182 } 17183 .bp-notify__success-copy { 17184 margin: 0; 17185 color: var(--bp-color-body-copy, #74736B); 17186 font-size: 14px; 17187 line-height: 145%; 17188 text-align: center; 17189 } 17190</style> 17191 17192 17193
17194<script> 17195 (function () { 17196 'use strict'; 17197 if (window.__bpCartCtlWired) return; 17198 window.__bpCartCtlWired = true; 17199 17200 const AMPLIENCE_BASE = 17201 (window.shop && window.shop.themeSettings && window.shop.themeSettings.amplience_cdn_base_url) || 17202 "https:\/\/media.bostonproper.com"; 17203 const STYLITICS_USERNAME = 'bostonproper'; 17204 const MAX_CARDS = 8; 17205 const ENDPOINT = 'https://widget-api.stylitics.com/api/outfits'; 17206 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>'; 17207 17208 // ----- Helpers ----- 17209 function inferPrefix(rootEl) { 17210 const root = rootEl.closest('[data-bp-ctl]'); 17211 if (!root) return 'bp-cart-drawer'; 17212 const match = Array.from(root.classList).find((c) => /__ctl$/.test(c)); 17213 return match ? match.replace(/__ctl$/, '') : 'bp-cart-drawer'; 17214 } 17215 17216 function escape(s) { 17217 return String(s || '').replace(/[&<>"']/g, (c) => ({ 17218 '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' 17219 }[c])); 17220 } 17221 17222 // Scroll-progress indicator â same thin-bar-with-thumb pattern as 17223 // bp-product-carousel's BpProductCarousel.updateArrows(). Wired once 17224 // per track (idempotent) and re-measured any time the track's content 17225 // changes, since a fresh render can change scrollWidth. 17226 function wireIndicator(track) { 17227 const root = track.closest('[data-bp-ctl]'); 17228 const indicator = root && root.querySelector('[data-bp-ctl-indicator]'); 17229 if (!indicator) return null; 17230 if (!track.__bpIndicatorUpdate) { 17231 const update = () => { 17232 const { scrollLeft, scrollWidth, clientWidth } = track; 17233 if (scrollWidth <= clientWidth + 1) { 17234 indicator.style.display = 'none'; 17235 return; 17236 } 17237 indicator.style.display = ''; 17238 const thumbW = (clientWidth / scrollWidth) * 100; 17239 const overflow = scrollWidth - clientWidth; 17240 const thumbX = overflow > 0 ? scrollLeft / overflow : 0; 17241 indicator.style.setProperty('--bp-ctl-thumb-w', thumbW + '%'); 17242 indicator.style.setProperty('--bp-ctl-thumb-x', thumbX); 17243 }; 17244 track.__bpIndicatorUpdate = update; 17245 track.addEventListener('scroll', update, { passive: true }); 17246 window.addEventListener('resize', update); 17247 } 17248 return track.__bpIndicatorUpdate; 17249 } 17250 17251 // Stylitics serves prices as currency-formatted strings.
17252 // "$25.00" â "$25" (drop the .00) so it lines up with the rest of 17253 // the BP cart typography. 17254 function formatPrice(s) { 17255 if (!s) return ''; 17256 return String(s).replace('.00', ''); 17257 } 17258 17259 function itemImage(item) { 17260 // Atlas's pickItemImage: Shopify Collective items use their raw 17261 // image_url (no Amplience asset); everyone else uses the 17262 // {amplience}/i/bostonproper/{remote_id}_2 SET shot. 17263 const isCollective = item && item.other_client_item_ids && item.other_client_item_ids.shopify_collective; 17264 const remoteId = item && item.remote_id; 17265 if (isCollective || !remoteId) return (item && item.image_url) || ''; 17266 return `${AMPLIENCE_BASE}/i/bostonproper/${remoteId}_2?fmt=auto&w=484`; 17267 } 17268 17269 function itemUrl(item) { 17270 const raw = (item && item.affiliate_link) || ''; 17271 // Keep navigation on the local storefront â strip the host. 17272 return raw.replace(/^https?:\/\/(?:www\.)?bostonproper\.com/, ''); 17273 } 17274 17275 // Product handle parsed from affiliate_link, e.g. "iris-ring-set". 17276 // Belt-and-suspenders against the remote_id/bp_style in-cart check 17277 // below: those assume Stylitics echoes the queried item_number back 17278 // as remote_id for the anchor, which doesn't hold for every product 17279 // (Stylitics' catalog id doesn't always match the ERP-synced bp_style 17280 // metafield). A live edge case: "Iris Ring Set" recommended itself 17281 // back because its Stylitics remote_id != its bp_style. The handle 17282 // is what the customer actually sees, so it's a more reliable match 17283 // regardless of whatever id scheme Stylitics uses internally. 17284 function itemHandle(item) { 17285 const raw = (item && item.affiliate_link) || ''; 17286 const match = raw.match(/\/products\/([^/?#]+)/); 17287 return match ? match[1] : ''; 17288 } 17289 17290 function isPopular(item) { 17291 // Stylitics doesn't carry product tags; BP convention surfaces 17292 // popularity via the `meta` map on collective items. We can flag 17293 // anchor items here later if Stylitics adds a signal; for now, 17294 // render no badge by default. 17295 return !!(item && item.bp_popular); 17296 } 17297 17298 function buildCard(item, prefix) { 17299 const title = item.name || ''; 17300 const url = itemUrl(item); 17301 const img = itemImage(item); 17302 const price = formatPrice(item.price_localized); 17303 const sale = item.sale_price_localized && item.sale_price_localized !== item.price_localized 17304 ? formatPrice(item.sale_price_localized) 17305 : null; 17306 17307 const badge = isPopular(item) ? `<span class="${prefix}__ctl-badge">Popular</span>` : ''; 17308 const priceHtml = sale 17309 ? `<span class="${prefix}__ctl-sale">${escape(sale)}</span> 17310 <span class="${prefix}__ctl-compare">${escape(price)}</span>` 17311 : escape(price); 17312 17313 return ` 17314 <li class="${prefix}__ctl-card ctl__item" data-bp-ctl-item data-remote-id="${escape(item.remote_id || '')}"> 17315 <a class="${prefix}__ctl-link" href="${escape(url || '#')}"> 17316 ${badge} 17317 <div class="${prefix}__ctl-image ctl-media-container"> 17318 <img src="${escape(img)}" alt="${escape(title)}" loading="lazy" width="240" height="300"> 17319 <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> 17320 </div> 17321 <div class="${prefix}__ctl-body"> 17322 <p class="${prefix}__ctl-name">${escape(title)}</p> 17323 <p class="${prefix}__ctl-price">${priceHtml}</p> 17324 </div> 17325 </a> 17326 </li>`; 17327 } 17328 17329 async function fetchOutfits(style) { 17330 const url = `${ENDPOINT}?username=${encodeURIComponent(STYLITICS_USERNAME)}&item_number=${encodeURIComponent(style)}`; 17331 try { 17332 const res = await fetch(url, { cache: 'force-cache' }); 17333 if (!res.ok) return []; 17334 const data = await res.json(); 17335 return Array.isArray(data) ? data : []; 17336 } catch (err) { 17337 console.warn('[bp-cart-ctl] Stylitics fetch failed', err); 17338 return []; 17339 } 17340 } 17341 17342 // Every bp_style currently in the bag, from the server-rendered cart 17343 // lines. bp-cart-line-item.liquid stamps data-bp-style on each line 17344 // and the drawer re-renders lines from section HTML (not from
17345 // /cart.js, which carries no metafields), so this stays accurate 17346 // after add/remove without an extra round-trip. 17347 function cartStyles() { 17348 const out = new Set(); 17349 document.querySelectorAll('[data-bp-cart-line][data-bp-style]').forEach((line) => { 17350 const s = (line.getAttribute('data-bp-style') || '').trim(); 17351 if (s) out.add(String(s)); 17352 }); 17353 return out; 17354 } 17355 17356 // Every product handle currently in the bag. See itemHandle() above â 17357 // this is the fallback exclusion for when remote_id/bp_style doesn't 17358 // match (Stylitics catalog id drift), since the handle is a direct, 17359 // customer-visible identity check. 17360 function cartHandles() { 17361 const out = new Set(); 17362 document.querySelectorAll('[data-bp-cart-line][data-product-handle]').forEach((line) => { 17363 const h = (line.getAttribute('data-product-handle') || '').trim(); 17364 if (h) out.add(h); 17365 }); 17366 return out; 17367 } 17368 17369 // Collect a flat de-duped item list from up to N outfits, dropping 17370 // anything already in the bag. 17371 // 17372 // This used to drop only the anchor style, which is why adding an 17373 // item could still see it recommended back: the anchor is just the 17374 // most-recently-added line, so as soon as a different line became the 17375 // anchor, the earlier item was fair game again â and any outfit 17376 // legitimately containing it would recommend a product already in the 17377 // bag. Excluding the whole bag covers the anchor too (it's a cart 17378 // line), but the anchor check is kept for the case where the cart 17379 // DOM isn't rendered yet. 17380 function flattenOutfits(outfits, anchorStyle, max) { 17381 const seen = new Set(); 17382 const inCart = cartStyles(); 17383 const inCartHandles = cartHandles(); 17384 const out = []; 17385 for (let i = 0; i < outfits.length && out.length < max; i += 1) { 17386 const items = (outfits[i] && outfits[i].items) || []; 17387 for (let j = 0; j < items.length && out.length < max; j += 1) { 17388 const item = items[j]; 17389 if (!item) continue; 17390 const rid = item.remote_id ? String(item.remote_id) : ''; 17391 if (rid && String(anchorStyle) === rid) continue; 17392 if (rid && inCart.has(rid)) continue; 17393 const handle = itemHandle(item); 17394 if (handle && inCartHandles.has(handle)) continue; 17395 const key = item.remote_id || item.name; 17396 if (!key || seen.has(key)) continue; 17397 seen.add(key); 17398 out.push(item); 17399 } 17400 } 17401 return out; 17402 } 17403 17404 // Read the anchor from the most-recently-added cart line in the DOM. 17405 // Falls back to /cart.js + a product fetch only if no DOM line carries 17406 // a data-bp-style (e.g. all anchors are products without a bp_style 17407 // metafield). 17408 function resolveAnchorStyle() { 17409 const lines = Array.from(document.querySelectorAll('[data-bp-cart-line][data-bp-style]')); 17410 // Pick the LAST one in source order â that's the most-recently-added 17411 // because Liquid renders cart.items in add order (oldest first). 17412 for (let i = lines.length - 1; i >= 0; i -= 1) { 17413 const style = lines[i].getAttribute('data-bp-style'); 17414 if (style && style.trim()) return style.trim(); 17415 } 17416 return null; 17417 } 17418 17419 let lastKey = null; 17420 let lastItems = null; 17421 17422 // Single-flight guard. Several listeners (DOMContentLoaded, cart:update, 17423 // bp:cart-drawer:opened, ...) can fire within milliseconds of each other 17424 // â most visibly on first page load, when a quick drawer-open races 17425 // DOMContentLoaded's own sync(). Without this, both calls would see the 17426 // same "not cached yet" state and each kick off an independent 17427 // fetchOutfits() call; whichever resolves last wins and overwrites the 17428 // other's render, which is why the CTL could flash in then disappear. 17429 // While a run is in flight, later calls just flag `pending` instead of 17430 // racing a second fetch; once the in-flight run finishes, one clean 17431 // follow-up run picks up whatever the final state actually is. 17432 let inFlight = null; 17433 let pending = false;
17434 17435 function sync() { 17436 if (inFlight) { 17437 pending = true; 17438 return inFlight; 17439 } 17440 inFlight = runSync().finally(() => { 17441 inFlight = null; 17442 if (pending) { 17443 pending = false; 17444 sync(); 17445 } 17446 }); 17447 return inFlight; 17448 } 17449 17450 async function runSync() { 17451 const tracks = Array.from(document.querySelectorAll('[data-bp-ctl-track]')); 17452 if (!tracks.length) return; 17453 const sections = tracks.map((t) => t.closest('[data-bp-ctl]')).filter(Boolean); 17454 17455 const anchorStyle = resolveAnchorStyle(); 17456 if (!anchorStyle) { 17457 sections.forEach((sec) => sec.setAttribute('hidden', '')); 17458 lastKey = null; 17459 return; 17460 } 17461 17462 // Cache on the anchor AND the bag contents (styles + handles â a 17463 // product missing bp_style would only show up in the handle set, so 17464 // both are needed to bust the cache correctly). Keying on the anchor 17465 // alone went stale now that the whole bag is excluded: removing a 17466 // non-anchor item leaves the anchor unchanged, so the removed 17467 // product would stay filtered out of its own recommendations. 17468 // fetchOutfits is force-cache'd, so re-running this is cheap. 17469 const cacheKey = anchorStyle 17470 + '|' + Array.from(cartStyles()).sort().join(',') 17471 + '|' + Array.from(cartHandles()).sort().join(','); 17472 let items = lastItems; 17473 if (cacheKey !== lastKey) { 17474 const outfits = await fetchOutfits(anchorStyle); 17475 items = flattenOutfits(outfits, anchorStyle, MAX_CARDS); 17476 lastKey = cacheKey; 17477 lastItems = items; 17478 } 17479 17480 if (!items || !items.length) { 17481 sections.forEach((sec) => sec.setAttribute('hidden', '')); 17482 return; 17483 } 17484 17485 tracks.forEach((track) => { 17486 const prefix = inferPrefix(track); 17487 track.innerHTML = items.map((item) => buildCard(item, prefix)).join(''); 17488 try { track.scrollTo({ left: 0, behavior: 'auto' }); } catch (_) {} 17489 const update = wireIndicator(track); 17490 if (update) requestAnimationFrame(update); 17491 }); 17492 sections.forEach((sec) => sec.removeAttribute('hidden')); 17493 17494 document.dispatchEvent(new CustomEvent('bp:ctl:updated')); 17495 }// `cart:updated` (with the 'd') is BP-internal â fired by the cart 17496 // drawer's bpCartChange() after qty/remove mutations. 17497 document.addEventListener('cart:updated', () => sync()); 17498 // `cart:update` (no 'd') is Horizon's stock event â fired on PDP 17499 // add-to-cart, quick-add, and product-card adds. The drawer reacts 17500 // to it but doesn't translate to `cart:updated`, so the CTL needs 17501 // to listen for both. Without this the CTL stays empty after any 17502 // cross-page add (the most common path into the drawer). 17503 document.addEventListener('cart:update', () => sync()); 17504 // `product:added` is the alternative add-to-cart signal some Horizon
17505 // surfaces dispatch â listen too so we cover every cart-grow path. 17506 document.addEventListener('product:added', () => sync()); 17507 // The cart drawer dispatches this when its dialog becomes visible 17508 // (see snippets/bp-cart-drawer.liquid â open()). Re-sync here so 17509 // the CTL populates the first time the user opens the drawer, 17510 // even when the cart was already populated server-side and no 17511 // cart mutation event has fired since the snippet's initial run. 17512 document.addEventListener('bp:cart-drawer:opened', () => sync()); 17513 // Fired by the drawer once the re-fetched cart lines are actually in 17514 // the DOM. The cart-* events above fire as soon as the cart API 17515 // returns, which is BEFORE the lines carrying data-bp-style are 17516 // replaced â so a sync on those alone reads the pre-mutation bag and 17517 // recommends back the item that was just added. This is the signal 17518 // the in-bag exclusion depends on. 17519 document.addEventListener('bp:cart-lines:rendered', () => sync()); 17520 17521 // Wire bag buttons â delegated so it survives track.innerHTML re-renders. 17522 // preventDefault + stopPropagation blocks the parent <a> from navigating. 17523 document.addEventListener('click', (e) => { 17524 const bag = e.target.closest && e.target.closest('[data-bp-ctl-bag]'); 17525 if (!bag) return; 17526 e.preventDefault(); 17527 e.stopPropagation(); 17528 const url = bag.getAttribute('data-url'); 17529 const remoteId = bag.getAttribute('data-bp-remote-id') || ''; 17530 openQuickAdd(url, remoteId); 17531 }); 17532 17533 function openQuickAdd(productUrl, remoteId) { 17534 if (!productUrl) return; 17535 // Set the Stylitics widget-add context so bp-how-to-wear-it can 17536 // attribute the follow-up /cart/add as a 'widget' engagement. 17537 const handle = (String(productUrl).match(/\/products\/([^/?#]+)/) || [])[1] || ''; 17538 if (handle) { 17539 window.__bpStyliticsWidgetAdd = { 17540 style: String(remoteId || handle), 17541 handle, 17542 until: Date.now() + 90000, 17543 }; 17544 } 17545 let host = window.__bpCartCtlQaHost; 17546 if (!host) { 17547 host = document.createElement('div'); 17548 host.style.cssText = 'position:absolute;left:-9999px;top:0;width:1px;height:1px;overflow:hidden;'; 17549 document.body.appendChild(host); 17550 window.__bpCartCtlQaHost = host; 17551 } 17552 host.innerHTML = 17553 '<product-card>' + 17554 '<a class="product-card__link" ref="productCardLink" href="' + productUrl + '"></a>' + 17555 '<quick-add-component ref="quickAdd">' + 17556 '<button type="button" class="button quick-add__button quick-add__button--choose add-to-cart-button" ' + 17557 'on:click="quick-add-component/handleClick"></button>' + 17558 '</quick-add-component>' + 17559 '</product-card>'; 17560 const choose = host.querySelector('.quick-add__button--choose'); 17561 if (typeof window.bpTrackCartQuickview === 'function') window.bpTrackCartQuickview(productUrl); 17562 requestAnimationFrame(() => { 17563 try { 17564 if (typeof window.bpOpenProductDrawer === 'function' && choose) window.bpOpenProductDrawer(choose); 17565 else if (choose) choose.click(); 17566 else window.location.href = productUrl; 17567 } catch (err) { 17568 console.warn('[bp-cart-ctl] quick-add open failed, navigating', err); 17569 window.location.href = productUrl; 17570 } 17571 }); 17572 } 17573 })(); 17574</script>
17574 17575 17576<style data-shopify> 17577 .ctl-media-container { 17578 position: relative; 17579 } 17580 17581 .ctl-bag-icon { 17582 position: absolute; 17583 bottom: 12px; 17584 right: 12px; 17585 z-index: 2; 17586 width: 36px; 17587 height: 36px; 17588 padding: 0; 17589 border: 1px solid rgba(23, 22, 9, 0.15); 17590 border-radius: 0; 17591 background: var(--bp-color-bg-page); 17592 color: var(--bp-color-text, #171609); 17593 display: inline-flex; 17594 align-items: center; 17595 justify-content: center; 17596 cursor: pointer; 17597 opacity: 0; 17598 transform: translateY(4px); 17599 transition: opacity 0.2s ease, transform 0.2s ease, background-color 0.2s ease; 17600 } 17601 17602 .ctl-bag-icon:hover { 17603 background: var(--bp-color-text, #171609); 17604 color: #fff; 17605 } 17606 .ctl-bag-icon svg { 17607 width: 20px; 17608 height: 20px; 17609 display: block; 17610 } 17611 .ctl__item:hover .ctl-bag-icon, 17612 .ctl-bag-icon:focus-visible { 17613 opacity: 1; 17614 transform: translateY(0); 17615 } 17616</style> 17617
17618<script> 17619(function () { 17620 if (window.bpBundleUpsell) return; 17621 17622 var QA_HOST = null; // hidden quick-add trigger host 17623 var REMOVED_KEY = 'removedUpsells'; 17624 var SURFACE_SELECTOR = 'bp-cart-drawer, bp-cart-page'; 17625 17626 // Candidate upsell products emitted on a cart line by bp-cart-line-item.liquid. 17627 function readLineCandidates(line) { 17628 var el = line.querySelector('[data-bp-line-upsell]'); 17629 if (!el) return []; 17630 try { return JSON.parse((el.textContent || '').trim() || '[]'); } 17631 catch (e) { return []; } 17632 } 17633 17634 function getRemoved() { 17635 try { return JSON.parse(sessionStorage.getItem(REMOVED_KEY) || '[]'); } 17636 catch (e) { return []; } 17637 } 17638 function addRemoved(id) { 17639 var removed = getRemoved(); 17640 if (id && removed.indexOf(String(id)) === -1) { 17641 removed.push(String(id)); 17642 try { sessionStorage.setItem(REMOVED_KEY, JSON.stringify(removed)); } catch (e) { /* noop */ } 17643 } 17644 } 17645 function escapeHtml(str) { 17646 return String(str == null ? '' : str).replace(/[&<>"']/g, function (c) { 17647 return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; 17648 }); 17649 } 17650 17651 function buildCard(u) { 17652 var card = document.createElement('li'); 17653 card.className = 'bp-cart-upsell'; 17654 card.setAttribute('data-bp-cart-upsell', ''); 17655 card.setAttribute('data-upsell-id', u.id); 17656 card.setAttribute('data-upsell-url', u.url); 17657 17658 var dv = parseFloat(u.discount_value); 17659 var discountLabel = ''; 17660 if (u.discount_type && dv) { 17661 discountLabel = u.discount_type === 'percentage' 17662 ? 'Save ' + Math.round(dv) + '%' 17663 : 'Save $' + Math.round(dv); 17664 } 17665 17666 var media = u.image 17667 ? '<a class="bp-cart-upsell__media" href="' + u.url + '">' + 17668 '<img src="' + u.image + '" alt="" width="120" height="150" loading="lazy">' + 17669 '</a>' 17670 : ''; 17671 17672 card.innerHTML = 17673 media + 17674 '<div class="bp-cart-upsell__body">' + 17675 '<p class="bp-cart-upsell__title">' + escapeHtml(u.title) + '</p>' + 17676 '<p class="bp-cart-upsell__prompt">Complete the look' + (discountLabel ? ' and' : '') + '</p>' + 17677 (discountLabel ? '<p class="bp-cart-upsell__discount">' + discountLabel + '</p>' : '') + 17678 '<button type="button" class="bp-cart-upsell__add" data-bp-upsell-add>Add to Bag</button>' + 17679 '</div>' + 17680 '<button type="button" class="bp-cart-upsell__close" data-bp-upsell-remove aria-label="Dismiss">' + 17681 '<svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">' + 17682 '<path d="M12.66 1 1 13" stroke="currentColor" stroke-miterlimit="10"/>' + 17683 '<path d="M1 1l11.66 12" stroke="currentColor" stroke-miterlimit="10"/>' + 17684 '</svg>' + 17685 '</button>'; 17686 return card; 17687 } 17688 17689 // Inject ONE "Complete the look" card into `surfaceEl` (a <bp-cart-drawer> 17690 // or <bp-cart-page>): the first cart line that has an eligible candidate â 17691 // available, not already in the cart, not dismissed this session. DOM-driven 17692 // (reads the server-emitted per-line blobs), so it works on cold open/load 17693 // and after a line re-render alike. Clears prior cards first. 17694 function render(surfaceEl) { 17695 if (!surfaceEl) return; 17696 surfaceEl.querySelectorAll('[data-bp-cart-upsell]').forEach(function (el) { el.remove(); }); 17697 17698 var bundlesOff = window.shop && window.shop.themeSettings && 17699 window.shop.themeSettings.bundlesEnabled === false; 17700 if (bundlesOff) return; 17701 17702 var lines = Array.prototype.slice.call(surfaceEl.querySelectorAll('[data-bp-cart-line]')); 17703 if (!lines.length) return; 17704 var inCart = lines 17705 .map(function (l) { return (l.dataset.productHandle || '').toLowerCase(); }) 17706 .filter(Boolean); 17707 var removed = getRemoved(); 17708 17709 for (var i = 0; i < lines.length; i++) { 17710 var candidates = readLineCandidates(lines[i]); 17711 if (!candidates.length) continue; 17712 var u = candidates.find(function (p) { 17713 var h = (p.handle || '').toLowerCase(); 17714 return h && p.available && 17715 inCart.indexOf(h) === -1 && removed.indexOf(String(p.id)) === -1; 17716 }); 17717 if (u) { 17718 u.url = u.url || ('/products/' + u.handle); 17719 lines[i].parentNode.insertBefore(buildCard(u), lines[i]); 17720 break; 17721 } 17722 } 17723 } 17724 17725 // Render into every cart surface currently in the DOM. 17726 function renderAll() {
17727 document.querySelectorAll(SURFACE_SELECTOR).forEach(function (el) { render(el); }); 17728 } 17729 17730 // Open the upsell product in the BP quick-add drawer (same dynamic hidden 17731 // trigger the HTWI section uses â Horizon reads the product URL from the 17732 // product-card's ref="productCardLink"). Preserves LIPs via the fetched form. 17733 function openQuickAdd(productUrl) { 17734 if (!productUrl) return; 17735 if (!QA_HOST) { 17736 QA_HOST = document.createElement('div'); 17737 QA_HOST.setAttribute('data-bp-upsell-qa-host', ''); 17738 QA_HOST.style.cssText = 'position:absolute;left:-9999px;top:0;width:1px;height:1px;overflow:hidden;'; 17739 document.body.appendChild(QA_HOST); 17740 } 17741 QA_HOST.innerHTML = 17742 '<product-card>' + 17743 '<a class="product-card__link" ref="productCardLink" href="' + productUrl + '"></a>' + 17744 '<quick-add-component ref="quickAdd">' + 17745 '<button type="button" class="button quick-add__button quick-add__button--choose add-to-cart-button" ' + 17746 'on:click="quick-add-component/handleClick"></button>' + 17747 '</quick-add-component>' + 17748 '</product-card>'; 17749 var choose = QA_HOST.querySelector('.quick-add__button--choose'); 17750 // Cart-flyout / cart-page Quickview view_item â this bespoke trigger isn't a 17751 // .bp-card, so bp-track-cards' fireQuickview can't see it; bpTrackCartQuickview 17752 // resolves the Page Type (Cart Flyout Quickview vs Cart Quickview). 17753 if (typeof window.bpTrackCartQuickview === 'function') window.bpTrackCartQuickview(productUrl); 17754 requestAnimationFrame(function () { 17755 try { 17756 if (typeof window.bpOpenProductDrawer === 'function' && choose) window.bpOpenProductDrawer(choose); 17757 else if (choose) choose.click(); 17758 else window.location.href = productUrl; 17759 } catch (e) { window.location.href = productUrl; } 17760 }); 17761 } 17762 17763 // One delegated listener handles Add-to-Bag + dismiss for cards on any surface. 17764 document.addEventListener('click', function (e) { 17765 var addBtn = e.target.closest && e.target.closest('[data-bp-upsell-add]'); 17766 if (addBtn) { 17767 e.preventDefault(); 17768 var addCard = addBtn.closest('[data-bp-cart-upsell]'); 17769 if (addCard) openQuickAdd(addCard.getAttribute('data-upsell-url')); 17770 return; 17771 } 17772 var rmBtn = e.target.closest && e.target.closest('[data-bp-upsell-remove]'); 17773 if (rmBtn) { 17774 e.preventDefault(); 17775 var rmCard = rmBtn.closest('[data-bp-cart-upsell]'); 17776 if (!rmCard) return; 17777 addRemoved(rmCard.getAttribute('data-upsell-id')); 17778 var surface = rmCard.closest(SURFACE_SELECTOR); 17779 rmCard.remove(); 17780 // Surface the next eligible offer on the same surface. 17781 if (surface) render(surface); 17782 } 17783 }); 17784 17785 // Self-wiring: render on ready + whenever the cart changes / a drawer opens / 17786 // the line list is re-rendered. All events are dispatched by the cart surfaces. 17787 ['cart:updated', 'bp:cart-drawer:opened', 'bp:cart-lines:rendered'].forEach(function (ev) { 17788 document.addEventListener(ev, function () { renderAll(); }); 17789 }); 17790 if (document.readyState === 'loading') { 17791 document.addEventListener('DOMContentLoaded', function () { renderAll(); }); 17792 } else { 17793 renderAll(); 17794 } 17795 17796 window.bpBundleUpsell = { 17797 render: render, 17798 renderAll: renderAll, 17799 openQuickAdd: openQuickAdd, 17800 getRemoved: getRemoved, 17801 addRemoved: addRemoved 17802 }; 17803})(); 17804</script>
17804 17805 17806 17807 17808<div class="bp-toast" data-bp-toast role="status" aria-live="polite" hidden> 17809 <span class="bp-toast__msg" data-bp-toast-msg></span> 17810 <button type="button" class="bp-toast__action" data-bp-toast-action hidden></button> 17811 <button type="button" class="bp-toast__close" data-bp-toast-close aria-label="Dismiss"> 17812 <svg width="14" height="14" viewBox="0 0 20 20" fill="none" aria-hidden="true"> 17813 <path d="M5 5l10 10M15 5L5 15" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/> 17814 </svg> 17815 </button> 17816</div> 17817 17818<style data-shopify> 17819 .bp-toast { 17820 position: fixed; 17821 left: 50%; 17822 bottom: 24px; 17823 transform: translateX(-50%) translateY(8px); 17824 z-index: 9998; 17825 display: flex; 17826 align-items: center; 17827 gap: 16px; 17828 max-width: calc(100vw - 32px); 17829 padding: 14px 16px; 17830 background: var(--bp-color-text, #171609); 17831 color: var(--bp-color-cta-text, #FDFFFA); 17832 font-family: var(--bp-font-body); 17833 font-size: 14px; 17834 font-weight: 500; 17835 line-height: 145%; 17836 letter-spacing: -0.14px; 17837 box-shadow: 0 6px 24px rgb(0 0 0 / 0.18); 17838 opacity: 0; 17839 pointer-events: none; 17840 transition: opacity 0.2s ease, transform 0.2s ease; 17841 } 17842 .bp-toast[hidden] { display: none; } 17843 .bp-toast.is-visible { 17844 opacity: 1; 17845 transform: translateX(-50%) translateY(0); 17846 pointer-events: auto; 17847 } 17848 17849 .bp-toast__msg { flex: 1 1 auto; } 17850 17851 .bp-toast__action { 17852 flex: 0 0 auto; 17853 background: transparent; 17854 border: 0; 17855 padding: 0; 17856 cursor: pointer; 17857 color: inherit; 17858 font: inherit; 17859 text-decoration: underline; 17860 text-underline-offset: 3px; 17861 } 17862 .bp-toast__action[hidden] { display: none; } 17863 .bp-toast__action:hover { opacity: 0.7; } 17864 17865 .bp-toast__close { 17866 flex: 0 0 auto; 17867 background: transparent; 17868 border: 0; 17869 padding: 0; 17870 width: 20px; 17871 height: 20px; 17872 cursor: pointer; 17873 color: inherit; 17874 display: inline-flex; 17875 align-items: center; 17876 justify-content: center; 17877 } 17878 .bp-toast__close:hover { opacity: 0.7; } 17879 17880 @media (prefers-reduced-motion: reduce) { 17881 .bp-toast { 17882 transition: none; 17883 transform: translateX(-50%); 17884 } 17885 .bp-toast.is-visible { transform: translateX(-50%); } 17886 } 17887</style> 17888
17889<script> 17890 (function () { 17891 if (window.bpToast) return; // singleton â safe if rendered twice 17892 17893 const el = document.querySelector('[data-bp-toast]'); 17894 if (!el) return; 17895 const msgEl = el.querySelector('[data-bp-toast-msg]'); 17896 const actionEl = el.querySelector('[data-bp-toast-action]'); 17897 const closeEl = el.querySelector('[data-bp-toast-close]'); 17898 let timer = null; 17899 17900 function hide() { 17901 clearTimeout(timer); 17902 el.classList.remove('is-visible'); 17903 // Wait out the fade before un-rendering so it doesn't vanish 17904 // abruptly. 200ms matches the transition above. 17905 timer = setTimeout(() => { el.hidden = true; }, 200); 17906 } 17907 17908 function show(message, opts) { 17909 const o = opts || {}; 17910 if (!message) return; 17911 clearTimeout(timer); 17912 17913 msgEl.textContent = message; 17914 17915 // Reset the action each time â a previous toast's label/attrs 17916 // must not leak into this one. 17917 actionEl.hidden = true; 17918 actionEl.textContent = ''; 17919 [...actionEl.attributes].forEach((a) => { 17920 if (a.name.indexOf('data-') === 0 && a.name !== 'data-bp-toast-action') { 17921 actionEl.removeAttribute(a.name); 17922 } 17923 }); 17924 17925 if (o.action) { 17926 actionEl.textContent = o.action; 17927 Object.keys(o.actionAttrs || {}).forEach((k) => actionEl.setAttribute(k, o.actionAttrs[k])); 17928 actionEl.hidden = false; 17929 } 17930 17931 el.hidden = false; 17932 // Force a reflow so the transition runs on a freshly-unhidden 17933 // element instead of being skipped. 17934 void el.offsetWidth; 17935 el.classList.add('is-visible'); 17936 17937 const duration = o.duration || 4000; 17938 timer = setTimeout(hide, duration); 17939 } 17940 17941 closeEl.addEventListener('click', hide); 17942 // The action is a one-shot; dismiss after it fires. The click still 17943 // bubbles first, so delegated handlers (e.g. [data-bp-saved-open]) 17944 // run normally. 17945 actionEl.addEventListener('click', () => hide()); 17946 17947 window.bpToast = show; 17948 window.bpToast.hide = hide; 17949 17950 // ---- Save-for-later confirmations ------------------------------- 17951 // `wishlist:item-saved` / `:item-removed` are dispatched by every 17952 // save surface (PDP gallery heart, cart line, saved drawer), so 17953 // wiring here covers them all without touching each one. 17954 // 17955 // "View" carries data-bp-saved-open â bp-saved-for-later-drawer 17956 // opens on a delegated document click for ANY element with that 17957 // attribute, so no extra wiring is needed. 17958 document.addEventListener('wishlist:item-saved', () => { 17959 // Show the toast in-frame too (like the remove toast). Inside the 17960 // Publitas quickview iframe the toast is the VISIBLE surface (the parent 17961 // toast sat BEHIND the Publitas modal â the "background" bug), and its 17962 // "View" click is intercepted by bp-quickview-cart-bridge and relayed to 17963 // the parent, which opens its saved drawer in the top layer above the 17964 // modal (QA 7/27, Dragana â previously the in-frame toast was suppressed 17965 // and the parent's was hidden behind the modal + its View unclickable). 17966 show('Saved for later', { 17967 action: 'View', 17968 actionAttrs: { 'data-bp-saved-open': '' } 17969 }); 17970 }); 17971 17972 document.addEventListener('wishlist:item-removed', () => { 17973 show('Removed from saved items'); 17974 }); 17975 })(); 17976</script>
17976 17977 17978 <style> .n113 {color: grey;} </style> 17979<div id="shopify-block-AeERjbDhiOTdYM000e__16157100011046449464" class="shopify-block shopify-app-block"> 17980 17981 17982 17983 17984 17985 17986 17987 17988 <link rel="stylesheet" href="https://cdn.shopify.com/extensions/01a0c561-16b0-72bc-8987-550a5e565f0a/narvar-extensions-244/assets/shipping-protection-cart-widget.css"> 17989
17989<script src="https://cdn.shopify.com/extensions/01a0c561-16b0-72bc-8987-550a5e565f0a/narvar-extensions-244/assets/shipping-protection-cart-widget.js" defer></script>
17989 17990 17991 17992 17993 17994 <style> 17995 div[data-product-handle="narvardeliveryprotection"] { 17996 display: none !important; 17997} 17998 17999button#CartDrawer-Checkout-DP-With { 18000 letter-spacing: .025em; 18001 --tw-text-opacity: 1; 18002 color: rgb(255 255 255 / var(--tw-text-opacity)); 18003 --tw-bg-opacity: 1; 18004 background-color: rgb(0 0 0 / var(--tw-bg-opacity)); 18005 font-weight: 600; 18006 height: 50px; 18007 font-size:100%; 18008 margin: 0; 18009} 18010button#CartDrawer-Checkout-DP-With:hover { 18011 --tw-bg-opacity: 1; 18012 background-color: rgb(102 102 102 / var(--tw-bg-opacity)); 18013} 18014button#CartDrawer-Checkout-DP-Without { 18015 --tw-text-opacity: 1; 18016 --tw-bg-opacity: 1; 18017 --tw-border-opacity: 1; 18018 letter-spacing: .025em; 18019 color: rgb(0 0 0 / var(--tw-text-opacity)); 18020 font-weight: 600; 18021 height: 50px; 18022 font-size:100%; 18023 border: 1px solid rgb(0 0 0/var(--tw-border-opacity)); 18024 text-transform: capitalize; 18025} 18026 </style> 18027 18028 18029 18030
18031<script> 18032 window.NarvarDPData = { 18033 variant_id: 46514716934310, 18034 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"}}), 18035 cart_attributes: "", 18036 settings: { 18037 widget_style: "opt-out-button", 18038 btn_with_class_names: "bp-cart-drawer__btn bp-cart-drawer__btn--primary", 18039 btn_without_class_names: "bp-cart-drawer__btn bp-cart-drawer__btn--secondary", 18040 btn_add_to_cart_class_names: "button, add-to-cart-button", 18041 subtotal_selector: "totals__subtotal-value", 18042 cart_count_bubble_selector: "bp-cart-drawer__bubble", 18043 color_accent: "#2563eb", 18044 always_show_widget: true, 18045 show_price_next_to_checkout_btn: true, 18046 show_domain: "www.bostonproper.com", 18047 shop_name: "Boston Proper", 18048 qty_update_selector: "bp-cart-line__qty-input" 18049 } 18050 }; 18051</script>
18051 18052 18053 18054</div><div id="shopify-block-AbGs2R0xnSVR3dGZhd__9271244056961380716" class="shopify-block shopify-app-block">
18054<script src='https://cdn.shopify.com/extensions/01a0d81f-4e47-7135-9a85-b401c95c75d9/discount-kit-632/assets/dk_cart_observer.js'></script>
vendor: 1 bytes, line 18054
18054
18055<script type='module' src='https://cdn.shopify.com/extensions/01a0d81f-4e47-7135-9a85-b401c95c75d9/discount-kit-632/assets/dk_cart.js'></script>
vendor: 1 bytes, line 18055
18055
18056<script type='module' src='https://cdn.shopify.com/extensions/01a0d81f-4e47-7135-9a85-b401c95c75d9/discount-kit-632/assets/dk_gift-selector.js'></script>
18056 18057 18058<!-- BEGIN app snippet: core_script --> 18059 18060 18061 18062 18063 18064 18065 18066
18067<script> 18068 // Initialize DiscountKit namespace 18069 window.discount_kit = window.discount_kit || {}; 18070 18071 // Configuration and data 18072 window.discount_kit.config = { 18073 auto_gift: true, 18074 gift_selector_enabled: false, 18075 gift_quickview: false, 18076 gift_quickview_auto_add: false, 18077 gift_quickview_change: false, 18078 gift_quickview_change_label: "Change gifts", 18079 gift_quickview_change_style: "theme", 18080 message: "You've unlocked a free gift! Make your selections now.", 18081 add_to_cart: "Add to cart", 18082 show_on_cart_page: false, 18083 stop_showing_after: 0, 18084 prevent_readd_removed_gifts: true, 18085 refresh_on_cart_change: false, 18086 custom_cart_update_event: "discount_kit:cart_changed", 18087 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}, 18088 collections: [], 18089 compare_at_prices: [], 18090 conversion_rate: 1.0, 18091 discounts: [{"id": "2372289298598", 18092 "discountType": "GWP", 18093 "discountTitle": "Logo Bag GWP", 18094 "startsAt": null, 18095 "endsAt": null, 18096 "discountNode": { "config": { "value": {"allowB2b":false,"appliesOncePerCustomer":false,"cartAttribute":null,"currencyCode":null,"customerOperator":"oneOf","customerTags":null,"discountTitle":"Logo Bag GWP","discountType":"GWP","uuid":"0a7a1c1b-512d-415d-ac70-f363298b3d5f","locationIds":null,"locationOperator":"oneOf","marketHandles":null,"marketOperator":"oneOf","matchRule":{"all":false,"type":"collection","include":["690350096550"],"selection":[],"exclude":[],"excludeSale":false,"purchaseType":"both"},"onlyB2b":false,"requireGiftProperty":false,"tiers":[{"buys":{"type":"minimumQuantity","value":2},"gets":{"type":"percentage","value":100,"targetQuantity":1,"matchRule":{"all":false,"type":"productSelection","include":[],"selection":[{"id":"
1809615283310133414","variants":null}],"exclude":[],"excludeSale":false}},"messageTranslations":null,"message":null}],"usageLimit":null} } }},{"id": "2372289986726", 18097 "discountType": "PRODUCT_VOLUME", 18098 "discountTitle": "Fall Trans trio", 18099 "startsAt": null, 18100 "endsAt": null, 18101 "discountNode": { "config": { "value": {"allowB2b":false,"appliesOncePerCustomer":false,"cartAttribute":null,"currencyCode":null,"customerOperator":"oneOf","customerTags":null,"discountTitle":"Fall Trans trio","discountType":"PRODUCT_VOLUME","uuid":"7126df3a-1578-47ff-852f-2063a9d21339","locationIds":null,"locationOperator":"oneOf","marketHandles":null,"marketOperator":"oneOf","matchRule":{"all":false,"type":"collection","include":["690350096550"],"selection":[],"exclude":[],"excludeSale":false,"purchaseType":"both"},"onlyB2b":false,"tiers":[{"buys":{"type":"minimumQuantity","value":2},"gets":{"type":"percentage","value":20},"message":"Buy 2, Save 20%","messageTranslations":null},{"gets":{"type":"percentage","value":30},"buys":{"type":"minimumQuantity","value":3},"message":"Buy 3, Save 30%+ Free Gift","messageTranslations":null}],"useUngroupedDiscounts":false,"volumeType":"mixAndMatch","roundingStrategy":"perQuantity"} } }},{"id": "2383881830566", 18102 "discountType": "CUSTOM", 18103 "discountTitle": "Buy 2, Save $20", 18104 "startsAt": null, 18105 "endsAt": null, 18106 "discountNode": { "config": { "value": {"allowB2b":false,"allowB2B":false,"onlyB2b":false,"appliesOncePerCustomer":false,"attributeKey":"_discount_kit","bucketRules":[{"name":"ALL_RESERVED"},{"name":"Buy 2, Save $20","collectionFilter":[691685752998],"cfp":[0]}],"cartAttribute":null,"currencyCode":null,"customerOperator":"oneOf","customerTags":null,"discountApplicationStrategy":"ALL","discountRules":[{"message":"Buy 2, Save $20","messageTranslations":null,"recurring":false,"requireAllTargets":false,"discountValue":{"fixedAmount":{"amount":"10.00","appliesToEachItem":true}},"maxRecurrences":null,"currency":null,"fixedPrice":null,"targetParts":[{"bucket":"Buy 2, Save $20","quantity":null,"targetSelectionStrategy":"cheapest_first"}
18106],"useCompareAtPrice":false,"useMetafieldPrice":false,"conditionParts":[{"bucket":"Buy 2, Save $20","quantity":2,"total":null,"uniqueProducts":null,"uniqueVariants":null,"operator":"greaterThanOrEqual","order":0}]}],"discountTitle":"Buy 2, Save $20","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":"16d49c3f-3c02-48a5-9a24-236f5088a324","consume":false} } }}] 18107 }; 18108 18109 // Gift products for GWP 18110 window.discount_kit.gift_products = []; 18111 18112 18113 18114 window.discount_kit.gift_products.push({ 18115 product: {"id":15283310133414,"title":"Boston Proper Logo Drawstring Bag Off White\/Black","handle":"boston-proper-logo-drawstring-bag-off-white-black","description":"\u003cp\u003ePerfect for storing shoes, accessories, lingerie, or delicate pieces between wears, the Boston Proper Logo Drawstring Bag keeps your essentials neatly organized at home and on the go. The drawstring closure makes packing and storage simple, while the signature logo adds a distinctly Boston Proper finish. Slip it into your suitcase, tote, or closet for an easy way to keep favorite pieces protected and close at hand.\u003c\/p\u003e","published_at":"2026-07-29T05:05:26-04:00","created_at":"2026-04-10T02:31:10-04:00","vendor":"Boston Proper","type":"Accessories","tags":["2DO87","2DO8740","797","Accessories","Active","Boston Proper","Exclusive","Fall Trans 26","Full Price","Handbag","INV5_2DO87","N\/A","Non-Apparel","nvgroup_2DO87","Published: 20260730","rtly-gc:offer-free-shipping","White","Woven","YGroup_2DO87"],"price":2000,"price_min":2000,"price_max":2000,"available":true,"price_varies":false,"compare_at_price":2000,"compare_at_price_min":2000,"compare_at_price_max":2000,"compare_at_price_varies":false,"variants":[{"id":56363332632742,"title":"Off White\/Black \/ One Size","option1":"Off White\/Black","option2":"One Size","option3":null,"sku":"2DO8740000","requires_shipping":true,"taxable":true,"featured_image":{"id":80132443013286,"product_id":15283310133414,"position":1,"created_at":"2026-09-25T02:34:47-04:00","updated_at":"2026-09-25T02:34:49-04:00","alt":null,"width":1639,"height":2048,"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO8740_SET_f9e9731e-2239-4209-9f28-2caca26750b9.jpg?v=1790318089","variant_ids":[56363332632742]},"available":true,"name":"Boston Proper Logo Drawstring Bag Off White\/Black - Off White\/Black \/ One Size","public_title":"Off White\/Black \/ One Size","options":["Off White\/Black","One Size"],"price":2000,"weight":0,"compare_at_price":2000,"inventory_management":"shopify","barcode":null,"featured_media":{"alt":null,"id":70476743606438,"position":1,"preview_image":{"aspect_ratio":0.8,"height":2048,"width":1639,"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO8740_SET_f9e9731e-2239-4209-9f28-2caca26750b9.jpg?v=1790318089"}},"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}],"images":["\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO8740_SET_f9e9731e-2239-4209-9f28-2caca26750b9.jpg?v=1790318089","\/\/www.bostonproper.com\/cdn\/shop\/files\/2_3d3048c7-b2f6-4056-b227-c04f487dfc61.jpg?v=1790318089"],"featured_image":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO8740_SET_f9e9731e-2239-4209-9f28-2caca26750b9.jpg?v=1790318089","options":["Color","Size"],"media":[{"alt":null,"id":70476743606438,"position":1,"preview_image":{"aspect_ratio":0.8,"height":2048,"width":1639,"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO8740_SET_f9e9731e-2239-4209-9f28-2caca26750b9.jpg?v=1790318089"},"aspect_ratio":0.8,"height":2048,"media_type":"image","src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2DO8740_SET_f9e9731e-2239-4209-9f28-2caca26750b9.jpg?v=1790318089","width":1639},{"alt":null,"id":70476743639206,"position":2,"preview_image":{"aspect_ratio":0.8,"height":2048,"width":1639,"src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2_3d3048c7-b2f6-4056-b227-c04f487dfc61.jpg?v=1790318089"},"aspect_ratio":0.8,"height":2048,"media_type":"image","src":"\/\/www.bostonproper.com\/cdn\/shop\/files\/2_3d3048c7-b2f6-4056-b227-c04f487dfc61.jpg?v=1790318089","width":1639}],"requires_selling_plan":false,"selling_plan_groups":[],"content":"\u003cp\u003ePerfect for storing shoes, accessories, lingerie, or delicate pieces between wears, the Boston Proper Logo Drawstring Bag keeps your essentials neatly organized at home and on the go. The drawstring closure makes packing and storage simple, while the signature logo adds a distinctly Boston Proper finish. Slip it into your suitcase, tote, or closet for an easy way to keep favorite pieces protected and close at hand.\u003c\/p\u003e"}, 18116 options_with_values: [{"name":"Color","position":1,"values":["Off White\/Black"]},{"name":"Size","position":2,"values":["One Size"]}] 18117 }); 18118 18119 18120</script>
18120 18121
18122<script 18123 type='module' 18124 src='https://cdn.shopify.com/extensions/01a0d81f-4e47-7135-9a85-b401c95c75d9/discount-kit-632/assets/dk_core.js' 18125></script>
18125 18126<!-- END app snippet --> 18127 18128 18129 18130 18131</div><div id="shopify-block-AZkhkQVl0RVZWQVpyZ__13480610564648845780" class="shopify-block shopify-app-block">
18131<script 18132 defer 18133 type="text/javascript" 18134 src="https://szero.narvar.com/packs/js/shop_now.js"></script>
vendor: 1 bytes, line 18134
18134
18135<script> 18136 (function(){ 18137 const scriptEl = document.querySelector('script[src="https://szero.narvar.com/packs/js/shop_now.js"]'); 18138 if(scriptEl){ 18139 scriptEl.addEventListener('load', function(){ 18140 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, 18141 rebuySmartCart: false, 18142 ampCartDrawer: false, 18143 }; 18144 18145 nv_shopnow.init(config); 18146 18147 const preview = window.Shopify.designMode; 18148 if(preview){ 18149 nv_shopnow.previewBanner(); 18150 } 18151 }); 18152 } 18153 })(); 18154</script>
18154 18155 18156 18157</div>
18157<script src="https://cdn.shopify.com/storefront/standard-actions.js" type="module" data-source-attribution="shopify.standard_actions"></script>
18157 18158</body> 18159</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.