1<!doctype html> 2<html class="no-js" lang="en" dir="ltr"> 3 <head> 4
4<script src="https://rapid-cdn.yottaa.com/rapid/lib/C-ABgEzjcIMAAA.js"></script>
4<meta charset="utf-8"> 5<meta name="viewport" content="width=device-width,initial-scale=1"> 6<title>Flag Organizer | My Evergreen</title><link rel="canonical" href="https://myevergreen.com/products/01245"><link rel="icon" href="//myevergreen.com/cdn/shop/files/EG-Logo-Icon_NoText_245e8429-764b-40c2-bff2-f21b8e0797b1.png?crop=center&height=48&v=1715373459&width=48" type="image/png"> 7 <link rel="apple-touch-icon" href="//myevergreen.com/cdn/shop/files/EG-Logo-Icon_NoText_245e8429-764b-40c2-bff2-f21b8e0797b1.png?crop=center&height=180&v=1715373459&width=180"><meta name="description" content="Keep all of your flags organized in one easy location! This two-sided flag organizer can hold up to 33 of your favorite house or garden flags, so you'll easily be able to decorate your home appropriately for the season!"><meta property="og:site_name" content="Evergreen"> 8<meta property="og:url" content="https://myevergreen.com/products/01245"> 9<meta property="og:title" content="Flag Organizer | My Evergreen"> 10<meta property="og:type" content="product"> 11<meta property="og:description" content="Keep all of your flags organized in one easy location! This two-sided flag organizer can hold up to 33 of your favorite house or garden flags, so you'll easily be able to decorate your home appropriately for the season!"><meta property="og:image" content="http://myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?crop=center&height=1200&v=1772545307&width=1200"> 12 <meta property="og:image:secure_url" content="https://myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?crop=center&height=1200&v=1772545307&width=1200"> 13 <meta property="og:image:width" content="3000"> 14 <meta property="og:image:height" content="3000"><meta property="og:price:amount" content="25.00"> 15 <meta property="og:price:currency" content="USD"><meta name="twitter:card" content="summary_large_image"> 16<meta name="twitter:title" content="Flag Organizer | My Evergreen"> 17<meta name="twitter:description" content="Keep all of your flags organized in one easy location! This two-sided flag organizer can hold up to 33 of your favorite house or garden flags, so you'll easily be able to decorate your home appropriately for the season!"> 18<link rel="preload" href="//myevergreen.com/cdn/shop/t/101/assets/main.css?v=123728977702231552111785770819" as="style"> 19 20 <!-- Hawksearch --> 21 22 23 <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin> 24 25 26 <link href="//myevergreen.com/cdn/shop/t/101/assets/hawksearch.css?v=71481992326372987921784661998" rel="stylesheet" type="text/css" media="all" /> 27 28 29 30<link rel="preconnect" href="https://myevergreen.searchapi-na.hawksearch.com"> 31<link rel="preconnect" href="https://myevergreen.tracking-na.hawksearch.com"> 32<link rel="preconnect" href="https://myevergreen.recs-na.hawksearch.com"> 33 34
35<script 36 type="module" 37 id="hawksearch-lib" 38 src="//cdn.jsdelivr.net/npm/@bridgeline-digital/[email protected]/dist/hawksearch-handlebars-ui.min.js" 39 crossorigin="anonymous" 40></script>
40 41 42 43<style> 44 .hs-fallback-message { text-align: center; padding: 40px 16px; color: rgb(var(--text-color, 0 0 0)); } 45</style> 46 47 48<template id="hs-native-fallback-bar"><form class="search relative" role="search" aria-label="Sitewide search" action="/search" method="get"> 49 <input type="hidden" name="view" value="native"> 50 <label class="label visually-hidden" for="hs-fallback-search-input">Search</label> 51 <div class="search__form block"> 52 <input type="search" 53 class="search__input w-full input" 54 id="hs-fallback-search-input" 55 name="q" 56 placeholder="Search for Sassafras Mats" 57 aria-label="Search site"> 58 <button class="search__submit text-current absolute focus-inset start" aria-label="Search"> 59 <span class="visually-hidden">Search</span> 60 <svg width="21" height="23" viewBox="0 0 21 23" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M14.398 14.483 19 19.514l-1.186 1.014-4.59-5.017a8.317 8.317 0 0 1-4.888 1.578C3.732 17.089 0 13.369 0 8.779S3.732.472 8.336.472c4.603 0 8.335 3.72 8.335 8.307a8.265 8.265 0 0 1-2.273 5.704ZM8.336 15.53c3.74 0 6.772-3.022 6.772-6.75 0-3.729-3.031-6.75-6.772-6.75S1.563 5.051 1.563 8.78c0 3.728 3.032 6.75 6.773 6.75Z"/></svg> 61 </button> 62 </div> 63</form> 64</template> 65
66<script> 67 /* If the HawkSearch library fails to load, replace the dead search field with the native-look 68 fallback bar (which submits to /search?view=native for real results), and recover any HawkSearch 69 results page by redirecting it to the native view. Only the error path runs here â when the 70 library loads normally, none of this executes. */ 71 (function () { 72 const lib = document.getElementById('hawksearch-lib'); 73 if (!lib) return; 74 lib.addEventListener('error', function () { 75 if (window.__hsFellBack) return; 76 window.__hsFellBack = true; 77 function applyFallback() { 78 document.documentElement.setAttribute('data-hawksearch-failed', ''); 79 80 /* Lazy-load the native bar's refinement styles â only on failure, so the working path 81 pays no cost. Core .search* layout is already in the globally-loaded main.css. */ 82 if (!document.getElementById('hs-fallback-css')) { 83 const link = document.createElement('link'); 84 link.id = 'hs-fallback-css'; 85 link.rel = 'stylesheet'; 86 link.href = '//myevergreen.com/cdn/shop/t/101/assets/predictive-search.css?v=33632668381892787391781124413'; 87 document.head.appendChild(link); 88 } 89 90 /* Swap the dead HawkSearch field for the cloned native-look bar. */ 91 const tpl = document.getElementById('hs-native-fallback-bar'); 92 document.querySelectorAll('hawksearch-unifiedsearch-field').forEach(function (host) { 93 if (tpl && tpl.content) { 94 host.replaceWith(tpl.content.cloneNode(true)); 95 } else { 96 host.remove(); 97 } 98 }); 99 100 /* Results-page recovery: if we're on a HawkSearch results page mid-outage, redirect to the 101 native results view (real results, no dead-end). Loop-safe: the native template renders no 102 hawksearch-search-results, and we guard on view!=native. */ 103 const params = new URLSearchParams(location.search); 104 if (document.querySelector('hawksearch-search-results') && params.get('q') && params.get('view') !== 'native') { 105 params.set('view', 'native'); 106 location.replace(location.pathname + '?' + params.toString()); 107 return; 108 } 109 110 /* Landing pages have no native equivalent â keep a graceful message. */ 111 document.querySelectorAll('hawksearch-search-results, hawksearch-landing-page').forEach(function (el) { 112 const msg = document.createElement('p'); 113 msg.className = 'hs-fallback-message'; 114 msg.setAttribute('role', 'status'); 115 msg.textContent = 'Search is temporarily unavailable. Please refresh the page to try again.'; 116 el.replaceWith(msg); 117 }); 118 document.querySelectorAll('hawksearch-recommendations, hawksearch-visualsearch-field').forEach(function (el) { 119 el.remove(); 120 }); 121 } 122 /* The library script lives in <head>; its load error can fire before the <body> (search field) 123 is parsed, so defer the DOM swap until the document is ready. */ 124 if (document.readyState === 'loading') { 125 document.addEventListener('DOMContentLoaded', applyFallback, { once: true }); 126 } else { 127 applyFallback(); 128 } 129 }); 130 })(); 131</script>
131 132 133 134<template id="hawksearch-styles-global"> 135 136 137<style> 138 139/* 140 The variant selector's space is reserved from INSIDE its own shadow DOM 141 (.hs-variant-selector padding + .variant-selector-list min-height in 142 hawksearch-styles-variants.liquid), which only renders when a product has 143 colour swatches. So the host is content-sized: colour products reserve the 144 swatch row, while size-only variants (e.g. House/Garden flags) and 145 single-variant cards collapse to nothing instead of holding an empty 146 swatch-height gap. Do NOT add a fixed min-height here â it can't tell 147 whether the card has swatches (that lives in the shadow DOM) and would 148 re-introduce the empty gap on non-colour cards. 149 */ 150 hawksearch-variant-selector { 151 display: block; 152 } 153 154 /* âââ 1. Sidebar: fixed width matching native filter sidebar ââââââââ */ 155 @media (min-width: 990px) { 156 .column-md--4 { 157 flex: 0 0 calc(241px + 8 * var(--space-unit)); 158 padding-inline-end: calc(8 * var(--space-unit)); 159 border-inline-end: 1px solid rgba(var(--text-color) / 0.15); 160 position: sticky; 161 top: var(--header-end, 0); 162 align-self: flex-start; 163 max-height: calc(100vh - var(--header-end, 0px)); 164 overflow-y: auto; 165 } 166 .column-md--8 { 167 flex: 1 1 0; 168 padding-inline-start: calc(8 * var(--space-unit)); 169 /* Prevent the results grid's min-content width from forcing .row 170 (Hawksearch's flex-wrap:wrap container) to wrap the sidebar and 171 results column at narrow desktop widths. */ 172 min-width: 0; 173 } 174 } 175 @media (min-width: 1280px) { 176 .column-md--4 { 177 flex: 0 0 calc(241px + 12 * var(--space-unit)); 178 padding-inline-end: calc(12 * var(--space-unit)); 179 } 180 .column-md--8 { 181 padding-inline-start: calc(12 * var(--space-unit)); 182 } 183 } 184 @media (max-width: 989px) { 185 .column-md--4 { 186 width: 100%; 187 flex-basis: 100%; 188 border-inline-end: none; 189 padding-inline-end: 0; 190 margin-bottom: 0; 191 } 192 } 193 194 /* âââ 2. Search results grid âââââââââââââââââââââââââââââââââââââââââââ */ 195 /* auto-fill + minmax lets the grid collapse 4 â 3 â 2 columns as the 196 results column narrows, so cards never compress below the min width. 197 Mobile rule below still pins 2 columns at <=989px. */ 198 .search-results-list { 199 display: grid; 200 grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); 201 gap: 16px; 202 } 203 @media (min-width: 990px) { 204 .search-results-list { 205 /* Cap at 4 columns: each column must be at least 25% minus its share 206 of gap (3 gaps ÷ 4 cols = 12px), so a 5th column can never fit. */ 207 grid-template-columns: repeat(auto-fill, minmax(max(220px, calc(25% - 12px)), 1fr)); 208 min-height: 475px; 209 } 210 } 211 212 213 214 /* Landing pages (any non-search template): force 3 product columns on desktop. 215 Sidebar width and mobile rule are inherited from the shared blocks above/below. */ 216 @media (min-width: 990px) { 217 .search-results-list { 218 grid-template-columns: repeat(3, 1fr); 219 } 220 } 221 222 223 224 @media (max-width: 989px) { 225 /* Zero gap on main layout row â must precede .search-results-list 226 because the grid element carries both .row and .search-results-list */ 227 .row { gap: 0; } 228 .search-results-list { grid-template-columns: repeat(2, 1fr); gap: 8px; min-height: 475px;} 229 .search-results-list__item--content { padding: 0; } 230 .column-md--8 { padding-inline: 0; } 231 select { box-sizing: border-box; max-width: 100%; } 232 } 233 234 /* âââ 3. Result item wrapper height + library default overrides âââââââ */ 235 .search-results-list__item { 236 height: 100%; 237 } 238 .search-results-list__item--content { 239 border-bottom: none; 240 } 241 /* 242 The library's default CSS for --product items sets: 243 padding: var(--padding) â adds inner whitespace that shrinks card content 244 text-align: center â centers title/price text 245 border + background â adds an unwanted container box 246 Our custom template owns all layout via .card classes, so reset these. 247 */ 248 .search-results-list__item--product { 249 padding: 0; 250 text-align: start; 251 border: none; 252 background: transparent; 253 } 254 .search-results-list__item--product:hover { 255 border-color: transparent; 256 } 257 258 /* âââ 4. Utility classes âââââââââââââââââââââââââââââââââââââââââââââââ */ 259 /* 260 The Hawksearch shadow DOM reset strips all layout from these class names. 261 Re-declare them here so the template's utility class system works. 262 */ 263 .flex { display: flex; } 264 .flex-col { flex-direction: column; } 265 .flex-auto { flex: 1 1 auto; } 266 .grow { flex-grow: 1; } 267 .items-end { align-items: flex-end; } 268 .block { display: block; } 269 .inline-block{ display: inline-block; } 270 .relative { position: relative; } 271 .absolute { position: absolute; } 272 .h-full { height: 100%; } 273 .w-full { width: 100%; } 274 .font-bold { font-weight: 700; } 275 .text-current{ color: currentColor; } 276 .text-start { text-align: start; } 277 /* Spacing helpers (matching theme's --space-unit = 0.4rem rhythm) */ 278 .mb-0 { margin-bottom: 0; } 279 .mb-1 { margin-bottom: var(--space-unit); } 280 .mt-1 { margin-top: var(--space-unit); } 281 .mb-8 { margin-bottom: calc(8 * var(--space-unit)); } 282 283 /* âââ Select dropdowns (sort, page-size) âââââââââââââââââââââââââââââ */ 284 select { 285 -webkit-appearance: none; 286 appearance: none; 287 padding-right: 36px; 288 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%23555' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); 289 background-repeat: no-repeat; 290 background-position: right 12px center; 291 background-size: 12px; 292 cursor: pointer; 293 } 294 295 /* âââ Facet styles: matching native collection filter sidebar ââââââââ */ 296 297 /* Facets container â remove library default box */ 298 .facets { 299 border: none; 300 background: transparent; 301 } 302 303 /* Hide HawkSearch's "Narrow Results" heading at all breakpoints. 304 On desktop the sidebar is always visible; no toggle needed. 305 On mobile our .hs-toolbar__filter-btn replaces this button â JS in 306 hawksearch-toolbar-handler.liquid clicks this element programmatically. */ 307 .facets__heading { 308 display: none; 309 } 310 /* Force facets content visible at all breakpoints â we control the 311 entire sidebar column's visibility via [data-filters-open] on the 312 host, so HawkSearch's internal expand/collapse is not needed. */ 313 .facets__content { 314 display: block; 315 } 316 317 /* Individual facet heading 318 Use px not rem â html { font-size: 62.5% } makes 1rem = 10px, 319 but shadow DOM :host is 16px. 18px matches body font setting. */ 320 .facet__heading { 321 font-family: var(--body-font-family); 322 font-weight: 700; 323 font-size: 18px; 324 text-transform: none; 325 padding: calc(6 * var(--space-unit)) 0; 326 border-bottom: 1px solid rgba(var(--text-color) / 0.15); 327 } 328 .facet__heading--collapsible:hover { 329 --icon-color: rgb(var(--link-color, var(--text-color))); 330 color: rgb(var(--link-color, var(--text-color))); 331 } 332 .facet__heading__toggle { 333 margin-inline-start: auto; 334 } 335 336 /* Facet content area */ 337 .facet__content { 338 padding: calc(4 * var(--space-unit)) 0 calc(6 * var(--space-unit)) 0; 339 } 340 /* Mobile: facet groups are expanded by default when the panel opens. 341 HawkSearch controls visibility via DOM presence, not inline styles â 342 the content node present = expanded, absent = collapsed. Do NOT set 343 display:none here; it hides content the library considers "expanded", 344 causing clicks to collapse rather than expand. */ 345 346 /* Checkbox list items */ 347 .checkbox-list-facet__list { 348 margin: 0; 349 } 350 .checkbox-list-facet__list__item { 351 margin: 0 0 calc(4 * var(--space-unit)) 0; 352 } 353 .checkbox-list-facet__list__item:last-child { 354 margin-bottom: 0; 355 } 356 357 /* "Show more" renders as an inline span in Hawksearch's facet shadow DOM, 358 so it needs block formatting for top margin to create visible spacing. */ 359 .facet__toggle { 360 display: inline-block; 361 margin-top: calc(5 * var(--space-unit)); 362 } 363 364 /* Facet value typography â 18px to match body font (not rem, see heading comment) */ 365 .facet__value__title { 366 font-family: var(--body-font-family); 367 font-weight: var(--body-font-weight, 400); 368 font-size: 18px; 369 flex: 1 1 auto; 370 } 371 .facet__value__count { 372 margin-inline-start: calc(3 * var(--space-unit)); 373 white-space: nowrap; 374 } 375 376 /* Checkbox styling â keep library's absolute positioning scheme, 377 override size (16â18px) and colors to match theme. 378 Library: input hidden, label { position:relative; padding-left }, 379 label:before { position:absolute; top; left:0 }. */ 380 input[type=checkbox]+label { 381 position: relative; 382 display: block; 383 margin: 0; 384 padding-left: calc(18px + 8px); 385 cursor: pointer; 386 line-height: 1.4; 387 } 388 input[type=checkbox]+label:before { 389 content: ""; 390 position: absolute; 391 top: 50%; 392 transform: translateY(-50%); 393 left: 0; 394 width: 18px; 395 height: 18px; 396 border: 1px solid rgba(var(--text-color) / 0.4); 397 border-radius: 2px; 398 background-color: rgba(var(--bg-color)); 399 } 400 input[type=checkbox]:checked+label:before { 401 border-color: rgb(var(--text-color)); 402 background-color: rgb(var(--text-color)); 403 } 404 /* Checkmark â drawn via ::after on the label, layered over ::before box */ 405 input[type=checkbox]+label:after { 406 content: ""; 407 position: absolute; 408 left: 6px; 409 top: 50%; 410 width: 5px; 411 height: 10px; 412 border: solid rgba(var(--bg-color)); 413 border-width: 0 2px 2px 0; 414 transform: translateY(-60%) rotate(45deg); 415 opacity: 0; 416 } 417 input[type=checkbox]:checked+label:after { 418 opacity: 1; 419 } 420 421 /* Range slider (price facet) */ 422 .range-slider__bar { 423 height: 3px; 424 border: none; 425 background: rgba(var(--text-color) / 0.15); 426 top: 3px; 427 } 428 .range-slider__bar__active { 429 background: rgb(var(--text-color)); 430 } 431 .range-slider__handle { 432 outline: none; 433 border: solid 3px rgba(var(--bg-color)); 434 background: rgb(var(--text-color)); 435 } 436 .range-slider__handle:hover { 437 outline: none; 438 background: rgb(var(--link-color, var(--text-color))); 439 } 440 /* Currency prefix on range slider inputs */ 441 .range-slider-facet .column { 442 position: relative; 443 } 444 .range-slider-facet .column::before { 445 content: '$'; 446 position: absolute; 447 left: 10px; 448 top: 50%; 449 transform: translateY(-50%); 450 pointer-events: none; 451 z-index: 1; 452 font-size: inherit; 453 color: inherit; 454 } 455 .range-slider-facet .column input { 456 padding-left: 22px; 457 } 458 @media (max-width: 989px) { 459 .range-slider-facet .row { 460 gap: 8px !important; 461 } 462 select[hawksearch-sort] { 463 padding-left: 0; 464 font-weight: 700; 465 font-size: 18px; 466 margin-top: 16px; 467 background-size: 16px; 468 background-position: right 10px center; 469 } 470 select[hawksearch-sort] > option { 471 background-color: #f9f9f9; 472 border-bottom: .5px solid rgba(var(--text-color) / 0.15); 473 } 474} 475 476 /* âââ Pagination âââââââââââââââââââââââââââââââââââââââââââââââââââ */ 477 .pagination { 478 display: flex; 479 align-items: center; 480 justify-content: center; 481 gap: 0; 482 line-height: 1; 483 font-family: var(--body-font-family); 484 } 485 .pagination__summary { 486 display: none; 487 } 488 .pagination__pages { 489 display: flex; 490 align-items: center; 491 gap: 0; 492 } 493 /* Page links + selected â match native .pagination__page-link / __page-current */ 494 .pagination__pages a, 495 .pagination__page--selected { 496 display: block; 497 padding: 8px 14px; 498 color: rgba(var(--text-color) / 0.8); 499 text-decoration: none; 500 font-size: 16px; 501 } 502 .pagination__page--selected { 503 font-weight: 700; 504 color: rgb(var(--text-color)); 505 background: linear-gradient(to top, currentColor 2px, transparent 2px) no-repeat center bottom / 1.3em; 506 } 507 .pagination__pages a:hover { 508 color: rgb(var(--text-color)); 509 background: linear-gradient(to top, currentColor 2px, transparent 2px) no-repeat center bottom / 1.3em; 510 } 511 /* Prev / Next arrows */ 512 .pagination__arrow { 513 display: flex; 514 align-items: center; 515 gap: calc(2 * var(--space-unit)); 516 padding: 8px 12px; 517 color: rgb(var(--text-color)); 518 text-decoration: none; 519 font-size: 16px; 520 font-weight: 700; 521 } 522 .pagination__arrow:hover { 523 opacity: 0.7; 524 } 525 .pagination__arrow--disabled { 526 opacity: 0.4; 527 pointer-events: none; 528 } 529 .pagination__arrow hawksearch-icon { 530 --icon-font-size: 16px; 531 } 532 533 /* Top pagination â mobile spacing */ 534 @media (max-width: 989px) { 535 hawksearch-pagination { 536 display: block; 537 margin-bottom: calc(4 * var(--space-unit)); 538 } 539 } 540 541 /* Bottom pagination wrapper */ 542 .hs-pagination-bottom { 543 display: flex; 544 justify-content: center; 545 padding: calc(8 * var(--space-unit)) 0; 546 margin-top: calc(4 * var(--space-unit)); 547 border-top: 1px solid rgba(var(--text-color) / 0.15); 548 } 549 550 a:hover, .link:hover { 551 color: rgb(var(--link-color, var(--text-color))); 552 } 553 554 /* âââ Selected facets (active filter tags) ââââââââââââââââââââââââââââ */ 555 .selected-facets { 556 display: flex; 557 flex-wrap: wrap; 558 gap: calc(2 * var(--space-unit)); 559 margin: 0 0 calc(6 * var(--space-unit)) 0; 560 } 561 .selected-facets__item { 562 display: inline-flex; 563 align-items: center; 564 gap: calc(2 * var(--space-unit)); 565 padding: calc(1.5 * var(--space-unit)) calc(3 * var(--space-unit)); 566 background: transparent; 567 border: 1px solid rgba(var(--text-color) / 0.15); 568 border-radius: 2px; 569 font-size: 1.2rem; 570 cursor: pointer; 571 } 572 .selected-facets__item:hover { 573 border-color: rgba(var(--text-color) / 0.4); 574 } 575 .selected-facets__item__remove { 576 position: relative; 577 display: flex; 578 align-items: center; 579 justify-content: center;
580 width: 20px; 581 height: 20px; 582 border-radius: 50%; 583 background-color: rgb(var(--text-color)); 584 color: rgba(var(--bg-color)); 585 } 586 /* 587 The library's <hawksearch-icon name="cross"> renders its glyph via 588 <use href="#cross">, and the referenced <symbol> hardcodes fill="#000" 589 on its path. Inside a <use> shadow tree that presentation attribute can't 590 be recolored from our injected CSS, so the black X is invisible on this 591 dark circular button. Hide the broken glyph and draw the X ourselves with 592 two rotated bars â currentColor inherits the button's (bg-color) text 593 color, keeping it centered and crisp at any size. 594 */ 595 .selected-facets__item__remove hawksearch-icon { 596 display: none; 597 } 598 .selected-facets__item__remove::before, 599 .selected-facets__item__remove::after { 600 content: ""; 601 position: absolute; 602 top: 50%; 603 left: 50%; 604 width: 10px; 605 height: 1.5px; 606 background-color: currentColor; 607 border-radius: 1px; 608 } 609 .selected-facets__item__remove::before { 610 transform: translate(-50%, -50%) rotate(45deg); 611 } 612 .selected-facets__item__remove::after { 613 transform: translate(-50%, -50%) rotate(-45deg); 614 } 615 616 /* âââ 5. Image container âââââââââââââââââââââââââââââââââââââââââââââââ */ 617 /* 618 The <a class="media block relative" style="padding-top: N%"> creates the 619 aspect-ratio box via the padding-top trick. Without overflow:hidden and 620 position:relative, the absolutely-positioned img escapes the box and 621 the card grows to the natural image height. 622 623 The Hawksearch reset sets overflow:visible and clears position on every 624 element â restore them here. 625 */ 626 .media { 627 overflow: hidden; 628 position: relative; 629 } 630 /* 631 img.img-fit: fills the aspect-ratio box created by its parent <a>. 632 object-fit:cover matches the native .img-fit rule in main.css L2053-2061. 633 */ 634 .img-fit { 635 position: absolute; 636 top: 0; 637 left: 0; 638 width: 100%; 639 height: 100%; 640 object-fit: cover; 641 } 642 643 /* âââ 6. Card flex layout ââââââââââââââââââââââââââââââââââââââââââââââ */ 644 /* 645 .card mirrors the <product-card> custom element's layout from main.css L2364-2368. 646 The card class string includes `flex` (display) and `flex-col` (direction) as 647 utilities, so this block only adds what utilities don't cover. 648 649 font-size: HawkSearch's shadow DOM root defaults to 16px, overriding the 650 inherited body font-size. The theme body uses calc(var(--body-font-size) * 0.1rem) 651 where html { font-size: 62.5% } makes 1rem = 10px â so body-font-size 18 â 18px. 652 We replicate this formula here so em-based descendants (price, title) compute 653 to the same px values as native product cards. 654 */ 655 .card { 656 display: flex; 657 flex-direction: column; 658 max-width: 768px; 659 margin: 0 auto; 660 font-size: calc(var(--body-font-size) * 0.1rem); 661 } 662 .card__info { 663 padding-top: calc(4 * var(--space-unit)); 664 } 665 /* From main.css L2506-2508 */ 666 .card--product .card__info { 667 flex: 1; 668 } 669 /* Wrapper reserves exactly 2 lines of space so price is always at the same 670 vertical position regardless of whether the title fills 1 or 2 lines. 671 min-height is on the wrapper (a plain block), NOT on the -webkit-box element: 672 putting min-height directly on display:-webkit-box expands the box height, 673 which lets the top of line 3 become visible before overflow:hidden clips it. */ 674 .card__title-wrapper { 675 min-height: calc(2 * 1.5em); 676 } 677 /* Clamp product title to 2 lines with ellipsis */ 678 .card__title { 679 display: -webkit-box; 680 -webkit-line-clamp: 2; 681 -webkit-box-orient: vertical; 682 overflow: hidden; 683 } 684 div.card__title-wrapper > p > a { 685 font-weight: 600; 686 } 687 /* The generic `a:hover` rule above (link-color) bleeds into the card's 688 button anchors (View Details), darkening their text on hover. The theme 689 keeps button text color fixed on hover and only animates the background, 690 so pin each button anchor to its own theme text-color variable. These 691 vars are RGB triplets, so they must be wrapped in rgb(). Scoped to the 692 button classes â higher specificity than `a:hover` (0,2,0 vs 0,1,1), 693 so no !important needed, and real links keep their link-color hover. */ 694 .btn--primary:hover, 695 .btn--primary:focus { 696 color: rgb(var(--btn-text-color)); 697 } 698 .btn--secondary:hover, 699 .btn--secondary:focus { 700 color: rgb(var(--btn-alt-text-color)); 701 } 702 /* Hover image swap (main.css L2371-2382) â hover swaps main/secondary image */ 703 @media (hover: hover) and (pointer: fine) { 704 .card__main-image, 705 .card__media.has-hover-image:hover .card__hover-image { 706 visibility: visible; 707 transition: opacity 0.5s, visibility 0s; 708 opacity: 1; 709 } 710 .card__hover-image, 711 .card__media.has-hover-image:hover .card__main-image { 712 visibility: hidden; 713 transition: opacity 0.5s, visibility 0s 0.5s; 714 opacity: 0; 715 } 716 } 717 /* Hide hover image on touch/mobile */ 718 @media (max-width: 768.98px) and (pointer: coarse) { 719 .card__hover-image { display: none; } 720 } 721 @media (hover: none) { 722 .card__hover-image { display: none; } 723 } 724 725 /* âââ 7. Card-link ::after overlay ââââââââââââââââââââââââââââââââââââ */ 726 /* 727 Makes the entire card info area clickable via the title anchor's ::after 728 pseudo-element. z-index:2 sits above card content but below quick-add (z:3). 729 Mirrors main.css L2392-2400. 730 */ 731 .card-link::after { 732 content: ""; 733 position: absolute; 734 z-index: 2; 735 top: 0; 736 left: 0; 737 width: 100%; 738 height: 100%; 739 } 740 741 /* âââ 8. Price spacing + font sizes âââââââââââââââââââââââââââââââââââ */ 742 /* Mirrors main.css L2402-2416 */ 743 .card:not(.card--related) .price { 744 padding-top: 12px; 745 } 746 .card:not(.card--related).card--no-lines .price { 747 padding-top: calc(2 * var(--space-unit)); 748 } 749 /* Price font sizes â mirrors main.css L3454-3463 */ 750 .price__current { 751 font-size: 1em; 752 white-space: nowrap; 753 } 754 .price__was { 755 font-size: 0.8em; 756 white-space: nowrap; 757 margin-left: 5px; 758 } 759 /* Desktop size bump â mirrors main.css L2664-2668 */ 760 @media (min-width: 990px) { 761 .card--product .price__current { font-size: 1.2em; } 762 .card--product .price__was { font-size: 1em; } 763 } 764 /* Sale price â was-price muted; current price inherits heading color */ 765 /* Mirrors main.css price--on-sale rules; uses cascading custom properties */ 766 .price--on-sale .price__was { 767 color: var(--hs-color-faint, #999); 768 text-decoration: line-through; 769 } 770 .price--on-sale .price__current { 771 color: var(--hs-color-emphasis, #111); 772 } 773 774 /* âââ 9. Rating component styling âââââââââââââââââââââââââââââââââââââââ */ 775 /* 776 hawksearch-rating has its own shadow DOM containing DIV.rating. Custom 777 styles are injected into every component's shadow DOM, so .rating matches 778 that div directly. Host layout is applied from the outer shadow DOM via the 779 hawksearch-rating element selector. 780 781 Star colour (terracotta) â see the mask block below .rating: 782 As of 6.4.0 each star renders as a <hawksearch-icon name="star|star-half| 783 star-empty"> whose glyph is an SVG sprite clone, <use href="#starâ¦">, and the 784 referenced <path> hardcodes fill="#000". A <use> instance can't be recoloured 785 from CSS: selectors can't cross the use shadow boundary, and the path's own 786 fill attribute blocks any inherited fill/currentColor. So the pre-6.4.0 787 `.rating { fill }` no longer reaches the glyph â that was the regression. 788 The fix recolours by ALPHA instead of fill (mask block below). 789 */ 790 .hs-rating-row { 791 display: flex; 792 align-items: center; 793 gap: 4px; 794 padding-top: 8px; 795 padding-bottom: 4px; 796 min-height: 28px; /* 26px stars + 12px padding â always reserved even when empty */ 797 } 798 hawksearch-rating { 799 display: flex; 800 align-items: center;
801 align-self: center; 802 /* Reserve star height before shadow DOM renders to prevent layout shift */ 803 min-height: 22px; 804 /* Transition fires when :not(:defined) stops matching (stars rendered) */ 805 opacity: 1; 806 transition: opacity 150ms ease-out; 807 } 808 hawksearch-rating:not(:defined) { 809 opacity: 0; 810 } 811 /* Hide count while stars are pending so both appear together */ 812 .hs-rating-row:has(hawksearch-rating:not(:defined)) .ratings-count { 813 opacity: 0; 814 } 815 .hs-rating-row hawksearch-rating, 816 .hs-rating-row .ratings-count, 817 .hs-rating-row p { 818 margin: 0; 819 align-self: center; 820 } 821 .rating { 822 fill: var(--rating-star-color, #da5256); 823 color: var(--rating-star-color, #da5256); 824 font-size: 22px; 825 } 826 827 /* 828 Recolour the stars to the brand colour without JS (see note above the layout rules). 829 Each .rating__icon host gets a brand-colour background revealed through a CSS mask 830 cut from the library's own glyph geometry (viewBox 0 0 20 20, paths extracted 831 from the live #star / #star-half / #star-empty symbols). Masking colours the 832 exact shape by alpha, independent of the path's hardcoded fill, and is driven by 833 --rating-star-color so the colour stays single-sourced with .rating above. 834 These :host() rules only match inside the hawksearch-icon shadow DOM (where our 835 global stylesheet is injected and :host is the icon); elsewhere they no-op. 836 Empty/half use fill-rule:evenodd so their inner subpath cuts an outline. 837 */ 838 :host(.rating__icon) { 839 background-color: var(--rating-star-color, #da5256); 840 -webkit-mask-repeat: no-repeat; 841 mask-repeat: no-repeat; 842 -webkit-mask-position: center; 843 mask-position: center; 844 /* Render the 0â20 mask viewBox 1:1 (20px), reproducing the native glyph's 845 intrinsic ~16.67px size exactly. The library's star <svg> has no viewBox, 846 so its glyph is a fixed-px size that does NOT scale with font-size; matching 847 that here keeps star size and inter-star spacing identical to the original. 848 (mask-size:contain would scale to the 22px host box and oversize the star.) */ 849 -webkit-mask-size: 20px 20px; 850 mask-size: 20px 20px; 851 } 852 /* Hide the un-recolourable black <use> glyph. visibility (not display) keeps it 853 in flow so it still sizes the host box the mask paints into. */ 854 :host(.rating__icon) svg { 855 visibility: hidden; 856 } 857 :host(.rating__icon[name="star"]) { 858 -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27m10%2014.392%205.15%203.108-1.367-5.858%204.55-3.942-5.991-.508L10%201.667%207.658%207.192%201.666%207.7l4.55%203.942L4.85%2017.5%2010%2014.392Z%27%2F%3E%3C%2Fsvg%3E"); 859 mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27m10%2014.392%205.15%203.108-1.367-5.858%204.55-3.942-5.991-.508L10%201.667%207.658%207.192%201.666%207.7l4.55%203.942L4.85%2017.5%2010%2014.392Z%27%2F%3E%3C%2Fsvg%3E"); 860 } 861 :host(.rating__icon[name="star-half"]) { 862 -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27m18.3%207.7-6-.5L10%201.7%207.7%207.2l-6%20.5%204.5%203.9-1.4%205.9%205.1-3.1%205.1%203.1-1.4-5.9%204.7-3.9zM10%2012.8l-3.1%201.9.8-3.6-2.8-2.3%203.7-.3L10%205.1l1.4%203.4%203.6.3-2.8%202.4.8%203.6-3-2z%27%20fill-rule%3D%27evenodd%27%2F%3E%3Cpath%20d%3D%27M10%201.7%207.7%207.2l-6%20.5%204.5%203.9-1.4%205.9%205.2-3.1z%27%20fill-rule%3D%27evenodd%27%2F%3E%3C%2Fsvg%3E"); 863 mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27m18.3%207.7-6-.5L10%201.7%207.7%207.2l-6%20.5%204.5%203.9-1.4%205.9%205.1-3.1%205.1%203.1-1.4-5.9%204.7-3.9zM10%2012.8l-3.1%201.9.8-3.6-2.8-2.3%203.7-.3L10%205.1l1.4%203.4%203.6.3-2.8%202.4.8%203.6-3-2z%27%20fill-rule%3D%27evenodd%27%2F%3E%3Cpath%20d%3D%27M10%201.7%207.7%207.2l-6%20.5%204.5%203.9-1.4%205.9%205.2-3.1z%27%20fill-rule%3D%27evenodd%27%2F%3E%3C%2Fsvg%3E"); 864 } 865 :host(.rating__icon[name="star-empty"]) { 866 -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27m18.333%207.7-5.991-.517L10%201.667%207.658%207.192%201.666%207.7l4.55%203.942L4.85%2017.5%2010%2014.392l5.15%203.108-1.359-5.858L18.334%207.7ZM10%2012.833l-3.133%201.892.833-3.567-2.767-2.4%203.65-.316L10%205.083l1.425%203.367%203.65.317-2.767%202.4.834%203.566-3.142-1.9Z%27%20fill-rule%3D%27evenodd%27%2F%3E%3C%2Fsvg%3E"); 867 mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27m18.333%207.7-5.991-.517L10%201.667%207.658%207.192%201.666%207.7l4.55%203.942L4.85%2017.5%2010%2014.392l5.15%203.108-1.359-5.858L18.334%207.7ZM10%2012.833l-3.133%201.892.833-3.567-2.767-2.4%203.65-.316L10%205.083l1.425%203.367%203.65.317-2.767%202.4.834%203.566-3.142-1.9Z%27%20fill-rule%3D%27evenodd%27%2F%3E%3C%2Fsvg%3E"); 868 } 869 .ratings-count { 870 font-size: 14px; 871 line-height: 1; 872 margin: 0; 873 align-self: center; 874 /* Transition fires when :has(hawksearch-rating:not(:defined)) stops matching */ 875 transition: opacity 150ms ease-out; 876 } 877 878 @media (max-width: 768px) { 879 .ratings-count { 880 display: none; 881 } 882 } 883 884 /* âââ 10. Contained card âââââââââââââââââââââââââââââââââââââââââââââââ */ 885 /* 886 Active when settings.card_contain = true (adds card--product-contained). 887 Mirrors main.css L2544-2553. CSS variables cascade through shadow DOM. 888 */ 889 .card--product-contained { 890 padding: calc(5 * var(--space-unit)); 891 border: 1px solid var(--card-border-color); 892 background-color: var(--hs-color-surface-contained, #fafafa); 893 color: rgb(var(--card-text-color)); 894 } 895 896</style> 897 898</template> 899<template id="hawksearch-styles-badges-buttons"> 900 901 902<style> 903 904 /* âââ 10. Product labels / badges âââââââââââââââââââââââââââââââââââââ */ 905 .product-label-container { 906 top: 0; 907 left: 0; 908 z-index: 1; 909 padding-bottom: var(--space-unit); 910 pointer-events: none; 911 background-color: transparent; 912 font-size: 13px; 913 } 914 .product-label-wrapper { 915 flex-wrap: wrap; 916 gap: calc(var(--space-unit)); 917 } 918 .product-label { 919 display: inline-block; 920 padding: calc(var(--space-unit)) calc(2 * var(--space-unit)); 921 font-size: 1.3rem; 922 letter-spacing: 0.05em; 923 line-height: 1.3; 924 } 925 /* Sale badge. The host --sale-label-* vars are only emitted when settings.show_sale_label 926 is on (theme.liquid), and the previously-referenced --sale-badge-bg-color / --primary-color 927 were never defined anywhere â so the background silently dropped. Inject the configured colours 928 directly to stay independent of that toggle, matching the .product-label--new rule below. */ 929 .product-label--sale { 930 background-color: rgb(247 23 53); 931 color: rgb(255 255 255); 932 } 933 /* New-arrival badge. The host --new-label-* vars are only emitted when settings.show_new_label 934 is on (theme.liquid), so inject the configured colours directly to stay independent of that toggle. */ 935 .product-label--new { 936 display: inline-flex; 937 align-items: center; 938 white-space: nowrap; 939 background-color: rgb(126 203 187); 940 color: rgb(9 3 2); 941 } 942 943 .product-label--new > svg { 944 flex-shrink: 0; 945 width: 1.2em; 946 height: 1.2em; 947 margin-right: 0.3em !important; 948 } 949 950 /* Mobile (2-up results grid): the card is ~half the viewport, so shrink the 951 New Arrivals badge to keep it on one line and off the product image. */ 952 @media (max-width: 768.98px) { 953 .product-label--new { 954 padding: 2px 6px; 955 font-size: 1rem; 956 letter-spacing: 0.02em; 957 } 958 .product-label--new > svg { 959 width: 1em; 960 height: 1em; 961 margin-right: 0.25em !important; 962 } 963 } 964 /* âââ 11. Button base styles ââââââââââââââââââââââââââââââââââââââââââ */ 965 /* 966 .btn and .btn--primary are defined in main.css (light DOM) and don't 967 penetrate the shadow. Re-declare the essential rules here so the ATC 968 button is styled. CSS variables (--btn-bg-color, --btn-text-color, etc.) 969 cascade from the host document into shadow DOM automatically. 970 */ 971 .btn { 972 display: inline-block; 973 position: relative; 974 max-width: 100%; 975 padding: var(--btn-padding-y, 12px) 26px; 976 transition: opacity 0.6s ease, color 0.6s ease, background-position 0.4s ease-out; 977 border-radius: var(--btn-border-radius, 0); 978 font-size: 0.88em; 979 font-weight: 700; 980 line-height: 1.2em; 981 text-align: center; 982 text-transform: var(--btn-text-transform, none); 983 -webkit-appearance: none; 984 appearance: none; 985 word-break: break-word; 986 cursor: pointer; 987 } 988 .btn--primary { 989 border: var(--btn-border-width) solid rgb(var(--btn-bg-color)); 990 outline-color: rgb(var(--btn-bg-color)); 991 outline-offset: 3px; 992 background: rgb(var(--btn-bg-hover-color)) linear-gradient(104deg, rgb(var(--btn-bg-hover-color)) 60%, rgb(var(--btn-bg-color)) 60%, rgb(var(--btn-bg-color)) 100%) no-repeat 100% 100%; 993 background-size: 300% 100%; 994 color: rgb(var(--btn-text-color)); 995 } 996 @media (hover: hover) and (pointer: fine) { 997 .btn--primary:not([disabled]):hover { 998 background-position: 0 100%; 999 } 1000 } 1001 1002 /* âââ 12. Button loading / success states ââââââââââââââââââââââââââââââ */ 1003 /* 1004 Mirrors main.css L1505â1514 and L2210â2244. These rules are in the 1005 light DOM and cannot pierce the shadow boundary â redeclare them here 1006 so the is-loading spinner and is-success checkmark render on .hs-atc-btn. 1007 */ 1008 @keyframes spinner { 1009 to { transform: rotate(360deg); } 1010 } 1011 @keyframes checkmark { 1012 0% { width: 0; height: 0; opacity: 1; } 1013 20% { width: 10px; height: 0; opacity: 1; } 1014 40% { width: 10px; height: 20px; opacity: 1; } 1015 90% { width: 10px; height: 20px; opacity: 1; } 1016 100% { width: 10px; height: 20px; opacity: 0; } 1017 } 1018 .btn--primary.is-loading { 1019 color: rgba(var(--btn-text-color) / 0.1); 1020 } 1021 /* Spinner ring */ 1022 .is-loading::after { 1023 content: ""; 1024 position: absolute;
1025 top: calc(50% - 10px); 1026 right: calc(50% - 10px); 1027 width: 20px; 1028 height: 20px; 1029 transition: opacity 0.2s; 1030 animation: spinner 0.6s linear infinite; 1031 border: 2px solid; 1032 border-radius: 50%; 1033 border-color: rgb(var(--btn-text-color)); 1034 border-top-color: transparent; 1035 } 1036 /* Checkmark (hidden until is-success) */ 1037 .is-loading::before { 1038 content: ""; 1039 position: absolute; 1040 top: 50%; 1041 left: 50%; 1042 width: 10px; 1043 height: 20px; 1044 margin-top: -2px; 1045 transform: scaleX(-1) rotate(135deg) translateX(-50%) translateY(-50%); 1046 transform-origin: left top; 1047 border-top: 2px solid rgb(var(--btn-text-color)); 1048 border-inline-end: 2px solid rgb(var(--btn-text-color)); 1049 opacity: 0; 1050 } 1051 .is-success.is-loading::after { 1052 opacity: 0; 1053 } 1054 .is-success::before { 1055 animation: checkmark 1.4s ease; 1056 } 1057 1058 /* Honour reduced-motion â neutralise the ATC spinner rotation and the checkmark 1059 animation while keeping the loading/success states visibly distinct. */ 1060 @media (prefers-reduced-motion: reduce) { 1061 .is-loading::after { 1062 animation: none; 1063 border-top-color: rgb(var(--btn-text-color)); 1064 opacity: 0.5; 1065 } 1066 .is-success::before { 1067 animation-duration: 0.001ms; 1068 } 1069 } 1070 1071 /* âââ 13. Quick-add button âââââââââââââââââââââââââââââââââââââââââââââ */ 1072 /* 1073 Mirrors quick-add.css positioning and hover-reveal logic. 1074 1075 Default position: absolute, sits just above .card__info-container 1076 (bottom:100% relative to the nearest positioned ancestor = .card__info-container.relative). 1077 This overlaps the bottom of the product image on hover. 1078 1079 The Hawksearch reset removes position from all elements, so the button 1080 falls into normal flow and is always visible. Restore the positioned model here. 1081 */ 1082 1083 /* Hidden by default; quick-add.css overrides this â replicate both in shadow */ 1084 .quick-add-btn-icon, 1085 .quick-add-view-btn { 1086 display: none; 1087 } 1088 1089 /* From quick-add.css L1-10 */ 1090 .card__quick-add { 1091 display: block; 1092 position: absolute; 1093 z-index: 3; 1094 right: 0; 1095 bottom: 100%; 1096 left: 0; 1097 flex-shrink: 0; 1098 padding: calc(2 * var(--space-unit)); 1099 } 1100 1101 /* Mobile: text button displayed below card info (position static = in-flow) */ 1102 /* From quick-add.css L158-165 */ 1103 @media (max-width: 1023.98px) { 1104 .mob\:card__quick-add--below { 1105 position: static; 1106 padding: calc(4 * var(--space-unit)) 0 0 0; 1107 } 1108 .mob\:card__quick-add--below .btn { 1109 padding-right: 10px; 1110 padding-left: 10px; 1111 } 1112 } 1113 1114 /* Desktop: hover-reveal overlay */ 1115 /* From quick-add.css L213-225, simplified for shadow DOM (no body.tab-used) */ 1116 @media (min-width: 1024px) {
1117 .card__quick-add:not(.desktop\:card__quick-add--below) { 1118 transition: opacity 0.2s, transform 0.2s; 1119 pointer-events: none; 1120 transform: translateY(10px); 1121 opacity: 0; 1122 } 1123 .card:hover .card__quick-add:not(.desktop\:card__quick-add--below), 1124 .card:focus-within .card__quick-add:not(.desktop\:card__quick-add--below) { 1125 transform: translateY(0); 1126 opacity: 1; 1127 pointer-events: initial; 1128 } 1129 /* From quick-add.css L226-229 */ 1130 .desktop\:card__quick-add--below { 1131 position: static; 1132 padding: calc(4 * var(--space-unit)) 0 0 0; 1133 } 1134 /* Desktop icon mode â square icon button, hover-revealed */ 1135 .desktop\:card__quick-add--icon .quick-add-btn-text { display: none; } 1136 .desktop\:card__quick-add--icon .quick-add-btn-icon { display: flex; } 1137 .desktop\:card__quick-add--icon .btn { 1138 width: 40px; 1139 height: 40px; 1140 padding: 0; 1141 display: flex; 1142 align-items: center; 1143 justify-content: center; 1144 } 1145 } 1146 1147 /* Mobile icon mode â square icon button, always visible */ 1148 @media (max-width: 1023.98px) { 1149 .mob\:card__quick-add--icon .quick-add-btn-text { display: none; } 1150 .mob\:card__quick-add--icon .quick-add-btn-icon { display: flex; } 1151 .mob\:card__quick-add--icon .btn { 1152 width: 40px; 1153 height: 40px; 1154 padding: 0; 1155 display: flex; 1156 align-items: center; 1157 justify-content: center; 1158 } 1159 } 1160 1161 /* ATC error alert â mirrors theme .alert utility classes in shadow DOM */ 1162 .js-form-error { 1163 background-color: var(--hs-color-error-bg, #fef2f2); 1164 color: var(--hs-color-error, #b91c1c); 1165 border: 1px solid var(--hs-color-error-border, #fecaca); 1166 border-radius: 4px; 1167 font-size: 0.875em; 1168 } 1169 1170</style> 1171 1172</template> 1173<template id="hawksearch-styles-search-field"> 1174 1175 1176<style> 1177 1178 /* âââ 14. Search icon + active search bar state ââââââââââââââââââââââââ */ 1179 /* 1180 Search icon: magnifying glass SVG as background-image on the input. 1181 Matches the native .search__input padding (54px start) and icon 1182 size/position. SVG from snippets/icon-search.liquid as a data URI. 1183 1184 Active state: when autocomplete is open, JS adds data-autocomplete-open 1185 to <hawksearch-unifiedsearch-field>. The :host() selector in this 1186 shadow DOM targets that attribute to create a white card container: 1187 â :host gets a white background, rounded top corners, and a subtle 1188 outer ring (matching .hs-autocomplete's side/bottom border) 1189 â the input's bottom radius is flattened so it connects with the dropdown 1190 â the input's own box-shadow is removed (the host ring is the border) 1191 Combined with .hs-autocomplete's border and bottom radius, the result 1192 is a unified white rounded card wrapping the entire input + results panel. 1193 */ 1194 .unifiedsearch-field input[type="text"] { 1195 box-sizing: border-box; 1196 padding-inline-start: 54px; 1197 padding-inline-end: 54px; 1198 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='21' height='23' viewBox='0 0 21 23' fill='%23555'%3E%3Cpath d='M14.398 14.483 19 19.514l-1.186 1.014-4.59-5.017a8.317 8.317 0 0 1-4.888 1.578C3.732 17.089 0 13.369 0 8.779S3.732.472 8.336.472c4.603 0 8.335 3.72 8.335 8.307a8.265 8.265 0 0 1-2.273 5.704ZM8.336 15.53c3.74 0 6.772-3.022 6.772-6.75 0-3.729-3.031-6.75-6.772-6.75S1.563 5.051 1.563 8.78c0 3.728 3.032 6.75 6.773 6.75Z'/%3E%3C/svg%3E"); 1199 background-repeat: no-repeat; 1200 background-position: 16px center; 1201 background-size: 20px; 1202 border-radius: var(--input-lg-border-radius, var(--input-border-radius)); 1203 transition: box-shadow 0.2s ease, border-radius 0.2s ease, background-color 0.2s ease; 1204 } 1205 1206 :host([data-autocomplete-open]) { 1207 z-index: 999; 1208 background: rgb(var(--bg-color)); 1209 border-radius: var(--input-lg-border-radius, var(--input-border-radius)) var(--input-lg-border-radius, var(--input-border-radius)) 0 0; 1210 box-shadow: 0 0 0 1px rgba(var(--text-color)/0.12); 1211 } 1212 :host([data-autocomplete-open]) .unifiedsearch-field { 1213 position: relative; 1214 z-index: 1000; 1215 } 1216 :host([data-autocomplete-open]) .unifiedsearch-field::before { 1217 content: ''; 1218 position: absolute; 1219 top: -8px; 1220 left: -8px; 1221 right: -8px; 1222 bottom: 0; 1223 border: 8px solid var(--hs-color-border-light, #ddd); 1224 border-bottom: none; 1225 border-radius: 1226 calc(var(--input-lg-border-radius, var(--input-border-radius)) + 8px) 1227 calc(var(--input-lg-border-radius, var(--input-border-radius)) + 8px) 1228 0 0; 1229 pointer-events: none; 1230 z-index: 1001; 1231 } 1232 :host([data-autocomplete-open]) .unifiedsearch-field input[type="text"] { 1233 position: relative; 1234 z-index: 999; 1235 box-shadow: none; 1236 border-bottom-left-radius: 0; 1237 border-bottom-right-radius: 0; 1238 background-color: rgba(var(--bg-color)); 1239 } 1240 :host([data-autocomplete-open]) .unifiedsearch-field input[type="text"]:focus { 1241 outline: 1px solid var(--hs-color-accent, rgb(var(--link-color, var(--text-color)))); 1242 outline-offset: -1px; 1243 } 1244 .unifiedsearch-field input[type="text"] { 1245 background-color: var(--hs-color-surface-input, #e6e6e6); 1246 } 1247 1248 /* âââ 15. Close button (â) âââââââââââââââââââââââââââââââââââââââââââ */ 1249 /* 1250 Rendered in the autocomplete template (hawksearch-autocomplete.liquid)
1251 so it only appears when autocomplete is open. Positioned absolutely 1252 relative to <hawksearch-unifiedsearch-field> (position:relative) so 1253 it visually overlaps the right side of the search input above. 1254 JS click handler in hawksearch-config.liquid clears the input and 1255 dismisses the autocomplete. 1256 */ 1257 /* Hidden by default; shown only when the input has a value. 1258 JS in hawksearch-config.liquid sets [data-has-value] on the 1259 <hawksearch-autocomplete> host based on input content. */ 1260 :host(:not([data-has-value])) .hs-autocomplete-close { 1261 display: none; 1262 } 1263 .hs-autocomplete-close { 1264 position: absolute; 1265 top: 0; 1266 right: 8px; 1267 z-index: 1001; 1268 display: flex; 1269 align-items: center; 1270 justify-content: center; 1271 width: 44px; 1272 height: 100%; 1273 max-height: 50px; 1274 padding: 0; 1275 border: none; 1276 background: transparent; 1277 cursor: pointer; 1278 color: var(--hs-color-icon, #555); 1279 } 1280 .hs-autocomplete-close:hover { 1281 color: var(--hs-color-emphasis, #111); 1282 } 1283 .hs-autocomplete-close svg { 1284 width: 20px; 1285 height: 20px; 1286 pointer-events: none; 1287 } 1288 1289</style> 1290 1291</template> 1292<template id="hawksearch-styles-autocomplete"> 1293 1294 1295<style> 1296 1297 1298 /* âââ 16. Dark overlay on autocomplete open âââââââââââââââââââââââââââ */ 1299 /* 1300 Full-viewport dark overlay behind the autocomplete dropdown. 1301 Rendered as a sibling div (.hs-autocomplete-overlay) in the 1302 autocomplete template â avoids the stacking context issue that 1303 a ::before on .hs-autocomplete would cause. 1304 z-index:998 sits below the dropdown (999) but above page content. 1305 */ 1306 .hs-autocomplete-overlay { 1307 position: fixed; 1308 inset: 0; 1309 background: rgba(0, 0, 0, 0.4); 1310 z-index: 998; 1311 opacity: 1; 1312 transition: opacity 0.2s ease; 1313 } 1314 .hs-autocomplete-overlay.is-closing { 1315 opacity: 0; 1316 } 1317 1318 /* âââ 17. Autocomplete dropdown ââââââââââââââââââââââââââââââââââââââââââ */ 1319 /* 1320 Previously in hawksearch-autocomplete.css (external file). 1321 Consolidated here so all Hawksearch shadow DOM styles live in one place. 1322 Class namespace: .hs-autocomplete (avoids collision with the native 1323 .predictive-search classes in predictive-search.css). 1324 Typography and spacing tuned to match the native search autocomplete design. 1325 */ 1326 1327 /* Layout â flex: products grow (left) | suggestions fixed width (right) */ 1328 .hs-autocomplete { 1329 position: absolute; 1330 width: 100%; 1331 z-index: 998; 1332 display: flex; 1333 flex-wrap: wrap; 1334 align-items: stretch; 1335 background: var(--hs-color-surface, #fff); 1336 border: 1px solid rgba(var(--text-color)/0.12); 1337 border-top: none; 1338 border-radius: 0 0 8px 8px; 1339 overflow: visible; 1340 box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); 1341 font-family: var(--body-font-family); 1342 } 1343 .hs-autocomplete::before { 1344 content: ''; 1345 position: absolute; 1346 top: 0; 1347 left: -9px; 1348 right: -9px; 1349 bottom: -8px; 1350 border: 8px solid var(--hs-color-border-light, #ddd); 1351 border-top: none; 1352 border-radius: 0 0 16px 16px; 1353 pointer-events: none; 1354 } 1355 1356 /* Tab panels fill available space; suggestions column is fixed width */ 1357 .hs-autocomplete__tab-panel--products, 1358 .hs-autocomplete__tab-panel--content { 1359 flex: 1 1 0; 1360 min-width: 0; 1361 } 1362 1363 /* âââ Products column âââ */ 1364 .hs-autocomplete__products { 1365 padding: 12px 0; 1366 border-right: 1px solid var(--hs-color-border, #e5e5e5); 1367 border-top: 2px solid var(--hs-color-surface-hover, #f5f5f5); 1368 max-height: 56vh; 1369 overflow-y: auto; 1370 } 1371 @media (max-width: 1023px) { 1372 .hs-autocomplete__products { 1373 border-right: none; 1374 /* Cap height so View All stays reachable and dropdown fits viewport (#23, #26) */ 1375 max-height: 38vh; 1376 /* Fade to signal scrollable content below (#29) */ 1377 -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 40px), transparent 100%); 1378 mask-image: linear-gradient(to bottom, black calc(100% - 40px), transparent 100%); 1379 } 1380 } 1381 1382 .hs-autocomplete__heading { 1383 font-size: 18px; 1384 font-weight: 700; 1385 letter-spacing: 0.04em; 1386 padding-block: 8px; 1387 border-bottom: 2px solid var(--hs-color-emphasis, #111); 1388 display: inline-block; 1389 margin: 0 32px 6px; 1390 } 1391 @media (max-width: 1199px) { 1392 .hs-autocomplete__heading { 1393 font-size: 14px; 1394 margin-inline: 16px; 1395 } 1396 } 1397 1398 /* âââ Product item row âââ */ 1399 .hs-autocomplete__item { 1400 display: grid; 1401 grid-template-columns: 66px 1fr; 1402 gap: 10px; 1403 align-items: center; 1404 padding: 16px 36px; 1405 text-decoration: none; 1406 color: inherit; 1407 transition: background 0.15s; 1408 } 1409 @media (max-width: 1199px) { 1410 .hs-autocomplete__item { 1411 padding: 10px 16px; 1412 } 1413 } 1414 .hs-autocomplete__item:hover { 1415 background: var(--hs-color-surface-hover, #f5f5f5); 1416 color: var(--hs-color-emphasis, #111); 1417 } 1418 1419 .hs-autocomplete__item-image { 1420 width: 66px; 1421 height: 66px; 1422 object-fit: contain; 1423 background: var(--hs-color-surface-alt, #f9f9f9); 1424 } 1425 1426 .hs-autocomplete__item-title { 1427 font-size: 18px; 1428 font-weight: 400; 1429 line-height: 1.2; 1430 margin: 0 0 2px; 1431 font-family: var(--hs-font-product-title, "New York", "Iowan Old Style", "Apple Garamond", Baskerville, "Times New Roman", "Droid Serif", Times, "Source Serif Pro", serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"); 1432 /* Prevent multi-line wrapping at all viewport sizes */ 1433 display: -webkit-box; 1434 -webkit-line-clamp: 2; 1435 -webkit-box-orient: vertical; 1436 overflow: hidden; 1437 } 1438 @media (max-width: 1199px) { 1439 .hs-autocomplete__item-title { 1440 font-size: 17px; 1441 line-height: 1.4; 1442 font-weight: 500; 1443 display: -webkit-box; 1444 -webkit-line-clamp: 2; 1445 -webkit-box-orient: vertical; 1446 overflow: hidden; 1447 } 1448 } 1449 1450 .hs-autocomplete__item-price { 1451 font-size: 16px; 1452 color: var(--hs-color-emphasis, #111); 1453 margin: 0; 1454 } 1455 .hs-autocomplete__item-price--was { 1456 text-decoration: line-through; 1457 color: var(--hs-color-faint, #999); 1458 margin-left: 6px; 1459 } 1460 .hs-autocomplete__item-price--sale { 1461 color: var(--hs-color-emphasis, #111); 1462 } 1463 1464 /* âââ View All link âââ */ 1465 .hs-autocomplete__view-all { 1466 padding: 24px 36px; 1467 font-size: 18px; 1468 } 1469 @media (max-width: 1199px) { 1470 .hs-autocomplete__view-all { 1471 font-size: 15px; 1472 padding: 16px; 1473 } 1474 } 1475 .hs-autocomplete__view-all a { 1476 color: var(--hs-color-emphasis, #111); 1477 text-decoration: underline; 1478 } 1479 .hs-autocomplete__view-all a:hover { 1480 color: rgb(var(--link-color, var(--text-color))); 1481 } 1482 .hs-autocomplete__view-all .icon { 1483 width: 14px; 1484 margin-inline-start: 6px; 1485 vertical-align: middle; 1486 fill: none; 1487 } 1488 1489 /* âââ No-results fallback â injected by JS when Count === 0 âââ */ 1490 .hs-autocomplete__no-results-heading { 1491 font-size: 18px; 1492 color: var(--hs-color-muted, #666); 1493 padding: 12px 36px 0; 1494 margin: 0; 1495 } 1496 @media (max-width: 1199px) { 1497 .hs-autocomplete__no-results-heading { 1498 padding: 12px 16px 0; 1499 } 1500 } 1501 1502 /* âââ DYM (Did You Mean) â zero-results fallback in the left column âââ */ 1503 .hs-autocomplete__dym { 1504 padding: 12px 0; 1505 } 1506 1507 /* âââ Suggestions column âââ */ 1508 /* min() ensures suggestions never exceed 30% of the container, so products 1509 always has at least 70% regardless of dropdown width. */ 1510 .hs-autocomplete__suggestions { 1511 background: var(--hs-color-surface-hover, #f5f5f5); 1512 padding: 12px 0; 1513 flex: 0 0 min(300px, 35%); 1514 } 1515 /* Mid-size: cap tightens further to keep products dominant on narrower viewports. */ 1516 @media (max-width: 1199px) { 1517 .hs-autocomplete__suggestions { 1518 flex: 0 0 min(222px, 28%); 1519 } 1520 } 1521 /* Mobile: stack vertically, suggestions appear above products. */ 1522 @media (max-width: 1023px) { 1523 .hs-autocomplete__suggestions { 1524 flex: 0 0 100%; 1525 order: -1; 1526 } 1527 .hs-autocomplete__tab-panel--products, 1528 .hs-autocomplete__tab-panel--content { 1529 flex: 0 0 100%; 1530 } 1531 } 1532 /* When suggestions column is empty, hide it and let products fill full width. 1533 JS in hawksearch-config.liquid sets [data-suggestions-empty] on .hs-autocomplete 1534 via MutationObserver â :has() doesn't work in Hawksearch shadow DOM styles. */ 1535 .hs-autocomplete[data-suggestions-empty] .hs-autocomplete__suggestions { 1536 display: none; 1537 } 1538 /* No-results fallback injects the heading and view-all as direct flex children 1539 of .hs-autocomplete (no wrapper). Default flex behavior packs them onto the 1540 same row â force each to a full-width flex line so view-all stacks below. */ 1541 .hs-autocomplete[data-suggestions-empty] > .hs-autocomplete__no-results-heading, 1542 .hs-autocomplete[data-suggestions-empty] > .hs-autocomplete__view-all { 1543 flex: 0 0 100%; 1544 } 1545 1546 .hs-autocomplete__suggestions-heading { 1547 font-size: clamp(12px, 1.1vw, 18px); 1548 font-family: var(--body-font-family); 1549 font-weight: 700; 1550 letter-spacing: 0.04em; 1551 margin: 0 0 2px; 1552 padding-top: 12px; 1553 padding-inline: clamp(10px, 1.3vw, 20px); 1554 padding-bottom: 6px; 1555 } 1556 /* Visual separator between the two suggestion groups (categories â popular). */ 1557 .hs-autocomplete__suggestion + .hs-autocomplete__suggestions-heading { 1558 margin-top: 12px; 1559 padding-top: 14px; 1560 } 1561 1562 .hs-autocomplete__suggestion { 1563 display: block; 1564 padding: 7px clamp(10px, 1.3vw, 20px); 1565 font-size: clamp(13px, 1.2vw, 15px); 1566 color: var(--hs-color-emphasis, #111); 1567 text-decoration: none; 1568 transition: background 0.15s; 1569 } 1570 1571 .hs-autocomplete__suggestion:hover { 1572 background: var(--hs-color-surface-subtle, #ebebeb); 1573 color: var(--hs-color-emphasis, #111); 1574 } 1575 1576 /* Mobile: full-width panel, use comfortable fixed sizes. */ 1577 @media (max-width: 1023px) { 1578 .hs-autocomplete__suggestions-heading { 1579 font-size: 14px; 1580 padding: 6px 16px; 1581 } 1582 .hs-autocomplete__suggestion { 1583 font-size: 15px; 1584 padding: 8px 16px; 1585 } 1586 } 1587 1588 /* âââ Tab strip âââ */ 1589 .hs-autocomplete__tabs { 1590 display: flex; 1591 width: 100%; 1592 border-bottom: 1px solid var(--hs-color-border, #e5e5e5); 1593 background: var(--hs-color-surface, #fff); 1594 } 1595 .hs-autocomplete__tab { 1596 padding: 10px 24px; 1597 font-size: 16px; 1598 font-weight: 600; 1599 font-family: var(--body-font-family); 1600 border: none; 1601 background: transparent; 1602 cursor: pointer; 1603 color: var(--hs-color-muted, #666); 1604 border-bottom: 2px solid transparent; 1605 transition: color 0.15s, border-color 0.15s; 1606 } 1607 .hs-autocomplete__tab:hover { 1608 color: var(--hs-color-emphasis, #111); 1609 } 1610 .hs-autocomplete__tab:focus-visible { 1611 outline: 2px solid var(--hs-color-emphasis, #111); 1612 outline-offset: -2px; 1613 } 1614 .hs-autocomplete__tab--active { 1615 color: var(--hs-color-emphasis, #111); 1616 border-bottom-color: var(--hs-color-emphasis, #111); 1617 } 1618 1619 /* Tab panel visibility â controlled by data-active-tab on container */ 1620 .hs-autocomplete[data-active-tab="content"] .hs-autocomplete__tab-panel--products { 1621 display: none; 1622 } 1623 .hs-autocomplete:not([data-active-tab="content"]) .hs-autocomplete__tab-panel--content { 1624 display: none; 1625 } 1626 1627 /* Content tab panel */ 1628 .hs-autocomplete__tab-panel--content { 1629 padding: 12px 0; 1630 max-height: 56vh; 1631 overflow-y: auto; 1632 } 1633 1634 /* Content item in tab panel */ 1635 .hs-autocomplete__content-item { 1636 display: block; 1637 padding: 12px 32px; 1638 font-size: 18px; 1639 color: var(--hs-color-emphasis, #111); 1640 text-decoration: none; 1641 transition: background 0.15s; 1642 } 1643 .hs-autocomplete__content-item:hover { 1644 background: var(--hs-color-surface-hover, #f5f5f5); 1645 color: var(--hs-color-emphasis, #111); 1646 } 1647 1648</style> 1649 1650</template> 1651<template id="hawksearch-styles-recommendations"> 1652 1653 1654<style> 1655 1656 /* âââ 18. Recommendations widget âââââââââââââââââââââââââââââââââââââââ */ 1657 /* 1658 The <hawksearch-recommendations> component uses a carousel layout: 1659 .recommendations outer wrapper 1660 .recommendations__content flex row (buttons + carousel) 1661 .recommendations__carousel overflow viewport 1662 .recommendations__list flex row of items 1663 .recommendations__carousel__item each item (inline width %) 1664 <hawksearch-recommendations-item> our custom card 1665 1666 Default itemsToDisplay: 3 desktop, 2 tablet, 1 mobile. 1667 Each .recommendations__carousel__item gets an inline width 1668 (e.g. 33.33% for 3 items). The Hawksearch shadow DOM reset strips 1669 display:flex, position, and overflow â restore them here. 1670 */ 1671 .recommendations__content { 1672 display: flex; 1673 align-items: center; 1674 position: relative; 1675 } 1676 .recommendations__carousel { 1677 overflow: hidden; 1678 flex: 1 1 0; 1679 } 1680 .recommendations__list { 1681 display: flex; 1682 position: relative; 1683 transition: left 0.3s ease; 1684 } 1685 .recommendations__carousel__item { 1686 flex-shrink: 0; 1687 box-sizing: border-box; 1688 padding: 0 8px; 1689 /* Width driven by CSS custom properties set on the <hawksearch-recommendations> 1690 host element in hawksearch-recommendations.liquid. Custom properties cascade 1691 through shadow DOM; the !important overrides the library's inline style. */ 1692 width: var(--recs-desktop-width, 25%) !important; 1693 } 1694 @media (max-width: 989px) { 1695 .recommendations__carousel__item { 1696 width: var(--recs-tablet-width, 50%) !important; 1697 } 1698 } 1699 @media (max-width: 479px) { 1700 .recommendations__carousel__item { 1701 width: 100% !important; 1702 } 1703 } 1704 /* Recommendation item: cap height to keep carousel rows consistent */ 1705 .recommendations__item { 1706 height: 100%; 1707 max-height: 400px; 1708 } 1709 1710 /* Carousel navigation buttons */ 1711 .recommendations__button { 1712 display: flex; 1713 align-items: center; 1714 justify-content: center; 1715 flex-shrink: 0; 1716 width: 40px; 1717 height: 40px; 1718 cursor: pointer; 1719 color: var(--hs-color-body, #333); 1720 background: transparent; 1721 border: none; 1722 text-decoration: none; 1723 } 1724 .recommendations__button:hover { 1725 color: rgb(var(--link-color, var(--text-color))); 1726 } 1727 .recommendations__button--disabled { 1728 opacity: 0.3; 1729 pointer-events: none; 1730 } 1731 1732 /* Carousel pagination dots */ 1733 .recommendations__pagination { 1734 display: flex; 1735 justify-content: center; 1736 gap: 8px; 1737 padding-top: 12px; 1738 } 1739 .recommendations__pagination__item { 1740 display: inline-block; 1741 position: relative; 1742 width: 10px; 1743 height: 10px; 1744 border-radius: 50%; 1745 background: var(--hs-color-dot, #ccc); 1746 cursor: pointer; 1747 } 1748 /* Expand the tap target to the WCAG 2.5.8 (AA) 24px minimum without changing the dot's visual size. */ 1749 .recommendations__pagination__item::before { 1750 content: ''; 1751 position: absolute; 1752 inset: -7px; 1753 } 1754 .recommendations__pagination__item--selected { 1755 background: var(--hs-color-dot-active, #333); 1756 } 1757 1758 /* Heading */ 1759 .recommendations__heading { 1760 display: none; 1761 } 1762 1763</style> 1764 1765</template> 1766<template id="hawksearch-styles-content-zones"> 1767 1768 1769<style> 1770 1771 /* âââ 19. Content zone components ââââââââââââââââââââââââââââââââââââââââ */ 1772 /* 1773 Content zones render promotional content (banners, featured products, 1774 custom HTML, popular queries) alongside search results. The default 1775 templates use .row/.column grid classes and component-specific classes 1776 that the Hawksearch shadow DOM reset strips â re-declare them here. 1777 */ 1778 1779 /* âââ 19a. Grid system (scoped to content zones) ââââââââââââââââââââââ */ 1780 /* 1781 IMPORTANT: .row and .column are generic grid classes also used by the 1782 search results sidebar/content layout. We scope these to .content-zone 1783 and .featured-items-content so they don't override the page-level 1784 column-md--4 / column-md--8 sidebar layout from section 1. 1785 */ 1786 .content-zone .row, 1787 .featured-items-content { 1788 display: flex; 1789 flex-wrap: wrap; 1790 } 1791 .content-zone .column, 1792 .featured-items-content .column { 1793 box-sizing: border-box; 1794 flex
1794: 0 0 auto; 1795 width: 100%; 1796 } 1797 .content-zone .column--12, 1798 .featured-items-content .column--12 { 1799 flex-basis: 100%; 1800 } 1801 @media (min-width: 740px) { 1802 .content-zone .column-sm--4, 1803 .featured-items-content .column-sm--4 { 1804 flex-basis: 33.333%; 1805 } 1806 .content-zone .column-sm--6, 1807 .featured-items-content .column-sm--6 { 1808 flex-basis: 50%; 1809 } 1810 .content-zone .column-sm--8, 1811 .featured-items-content .column-sm--8 { 1812 flex-basis: 66.667%; 1813 } 1814 .content-zone .flex-align-self-sm-center, 1815 .featured-items-content .flex-align-self-sm-center { 1816 align-self: center; 1817 } 1818 } 1819 @media (min-width: 1260px) { 1820 .content-zone .column-lg--4, 1821 .featured-items-content .column-lg--4 { 1822 flex-basis: 33.333%; 1823 } 1824 } 1825 1826 /* âââ 19b. Content zone container ââââââââââââââââââââââââââââââââââââââââ */ 1827 .content-zone { 1828 margin-bottom: 16px; 1829 } 1830 1831 /* âââ 19c. Custom HTML content âââââââââââââââââââââââââââââââââââââââââââ */ 1832 .custom-content { 1833 font-family: var(--body-font-family); 1834 font-size: 16px; 1835 line-height: 1.6; 1836 } 1837 .custom-content img { 1838 display: block; 1839 width: auto; 1840 max-width: 100%; 1841 height: auto; 1842 } 1843 .custom-content a { 1844 color: rgb(var(--link-color, var(--text-color))); 1845 text-decoration: underline; 1846 } 1847 .custom-content a:hover { 1848 color: rgb(var(--link-color, var(--text-color))); 1849 } 1850 1851 /* âââ 19d. Featured items ââââââââââââââââââââââââââââââââââââââââââââââââ */ 1852 .featured-items-content { 1853 gap: 16px; 1854 } 1855 .featured-items-content__item { 1856 position: relative; 1857 padding: 12px; 1858 box-sizing: border-box; 1859 } 1860 .featured-items-content__item--product { 1861 text-align: center; 1862 } 1863 .featured-items-content__item__pin { 1864 position: absolute; 1865 top: 8px; 1866 right: 8px; 1867 color: var(--hs-color-pin, #d4a017); 1868 } 1869 .featured-items-content__item__sale-indicator { 1870 display: inline-block; 1871 padding: 2px 8px; 1872 font-size: 0.75rem; 1873 font-weight: 700; 1874 text-transform: uppercase; 1875 /* --sale-badge-bg-color / --primary-color were never defined â inject the configured 1876 sale-label colours directly (same fix as .product-label--sale in badges-buttons). */ 1877 background-color: rgb(247 23 53); 1878 color: rgb(255 255 255); 1879 border-radius: 2px; 1880 margin-bottom: 8px; 1881 } 1882 .featured-items-content__item__image { 1883 display: block; 1884 text-decoration: none; 1885 } 1886 .featured-items-content__item__image img { 1887 display: block; 1888 width: 100%; 1889 height: auto; 1890 max-width: 100%; 1891 } 1892 .featured-items-content__item__title { 1893 margin-top: 8px; 1894 font-size: 1rem; 1895 font-weight: 600; 1896 line-height: 1.4; 1897 } 1898 .featured-items-content__item__title a { 1899 color: inherit; 1900 text-decoration: none; 1901 } 1902 .featured-items-content__item__title a:hover { 1903 color: rgb(var(--link-color, var(--text-color))); 1904 } 1905 .featured-items-content__item__price { 1906 margin-top: 4px; 1907 font-size: 0.9rem; 1908 } 1909 .featured-items-content__item__price__original { 1910 text-decoration: line-through; 1911 color: var(--hs-color-faint, #999); 1912 margin-right: 6px; 1913 } 1914 .featured-items-content__item__price__current { 1915 font-weight: 700; 1916 } 1917 1918 /* âââ 19e. Image banners âââââââââââââââââââââââââââââââââââââââââââââââââ */ 1919 .image-content { 1920 margin-bottom: 12px; 1921 } 1922 .image-content__image { 1923 max-width: 100%; 1924 height: auto; 1925 display: block; 1926 } 1927 1928 /* âââ 19f. Popular queries âââââââââââââââââââââââââââââââââââââââââââââââ */ 1929 .popular-queries-content { 1930 display: flex; 1931 flex-wrap: wrap; 1932 gap: 8px; 1933 padding: 12px 0; 1934 } 1935 .popular-queries-content__item { 1936 display: inline-block; 1937 padding: 4px 12px; 1938 text-decoration: none; 1939 color: var(--hs-color-body, #333); 1940 border: 1px solid var(--hs-color-border-light, #ddd); 1941 border-radius: 4px; 1942 transition: background 0.15s, color 0.15s; 1943 cursor: pointer; 1944 } 1945 .popular-queries-content__item:hover { 1946 background: var(--hs-color-surface-hover, #f5f5f5); 1947 color: rgb(var(--link-color, var(--text-color))); 1948 } 1949 /* Weight-based font sizes for tag cloud */ 1950 .popular-queries-content__item--1 { font-size: 0.8rem; } 1951 .popular-queries-content__item--2 { font-size: 0.9rem; } 1952 .popular-queries-content__item--3 { font-size: 1rem; font-weight: 500; } 1953 .popular-queries-content__item--4 { font-size: 1.15rem; font-weight: 600; } 1954 .popular-queries-content__item--5 { font-size: 1.3rem; font-weight: 700; } 1955 1956</style> 1957 1958</template> 1959<template id="hawksearch-styles-toolbar"> 1960 1961 1962<style> 1963 1964 /* âââ 22. Products toolbar (filter toggle + sort/page-size str
1964ip) ââââââ */ 1965 /* 1966 Mirrors the native .products-toolbar bar from the theme. 1967 Sits between <hawksearch-selected-facets> and <hawksearch-pagination> 1968 inside the .column-md--8 results column. 1969 1970 Filter toggle bridge: 1971 JS (hawksearch-toolbar-handler.liquid) sets [data-filters-open] on 1972 <hawksearch-search-results>. Presence = sidebar visible, absence = hidden. 1973 Uses :host(hawksearch-search-results...) to scope these rules so they only 1974 apply when the stylesheet is injected into the search-results shadow root, 1975 not into sorting/item shadow roots. 1976 */ 1977 1978 /* Toolbar bar */ 1979 .hs-toolbar { 1980 display: flex; 1981 align-items: center; 1982 gap: calc(6 * var(--space-unit)); 1983 padding-top: calc(4 * var(--space-unit)); 1984 padding-bottom: calc(4 * var(--space-unit)); 1985 margin-bottom: calc(8 * var(--space-unit)); 1986 border-top: 1px solid rgba(var(--text-color) / 0.15); 1987 border-bottom: 1px solid rgba(var(--text-color) / 0.15); 1988 } 1989 1990 /* Filter toggle button */ 1991 .hs-toolbar__filter-btn { 1992 display: inline-flex; 1993 align-items: center; 1994 gap: calc(3 * var(--space-unit)); 1995 font-family: var(--body-font-family, inherit); 1996 font-size: 1em; 1997 font-weight: 700; 1998 color: currentColor; 1999 background: transparent; 2000 border: none; 2001 cursor: pointer; 2002 padding: 0; 2003 white-space: nowrap; 2004 } 2005 .hs-toolbar__filter-btn:hover { 2006 opacity: 0.7; 2007 } 2008 .hs-toolbar__filter-btn:focus-visible { 2009 outline: 2px solid rgb(var(--text-color)); 2010 outline-offset: 2px; 2011 border-radius: 2px; 2012 } 2013 /* Icon circles slide toward center when sidebar is closed, 2014 matching the native filter icon animation */ 2015 .hs-toolbar__filter-btn circle { 2016 transition: transform 0.25s ease; 2017 } 2018 :host(hawksearch-search-results:not([data-filters-open])) .hs-toolbar__filter-btn circle:nth-of-type(1), 2019 :host(hawksearch-landing-page:not([data-filters-open])) .hs-toolbar__filter-btn circle:nth-of-type(1) { 2020 transform: translateX(6px); 2021 } 2022 :host(hawksearch-search-results:not([data-filters-open])) .hs-toolbar__filter-btn circle:nth-of-type(2), 2023 :host(hawksearch-landing-page:not([data-filters-open])) .hs-toolbar__filter-btn circle:nth-of-type(2) { 2024 transform: translateX(-6px); 2025 } 2026 2027 /* Responsive labels: "Filter" on desktop, "Filter & Sort" on mobile */ 2028 .hs-toolbar__filter-label-desktop { display: none; } 2029 .hs-toolbar__filter-label-mobile { display: inline; } 2030 @media (min-width: 990px) { 2031 .hs-toolbar__filter-label-desktop { display: inline; } 2032 .hs-toolbar__filter-label-mobile { display: none; } 2033 } 2034 2035 /* Sort + page-size: separator + hidden on mobile 2036 (mobile uses HawkSearch's facets heading for sort access) */ 2037 .hs-toolbar__sort { 2038 padding-inline-start: calc(6 * var(--space-unit)); 2039 border-inline-start: 1px solid rgba(var(--text-color) / 0.15); 2040 } 2041 select[hawksearch-sort] { 2042 background-color: var(--hs-color-surface, #fff); 2043 } 2044 /* 989px complements min-width: 990px â matches DESKTOP_MIN in hawksearch-toolbar-handler.liquid */ 2045 @media (max-width: 989px) { 2046 .hs-toolbar__sort, 2047 .hs-toolbar__page-size { 2048 display: none; 2049 } 2050 } 2051 @media (min-width: 990px) { 2052 .hs-toolbar__page-size { 2053 margin-inline-start: auto; 2054 } 2055 } 2056 2057 /* ââ Filter sidebar show/hide via host attribute ââââââââââââââââââââââ 2058 Desktop: display:none toggle (no animation needed). 2059 Mobile: visibility + translate3d for left-slide drawer transition, 2060 mirroring the theme's .drawer / .drawer[open] CSS pattern. 2061 [data-filters-open] present = visible. Absent = hidden. */ 2062 2063 /* Desktop: simple display toggle */ 2064 @media (min-width: 990px) { 2065 :host(hawksearch-search-results:not([data-filters-open])) .column-md--4, 2066 :host(hawksearch-landing-page:not([data-filters-open])) .column-md--4 { 2067 display: none; 2068 } 2069 :host(hawksearch-search-results:not([data-filters-open])) .column-md--8, 2070 :host(hawksearch-landing-page:not([data-filters-open])) .column-md--8 { 2071 padding-inline-start: 0; 2072 } 2073 } 2074 2075 /* Mobile drawer: closed state (slide off-screen left) */ 2076 @media (max-width: 989px) { 2077 .column-md--4 { 2078 position: fixed; 2079 top: 0; 2080 left: 0; 2081 /* Above the theme header (sticky, z-index:100) so the full-screen filter 2082 drawer covers it on mobile â otherwise the header + search bar overlap 2083 the drawer's title and close button. Stays below the visual-search 2084 overlay (z-index:9999) and true modals. */ 2085 z-index: 110; 2086 width: 100%; 2087 max-width: 540px; 2088 height: 100vh; 2089 height: 100dvh; 2090 background-color: rgb(var(--bg-color, 255 255 255)); 2091 /* overflow-y:auto lets .column-md--4 itself scroll so HS elements 2092 never need to be moved into a wrapper â moving them re-triggers 2093 connectedCallback and wipes their rendered shadow DOM. */ 2094 overflow-y: auto; 2095 overflow-x: hidden; 2096 -webkit-overflow-scrolling: touch; 2097 /* 24px side padding for the scrollable content area; header and 2098 footer use negative margins to extend back to the drawer edges. */ 2099 padding: 0 24px; 2100 visibility: hidden; 2101 transform: translate3d(-100%, 0, 0); 2102 transition: visibility 0s 0.6s, transform 0.7s cubic-bezier(0.19, 1, 0.22, 1); 2103 } 2104 2105 /* Mobile drawer: open state */ 2106 :host(hawksearch-search-results[data-filters-open]) .column-md--4, 2107 :host(hawksearch-landing-page[data-filters-open]) .column-md--4 { 2108 visibility: visible; 2109 transform: translate3d(0, 0, 0); 2110 transition: visibility 0s 0s, transform 0.7s cubic-bezier(0.19, 1, 0.22, 1); 2111 } 2112 } 2113 2114 /* ââ No-facets state âââââââââââââââââââââââââââââââââââââââââââââââââ 2115 Concept Search fallback returns Facets: []. Toolbar handler sets 2116 [data-hs-no-facets] on the host; button is visually disabled (empty 2117 toolbar looks worse than a dimmed anchor) and the sidebar column is 2118 hidden. pointer-events:none + handler click guard + rAF-applied 2119 aria-disabled cover mouse, keyboard, and AT. Orthogonal to 2120 [data-filters-open] â these rules win regardless. */ 2121 :host([data-hs-no-facets]) .hs-toolbar__filter-btn { 2122 opacity: 0.4;
2123 cursor: not-allowed; 2124 pointer-events: none; 2125 } 2126 :host([data-hs-no-facets]) .column-md--4 { 2127 display: none; 2128 } 2129 :host([data-hs-no-facets]) .column-md--8 { 2130 padding-inline-start: 0; 2131 } 2132 2133 /* ââ Mobile facet drawer chrome ââââââââââââââââââââââââââââââââââââââ 2134 Header (title + close) and sticky footer CTA. 2135 Injected into shadow DOM by hawksearch-toolbar-handler.liquid. 2136 .column-md--4 is the scroll container (overflow-y:auto). Header and 2137 footer use position:sticky so they stay visible without wrapping the 2138 HS custom elements â moving those wipes their rendered shadow DOM. 2139 Negative margins on header/footer extend them back to drawer edges 2140 despite the 24px side padding on .column-md--4. */ 2141 @media (max-width: 989px) { 2142 .hs-drawer__header { 2143 position: sticky; 2144 top: 0; 2145 z-index: 10; 2146 display: flex; 2147 align-items: center; 2148 justify-content: space-between; 2149 margin-left: -24px; 2150 margin-right: -24px; 2151 padding: 20px 24px; 2152 border-bottom: 1px solid rgba(var(--text-color) / 0.15); 2153 background-color: rgb(var(--bg-color, 255 255 255)); 2154 } 2155 .hs-drawer__title { 2156 font-family: var(--body-font-family); 2157 font-size: 22px; 2158 font-weight: 700; 2159 margin: 0; 2160 color: rgb(var(--heading-color, var(--text-color))); 2161 } 2162 .hs-drawer__close { 2163 display: flex; 2164 align-items: center; 2165 justify-content: center; 2166 background: none; 2167 border: none; 2168 padding: 10px; 2169 margin: -10px; 2170 cursor: pointer; 2171 color: rgb(var(--heading-color, var(--text-color))); 2172 } 2173 .hs-drawer__close:focus-visible { 2174 outline: 2px solid rgb(var(--text-color)); 2175 outline-offset: 2px; 2176 border-radius: 2px; 2177 } 2178 .hs-drawer__close svg { 2179 width: 20px; 2180 height: 20px; 2181 pointer-events: none; 2182 } 2183 .hs-drawer__footer { 2184 position: sticky; 2185 bottom: 0; 2186 z-index: 1; 2187 margin-left: -24px; 2188 margin-right: -24px; 2189 padding: 16px 24px; 2190 border-top: 1px solid rgba(var(--text-color) / 0.15); 2191 background: rgb(var(--bg-color, 255 255 255)); 2192 } 2193 .hs-drawer__cta { 2194 display: block; 2195 width: 100%; 2196 padding: 14px 24px; 2197 font-family: var(--body-font-family, inherit); 2198 font-size: 16px; 2199 font-weight: 700; 2200 text-align: center; 2201 color: rgb(var(--bg-color, 255 255 255)); 2202 background-color: rgb(var(--btn-bg-color)); 2203 border: 1px solid rgb(var(--btn-bg-color)); 2204 border-radius: var(--btn-border-radius, 0); 2205 cursor: pointer; 2206 transition: opacity 0.2s ease; 2207 } 2208 .hs-drawer__cta:hover { opacity: 0.85; } 2209 .hs-drawer__cta:focus-visible { 2210 outline: 2px solid rgb(var(--text-color)); 2211 outline-offset: 2px; 2212 } 2213 } 2214 2215 /* Desktop: hide drawer chrome if injected */ 2216 @media (min-width: 990px) { 2217 .hs-drawer__header, 2218 .hs-drawer__footer { 2219 display: none; 2220 } 2221 } 2222 2223 /* Mobile sort â shown inside facets column on mobile only. 2224 Desktop sort lives in .hs-toolbar__sort (always visible). */ 2225 .hs-mobile-sort { 2226 display: none; 2227 } 2228 @media (max-width: 989px) { 2229 .hs-mobile-sort { 2230 display: block; 2231 padding-bottom: calc(4 * var(--space-unit)); 2232 margin-bottom: calc(4 * var(--space-unit)); 2233 border-bottom: 1px solid rgba(var(--text-color) / 0.15); 2234 } 2235 } 2236 2237 /* Honour reduced-motion â make the mobile filter drawer's slide instant (overrides the 2238 0.7s transform transition on the open/closed drawer column). */ 2239 @media (prefers-reduced-motion: reduce) { 2240 :host(hawksearch-search-results) .column-md--4, 2241 :host(hawksearch-landing-page) .column-md--4 { 2242 transition-duration: 0.001ms !important; 2243 } 2244 } 2245 2246</style> 2247 2248</template> 2249<template id="hawksearch-styles-variants"> 2250 2251 2252<style> 2253 2254 /* âââ Variant selector host ââââââââââââââââââââââââââââââââââââââââââââ */ 2255 hawksearch-variant-selector { 2256 display: block; 2257 } 2258 2259 /* âââ Swatch row âââââââââââââââââââââââââââââââââââââââââââââââââââââââ */ 2260 .hs-variant-selector { 2261 padding-top: calc(3 * var(--space-unit)); 2262 } 2263 2264 .variant-selector-list { 2265 display: flex; 2266 flex-wrap: wrap; 2267 gap: calc(2 * var(--space-unit)); 2268 position: relative; 2269 z-index: 3; /* above .card-link::after overlay (z-index: 2) */ 2270 min-height: var(--swatch-card-size, 24px); 2271 } 2272 2273 /* âââ Individual swatch button âââââââââââââââââââââââââââââââââââââââââ */ 2274 /* 2275 Size mirrors native .card__swatches > .opt-label (main.css L4260-4267). 2276 Uses --swatch-card-size CSS custom property which cascades through shadow DOM 2277 from the theme's swatch size setting (default 24px). 2278 Swatch image is an <img> child (was a CSS background-image) so the index imageUrl sits in an 2279 HTML src attribute and can't break out of a url('...') CSS context â see report F4. 2280 */ 2281 .variant-selector-list__item { 2282 width: var(--swatch-card-size, 24px); 2283 height: var(--swatch-card-size, 24px); 2284 border-radius: 50%; 2285 border: 1px solid rgba(var(--text-color) / 0.2); 2286 padding: 0; 2287 cursor: pointer; 2288 overflow: hidden; 2289 background: rgba(var(--text-color) / 0.05); 2290 background-size: cover; 2291 background-position: center; 2292 background-repeat: no-repeat; 2293 flex-shrink: 0; 2294 position: relative; 2295 transition: border-color 0.2s; 2296 /* Fade in on remount to mask the flash when the library re-renders */ 2297 animation: hs-swatch-in 150ms ease-out; 2298 } 2299 @keyframes hs-swatch-in { 2300 from { opacity: 0; } 2301 to { opacity: 1; } 2302 } 2303 /* Swatch image â fills the circular button (clipped by overflow:hidden + border-radius:50%). 2304 pointer-events:none so clicks always register on the button itself. */ 2305 .variant-selector-list__item-img { 2306 width: 100%; 2307 height: 100%; 2308 object-fit: cover; 2309 display: block; 2310 pointer-events: none; 2311 } 2312 2313 .variant-selector-list__item:hover { 2314 border-color: rgba(var(--text-color) / 0.5); 2315 } 2316
2317 /* Selected state â outline ring matching native input:checked + .opt-label--swatch */ 2318 .variant-selector-list__item--selected { 2319 outline: 2px solid rgb(var(--text-color)); 2320 outline-offset: 2px; 2321 border-color: transparent; 2322 } 2323 2324 /* âââ Overflow label (+N) âââââââââââââââââââââââââââââââââââââââââââââ */ 2325 .variant-swatch-overflow { 2326 align-self: center; 2327 flex-shrink: 0; 2328 font-size: 18px; 2329 font-weight: 500; 2330 line-height: 1; 2331 color: rgb(var(--text-color)); 2332 pointer-events: none; 2333 margin-left: 8px; 2334 } 2335 2336</style> 2337 2338</template> 2339<template id="hawksearch-styles-visual-search"> 2340 2341 2342<style> 2343 2344 /* âââ 20. Visual search â camera icon button âââââââââââââââââââââââââââ */ 2345 /* 2346 Injected by JS into .unifiedsearch-field shadow DOM. 2347 Positioned absolutely at the right side of the search input, 2348 mirroring the close button pattern but offset to avoid overlap. 2349 Hidden when autocomplete is open (close button takes that space). 2350 */ 2351 .hs-vs-camera-btn { 2352 position: absolute; 2353 top: 0; 2354 right: 8px; 2355 z-index: 2; 2356 display: flex; 2357 align-items: center; 2358 justify-content: center; 2359 width: 44px; 2360 height: 100%; 2361 max-height: 50px; 2362 padding: 0; 2363 border: none; 2364 background: transparent; 2365 cursor: pointer; 2366 color: var(--hs-color-icon, #555); 2367 transition: color 0.15s ease; 2368 } 2369 .hs-vs-camera-btn:hover { 2370 color: var(--hs-color-emphasis, #111); 2371 } 2372 .hs-vs-camera-btn:focus-visible { 2373 outline: 2px solid rgb(var(--text-color)); 2374 outline-offset: -2px; 2375 border-radius: 4px; 2376 } 2377 .hs-vs-camera-btn svg { 2378 width: 20px; 2379 height: 20px; 2380 pointer-events: none; 2381 } 2382 /* Hide camera icon when autocomplete dropdown is open. 2383 The â close button lives inside the autocomplete shadow root and is 2384 only present when the dropdown is open â so this is the only case 2385 where the two controls overlap. On the search results page the input 2386 may have a value but the dropdown is closed, so the camera must remain 2387 visible. :host([data-has-value]) is intentionally NOT used here. */ 2388 :host([data-autocomplete-open]) .hs-vs-camera-btn { 2389 display: none; 2390 } 2391 2392 /* âââ 21. Visual search â drop area styling âââââââââââââââââââââââââââ */ 2393 /* 2394 The host element is hidden by default and becomes a fixed full-viewport 2395 overlay when JS sets [data-vs-open]. Using position:fixed on the host 2396 breaks out of ALL stacking contexts (the header's z-index:30 no longer 2397 constrains it). The overlay, close button, and drop area are all inside 2398 the same shadow root, so internal z-index ordering works naturally. 2399 */ 2400 2401 /* Host: hidden by default, full-viewport overlay when open */ 2402 :host(hawksearch-visualsearch-field) { 2403 display: none !important; 2404 } 2405 :host(hawksearch-visualsearch-field[data-vs-open]) { 2406 /* display:block (not flex) so the .visualsearch-field panel fills to its max-width:600px and 2407 stays centered via margin:auto â flex made it shrink-wrap to a narrow column (F17 regression). 2408 Landscape scrolling is handled by the host overflow-y + the panel's own max-height/overflow. */ 2409 display: block !important; 2410 overflow-y: auto !important; 2411 -webkit-overflow-scrolling: touch; 2412 position: fixed !important; 2413 top: 0 !important; 2414 left: 0 !important; 2415 right: 0 !important; 2416 bottom: 0 !important; 2417 z-index: 9999 !important; 2418 2419 /* Override library custom properties within this shadow root */ 2420 --container-border: none; 2421 --container-background: rgb(var(--bg-color)); 2422 --container-background--alternate: rgba(var(--btn-bg-color, var(--text-color)) / 0.05); 2423 --color-accent: rgb(var(--btn-bg-color, var(--text-color))); 2424 --color-accent-light: var(--hs-color-error-bg, #fef2f2); 2425 --padding-sm: 0; 2426 } 2427 2428 /* Overlay â covers full viewport behind the drop area */ 2429 .hs-vs-overlay { 2430 position: fixed; 2431 inset: 0; 2432 background: rgba(0, 0, 0, 0.4); 2433 z-index: 0; 2434 } 2435 2436 /* Close button â positioned inside the header bar */ 2437 .hs-vs-close { 2438 position: absolute; 2439 /* Track the panel's margin-top (clamp(16px,8vh,120px)) + ~20px so the X sits in the header's 2440 top-right corner on every viewport, matching the original 140px/120px relationship. */ 2441 top: calc(clamp(16px, 8vh, 120px) + 20px); 2442 right: max(8px, calc(50% - 290px)); 2443 z-index: 2; 2444 display: flex; 2445 align-items: center; 2446 justify-content: center; 2447 width: 32px; 2448 height: 32px; 2449 padding: 0; 2450 border: none; 2451 border-radius: 50%; 2452 background: transparent; 2453 cursor: pointer; 2454 color: rgba(var(--text-color) / 0.5); 2455 transition: color 0.15s ease, background-color 0.15s ease; 2456 } 2457 /* Expand the tap target to ~44px without changing the visible 32px button. */ 2458 .hs-vs-close::before { 2459 content: ''; 2460 position: absolute; 2461 inset: -6px; 2462 } 2463 .hs-vs-close:hover { 2464 color: rgb(var(--text-color)); 2465 background: rgba(var(--text-color) / 0.08); 2466 } 2467 .hs-vs-close svg { 2468 width: 16px; 2469 height: 16px; 2470 pointer-events: none; 2471 } 2472 2473 /* Error message */ 2474 .hs-vs-error { 2475 position: relative; 2476 z-index: 1; 2477 max-width: 600px; 2478 margin: 8px auto 0; 2479 padding: 10px 16px; 2480 font-size: 13px; 2481 color: var(--hs-color-error, #b91c1c); 2482 background: var(--hs-color-error-bg, #fef2f2); 2483 border: 1px solid var(--hs-color-error-border, #fecaca); 2484 border-radius: var(--input-border-radius, 8px); 2485 text-align: center; 2486 } 2487 .hs-vs-error[hidden] { display: none; } 2488 2489 /* Drop area â centered in viewport */ 2490 .visualsearch-field { 2491 position: relative !important; 2492 z-index: 1 !important; 2493 max-width: 600px !important; 2494 margin: clamp(16px, 8vh, 120px) auto !important; 2495 max-height: calc(100dvh - 32px) !important; 2496 padding: 0 !important; 2497 background: rgb(var(--bg-color)) !important; 2498 border: 1px solid rgba(var(--text-color) / 0.09) !important; 2499 border-radius: 4px !important; 2500 overflow: auto !important; 2501 box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12) !important; 2502 } 2503 /* Header title bar */ 2504 .hs-vs-header { 2505 display: flex !important;
2506 align-items: center !important; 2507 justify-content: center !important; 2508 padding: 20px 52px !important; 2509 border-bottom: 1px solid rgba(var(--text-color) / 0.08) !important; 2510 } 2511 .hs-vs-header__title { 2512 font-style: var(--heading-font-style, normal) !important; 2513 font-weight: var(--heading-font-weight, 800) !important; 2514 font-size: 22px !important; 2515 text-align: center !important; 2516 } 2517 .visualsearch-field__drop-area { 2518 margin: 20px !important; 2519 border: 2px dashed var(--hs-vs-drop-border, #c9a090) !important; 2520 border-radius: 2px !important; 2521 padding: 40px 32px !important; 2522 text-align: center !important; 2523 background: var(--hs-vs-drop-bg, #faf3f0) !important; 2524 transition: border-color 0.2s ease, background-color 0.2s ease !important; 2525 cursor: pointer !important; 2526 margin-bottom: 20px !important; 2527 } 2528 .visualsearch-field__drop-area:hover { 2529 border-color: var(--hs-vs-drop-border-hover, #a07060) !important; 2530 background: var(--hs-vs-drop-bg-hover, #f4ebe4) !important; 2531 } 2532 /* Active drag-over state â library class */ 2533 .visualsearch-field__drop-area.dragging-state { 2534 border-color: var(--hs-vs-drop-border-active, #8b5e52) !important; 2535 background: var(--hs-vs-drop-bg-active, #ede0da) !important; 2536 } 2537 /* Active drag-over state â JS-driven class (belt and suspenders) */ 2538 .visualsearch-field__drop-area[hawksearch-visualsearch-droparea].dragover, 2539 .visualsearch-field__drop-area:focus-within { 2540 border-color: var(--hs-vs-drop-border-active, #8b5e52) !important; 2541 background: var(--hs-vs-drop-bg-active, #ede0da) !important; 2542 } 2543 .visualsearch-field__drop-area__image-display { 2544 width: 200px !important; 2545 height: 200px !important; 2546 margin: 0 auto 16px !important; 2547 overflow: hidden !important; 2548 border-radius: 2px !important; 2549 } 2550 .visualsearch-field__drop-area__image-display img { 2551 width: 100% !important; 2552 height: 100% !important; 2553 object-fit: contain !important; 2554 } 2555 .visualsearch-field__drop-area__prompt-msg { 2556 display: block !important; 2557 font-size: 18px !important; 2558 font-weight: 700 !important; 2559 color: rgb(var(--text-color)) !important; 2560 margin: 16px 0 0 !important; 2561 line-height: 1.4 !important; 2562 } 2563 /* Format hint below prompt text */ 2564 .hs-vs-format-note { 2565 display: block !important; 2566 font-size: 13px !important; 2567 color: rgba(var(--text-color) / 0.55) !important; 2568 margin: 6px 0 0 !important; 2569 line-height: 1.5 !important; 2570 } 2571 /* Upload illustration icon */ 2572 .hs-vs-icon { 2573 display: flex !important; 2574 justify-content: center !important; 2575 margin-bottom: 0 !important; 2576 } 2577 .hs-vs-icon svg { 2578 width: 56px !important; 2579 height: 56px !important; 2580 } 2581 /* Hide icon when image preview is showing */ 2582 .visualsearch-field__drop-area__image-display:not(:empty) ~ .hs-vs-icon { 2583 display: none !important; 2584 } 2585 /* Search submit button â hidden until an image is loaded */ 2586 .hs-vs-search-btn { 2587 display: none !important; 2588 width: 240px !important; 2589 margin: 20px auto 0 !important; 2590 padding: 13px 24px !important; 2591 background: rgb(var(--btn-bg-color, var(--text-color))) !important; 2592 color: rgb(var(--btn-text-color, var(--bg-color))) !important; 2593 border: none !important; 2594 border-radius: 3px !important; 2595 font-family: var(--body-font-family, inherit) !important; 2596 font-size: 14px !important; 2597 font-weight: 700 !important; 2598 letter-spacing: 0.03em !important; 2599 cursor: pointer !important; 2600 transition: background-color 0.15s ease !important; 2601 } 2602 .hs-vs-search-btn:hover:not(:disabled) { 2603 background: rgb(var(--btn-bg-hover-color, var(--btn-bg-color, var(--text-color)))) !important; 2604 } 2605 .hs-vs-search-btn:disabled { 2606 opacity: 0.55 !important; 2607 cursor: default !important; 2608 } 2609 /* Show search button once an image is loaded into the display container */ 2610 .visualsearch-field__drop-area__image-display:not(:empty) ~ .hs-vs-search-btn { 2611 display: block !important; 2612 } 2613 .visualsearch-field__drop-area__upload-button { 2614 display: block !important; 2615 width: 240px !important; 2616 margin: 12px auto 0 !important; 2617 padding: 13px 24px !important; 2618 background: rgb(var(--btn-bg-color, var(--text-color))) !important; 2619 color: rgb(var(--btn-text-color, var(--bg-color))) !important; 2620 border-radius: 3px !important; 2621 font-family: var(--body-font-family, inherit) !important; 2622 font-size: 14px !important; 2623 font-weight: 700 !important; 2624 letter-spacing: 0.03em !important; 2625 text-transform: var(--heading-text-transform, none) !important; 2626 text-decoration: none !important; 2627 text-align: center !important; 2628 cursor: pointer !important; 2629 transition: background-color 0.15s ease !important; 2630 } 2631 .visualsearch-field__drop-area__upload-button:hover { 2632 background: rgb(var(--btn-bg-hover-color, var(--btn-bg-color, var(--text-color)))) !important; 2633 text-decoration: none !important; 2634 } 2635 .visualsearch-field__drop-area__upload-button input[type="file"] { 2636 position: absolute; 2637 width: 1px; 2638 height: 1px; 2639 overflow: hidden; 2640 clip: rect(0, 0, 0, 0); 2641 border: 0; 2642 } 2643 .visualsearch-field__drop-area__drop-msg { 2644 font-size: 12px !important; 2645 color: rgba(var(--text-color) / 0.4) !important; 2646 margin: 8px 0 0 !important; 2647 } 2648 2649</style> 2650 2651</template> 2652 2653 2654<template id="autocomplete-template"> 2655 2656 2657<button class="hs-autocomplete-close" type="button" aria-label="Close search"> 2658 <svg width="24" height="24" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5" fill="none" aria-hidden="true" focusable="false"> 2659 <path d="M5 19 19 5M5 5l14 14"/> 2660 </svg> 2661</button> 2662<div class="hs-autocomplete-overlay"></div> 2663<div class="hs-autocomplete" role="region"> 2664 2665 <!-- ââ Tab strip (visible only when content results exist) ââ --> 2666 {{#if content.results.length}} 2667 <div class="hs-autocomplete__tabs" role="tablist"> 2668 <button class="hs-autocomplete__tab hs-autocomplete__tab--active" data-tab="products" type="button" 2669 role="tab" aria-selected="true" tabindex="0" 2670 id="hs-tab-products" aria-controls="hs-panel-products">Products</button> 2671 <button class="hs-autocomplete__tab" data-tab="content" type="button" 2672 role="tab" aria-selected="false" tabindex="-1" 2673 id="hs-tab-content" aria-controls="hs-panel-content">Content</button> 2674 </div> 2675 {{/if}} 2676 2677 <!-- ââ Products tab panel ââ --> 2678 <div class="hs-autocomplete__tab-panel--products" id="hs-panel-products" role="tabpanel" aria-labelledby="{{#if content.results.length}}hs-tab-products{{/if}}"> 2679 {{#if products.results.length}} 2680 <div class="hs-autocomplete__products"> 2681 2682 <p class="hs-autocomplete__heading">Products</p> 2683 2684 {{#each products.results}} 2685 <a hawksearch-product="{{id}}" href="{{url}}" class="hs-autocomplete__item"> 2686 2687 <img 2688 hawksearch-image 2689 class="hs-autocomplete__item-image" 2690 src="{{imageUrl}}" 2691 alt="{{title}}" 2692 width="56" 2693 height="56" 2694 loading="lazy" 2695 > 2696 2697 <div> 2698 <p class="hs-autocomplete__item-title">{{title}}</p> 2699 2700 {{#unless (eq price undefined)}} 2701 <p class="hs-autocomplete__item-price"> 2702 {{#if (lt price salePrice)}}
2703 <span class="hs-autocomplete__item-price--sale">{{currency price}}</span> 2704 <span class="hs-autocomplete__item-price--was">{{currency salePrice}}</span> 2705 {{else}} 2706 <span>{{currency price}}</span> 2707 {{/if}} 2708 </p> 2709 {{/unless}} 2710 </div> 2711 2712 </a> 2713 {{/each}} 2714 2715 <!-- View All Results --> 2716 <div class="hs-autocomplete__view-all"> 2717 <a hawksearch-view-all href="/search"> 2718 View all search results 2719 <svg width="24" height="24" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5" fill="none" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M4.696 12h14.686m-7.007-7.5 7.5 7.5-7.5 7.5"/></svg> 2720 </a> 2721 </div> 2722 2723 </div> 2724 {{/if}} 2725 2726 <!-- Did You Mean â zero-results fallback (renders where products would be) --> 2727 {{#if productSuggestedQueries.results.length}} 2728 <div class="hs-autocomplete__dym"> 2729 <p class="hs-autocomplete__suggestions-heading">{{productSuggestedQueries.title}}</p> 2730 {{#each productSuggestedQueries.results}} 2731 <a hawksearch-query="{{query}}" href="{{url}}" class="hs-autocomplete__suggestion"> 2732 {{query}} 2733 </a> 2734 {{/each}} 2735 </div> 2736 {{/if}} 2737 2738 {{#if contentSuggestedQueries.results.length}} 2739 <div class="hs-autocomplete__dym"> 2740 <p class="hs-autocomplete__suggestions-heading">{{contentSuggestedQueries.title}}</p> 2741 {{#each contentSuggestedQueries.results}} 2742 <a hawksearch-query="{{query}}" href="{{url}}" class="hs-autocomplete__suggestion"> 2743 {{query}} 2744 </a> 2745 {{/each}} 2746 </div> 2747 {{/if}} 2748 2749 {{!-- Fallback: when products and all DYM are empty, show View All so the panel is never blank --}} 2750 {{#unless products.results.length}}{{#unless productSuggestedQueries.results.length}}{{#unless contentSuggestedQueries.results.length}} 2751 <div class="hs-autocomplete__view-all"> 2752 <a hawksearch-view-all href="/search"> 2753 View all search results 2754 <svg width="24" height="24" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5" fill="none" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M4.696 12h14.686m-7.007-7.5 7.5 7.5-7.5 7.5"/></svg> 2755 </a> 2756 </div> 2757 {{/unless}}{{/unless}}{{/unless}} 2758 </div> 2759 2760 <!-- ââ Content tab panel ââ --> 2761 {{#if content.results.length}} 2762 <div class="hs-autocomplete__tab-panel--content" id="hs-panel-content" role="tabpanel" aria-labelledby="hs-tab-content"> 2763 <p class="hs-autocomplete__heading">{{content.title}}</p> 2764 {{#each content.results}} 2765 <a hawksearch-content="{{id}}" href="{{url}}" class="hs-autocomplete__content-item"> 2766 {{title}} 2767 </a> 2768 {{/each}} 2769 </div> 2770 {{/if}} 2771 2772 <!-- ââ Suggestions Column (always in DOM; CSS hides when empty) ââ --> 2773 <div class="hs-autocomplete__suggestions"> 2774 2775 <!-- Category suggestions --> 2776 {{#if categories.results.length}} 2777 <p class="hs-autocomplete__suggestions-heading">{{categories.title}}</p> 2778 {{#each categories.results}} 2779 <a hawksearch-category-field="{{field}}" hawksearch-category-value="{{value}}" href="{{url}}" class="hs-autocomplete__suggestion"> 2780 {{title}} 2781 </a> 2782 {{/each}} 2783 {{/if}} 2784 2785 <!-- Popular search queries --> 2786 {{#if queries.results.length}} 2787 <p class="hs-autocomplete__suggestions-heading">{{queries.title}}</p> 2788 {{#each queries.results}} 2789 <a hawksearch-query="{{query}}" href="{{url}}" class="hs-autocomplete__suggestion"> 2790 {{query}} 2791 </a> 2792 {{/each}} 2793 {{/if}} 2794 2795 </div> 2796 2797</div> 2798</template> 2799 2800 2801<template id="hawksearch-result-item-template"> 2802<div class="search-results-list__item search-results-list__item--{{type}}"> 2803 <div class="card card--product h-full relative flex card--product-contained card--no-lines"> 2804 2805 {{!-- Image Area --}} 2806 <div class="card__media relative{{#if attributes.second_image_url}} has-hover-image{{/if}}"> 2807 <a hawksearch-link 2808 href="{{url}}" 2809 aria-label="{{title}}" 2810 class="media block relative js-prod-link" 2811 style="padding-top: 100.0%;" 2812 tabindex="-1" 2813 > 2814 <img 2815 hawksearch-image 2816 src="{{#if selectedVariant.imageUrl}}{{selectedVariant.imageUrl}}{{else}}{{imageUrl}}{{/if}}" 2817 alt="{{title}}" 2818 loading="lazy" 2819 fetchpriority="low" 2820 sizes="(max-width: 989px) calc(50vw - 8px), calc(25vw - 60px)" 2821 class="img-fit card__main-image" 2822 width="460" 2823 height="460" 2824 > 2825 {{#if attributes.second_image_url}} 2826 <img 2827 src="{{attributes.second_image_url.[0]}}" 2828 alt="" 2829 loading="lazy" 2830 class="img-fit card__hover-image" 2831 width="460" 2832 height="460" 2833 > 2834 {{/if}} 2835 </a> 2836 2837 {{!-- Badges â new-arrival + sale, stacked in one container (.product-label-wrapper is 2838 flex-wrap, like native product-label.liquid). New-arrival shows whenever product_tags 2839 contains "new-arrival". Sale is driven by the SAME effective sale state as the price 2840 block below (prefer the selected variant, fall back to top-level) so the badge and the 2841 struck price can never disagree. --}} 2842 <div class="product-label-container absolute"> 2843 <div class="product-label-wrapper flex"> 2844 {{#each attributes.product_tags}}{{#if (eq this "new-arrival")}}<span class="product-label product-label--new"><svg class="icon icon--star" width="14" height="14" viewBox="0 0 16 16" aria-hidden="true" focusable="false" role="presentation">
2844<path fill="currentColor" d="M8 1c.21 0 .4.13.47.33l1.62 4.54 4.92.1a.5.5 0 01.29.9l-3.92 2.9 1.42 4.58a.5.5 0 01-.75.56L8 12.17 3.95 14.9a.5.5 0 01-.75-.56l1.42-4.58L.7 6.87a.5.5 0 01.29-.9l4.92-.1 1.62-4.54A.5.5 0 018 1zm0 2L6.74 6.52a.5.5 0 01-.46.33l-3.8.08L5.5 9.17a.5.5 0 01.18.55l-1.1 3.56 3.14-2.13a.5.5 0 01.56 0l3.15 2.13-1.1-3.56a.5.5 0 01.17-.55l3.02-2.23-3.8-.08a.5.5 0 01-.46-.33L8 2.99z"></path></svg>New Arrival</span>{{/if}}{{/each}} 2845 {{#if selectedVariant.price}} 2846 {{#if (lt selectedVariant.price selectedVariant.salePrice)}} 2847 <span class="product-label product-label--sale">{{strings.sale}}</span> 2848 {{/if}} 2849 {{else}} 2850 {{#if (lt price salePrice)}} 2851 <span class="product-label product-label--sale">{{strings.sale}}</span> 2852 {{/if}} 2853 {{/if}} 2854 </div> 2855 </div> 2856 </div> 2857 2858 {{!-- Info Area --}} 2859 <div class="card__info-container flex flex-col flex-auto relative"> 2860 <div class="card__info w-full"> 2861 <div class="card__info-inner flex flex-col h-full w-full"> 2862 2863 {{!-- Rating â always rendered so CSS min-height reserves the row on unrated cards --}} 2864 <div class="hs-rating-row"> 2865 {{#if rating}} 2866 <hawksearch-rating rating="{{rating}}"></hawksearch-rating> 2867 <p class="ratings-count">{{number rating 1}} {{#if attributes.review_count}}({{attributes.review_count.[0]}}){{/if}}</p> 2868 {{/if}} 2869 </div> 2870 2871 <div class="card__title-wrapper"> 2872 <p class="card__title font-bold mt-1 mb-0"> 2873 <a hawksearch-link href="{{url}}" class="card-link text-current js-prod-link">{{title}}</a> 2874 </p> 2875 </div> 2876 2877 <hawksearch-variant-selector></hawksearch-variant-selector> 2878 2879 {{!-- Price â matches price.liquid structure. Wrapped in flex grow items-end when 2880 card_price_bottom is on, mirroring product-card.liquid L525-529 â pins the price 2881 to the card bottom independent of the variant-selector's rendered height. --}} 2882 <div class="flex grow items-end"> 2883 {{#unless (eq price undefined)}} 2884 {{#if selectedVariant.price}} 2885 <div class="price{{#if (lt selectedVariant.price selectedVariant.salePrice)}} price--on-sale{{/if}}"> 2886 <div class="price__default"> 2887 {{#if (lt selectedVariant.price selectedVariant.salePrice)}} 2888 <strong class="price__current">{{currency selectedVariant.price}}</strong> 2889 <s class="price__was">{{currency selectedVariant.salePrice}}</s> 2890 {{else}} 2891 <strong class="price__current">{{currency selectedVariant.price}}</strong> 2892 {{/if}} 2893 </div> 2894 </div> 2895 {{else}} 2896 <div class="price{{#if (lt price salePrice)}} price--on-sale{{/if}}"> 2897 <div class="price__default"> 2898 {{#if (lt price salePrice)}} 2899 <strong class="price__current">{{currency price}}</strong> 2900 <s class="price__was">{{currency salePrice}}</s> 2901 {{else}} 2902 <strong class="price__current">{{currency price}}</strong> 2903 {{/if}} 2904 </div> 2905 </div> 2906 {{/if}} 2907 {{/unless}} 2908 </div> 2909 2910 2911 2912 2913 </div> 2914 </div> 2915 2916 {{!-- CTA â gated on settings.enable_quick_add. 2917 Three branches: 2918 1. Personalized â View Details only (PDP collects personalization properties). 2919 2. Single-variant AND selectedVariant not "in stock" â View Details only 2920 (OOS single-variants route to PDP, which carries any ship-date/backorder messaging). 2921 3. Otherwise (multi-variant, or single-variant in stock) â ATC button. 2922 Multi-variant cards stay on the ATC path even when selectedVariant is OOS, 2923 because the variant drawer can surface in-stock siblings. 2924 Stock gate uses the affirmative "in stock" allowlist so any unexpected 2925 availability value (new index states, undefined) routes safely to PDP. 2926 hawksearch-atc-handler keys off .hs-atc-btn, so View Details paths bypass ATC. --}} 2927 2928 2929 {{#if attributes.is_personalized.[0]}} 2930 <div class="card__quick-add mob:card__quick-add--below"> 2931 <a hawksearch-link href="{{url}}" class="btn btn--primary w-full">View Details</a> 2932 </div> 2933 {{else}} 2934 {{#unless variants.[1]}} 2935 {{#unless (eq selectedVariant.attributes.availability.[0] "in stock")}} 2936 <div class="card__quick-add mob:card__quick-add--below"> 2937 <a hawksearch-link href="{{url}}" class="btn btn--primary w-full">View Details</a> 2938 </div> 2939 {{else}} 2940 <div class="card__quick-add mob:card__quick-add--below"> 2941 <div class="alert mb-8 bg-error-bg text-error-text js-form-error text-start" role="alert" hidden></div> 2942 2943 <button 2944 type="button" 2945 class="btn btn--primary w-full hs-atc-btn" 2946 data-product-url="{{url}}" 2947 data-multi-variant="{{#if variants.[1]}}true{{/if}}" 2948 data-variant-id="{{selectedVariant.id}}" 2949 data-product-id="{{attributes.product_id.[0]}}" 2950 data-selected-color="{{selectedVariant.color.name}}" 2951 data-price="{{selectedVariant.price}}" 2952 aria-haspopup="{{#if variants.[1]}}dialog{{else}}false{{/if}}" 2953 >
2954 <span class="quick-add-btn-icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M12.12 20.44H5.6V9.56h12.8v3.73c.06.4.4.69.8.7.44 0 .8-.35.8-.8v-4.5a.792.792 0 0 0-.8-.69H17V6.5C16.9 4 14.7 2 12 2S7 4.09 7 6.67V8H4.71c-.4.04-.71.37-.71.78v12.53a.8.8 0 0 0 .8.69h7.43c.38-.06.67-.39.67-.78 0-.43-.35-.78-.78-.78ZM8.66 6.67c0-1.72 1.49-3.11 3.33-3.11s3.33 1.39 3.33 3.11V8H8.65V6.67Z"/><path d="M20 17.25h-2.4v-2.5a.817.817 0 0 0-.8-.7c-.44 0-.8.36-.8.8v2.4h-2.5c-.4.06-.7.4-.7.8 0 .44.36.8.8.8H16v2.5c.06.4.4.7.8.7.44 0 .8-.36.8-.8v-2.4h2.5c.4-.06.69-.4.7-.8 0-.44-.35-.8-.8-.8Z"/></svg></span> 2955 <span class="quick-add-btn-text">{{#if variants.[1]}}Choose options{{else}}Add to Cart{{/if}}</span> 2956 </button> 2957 2958 <a hawksearch-link href="{{url}}" class="btn btn--secondary quick-add-view-btn">View Details</a> 2959 </div> 2960 {{/unless}} 2961 {{else}} 2962 <div class="card__quick-add mob:card__quick-add--below"> 2963 <div class="alert mb-8 bg-error-bg text-error-text js-form-error text-start" role="alert" hidden></div> 2964 2965 <button 2966 type="button" 2967 class="btn btn--primary w-full hs-atc-btn" 2968 data-product-url="{{url}}" 2969 data-multi-variant="{{#if variants.[1]}}true{{/if}}" 2970 data-variant-id="{{selectedVariant.id}}" 2971 data-product-id="{{attributes.product_id.[0]}}" 2972 data-selected-color="{{selectedVariant.color.name}}" 2973 data-price="{{selectedVariant.price}}" 2974 aria-haspopup="{{#if variants.[1]}}dialog{{else}}false{{/if}}" 2975 > 2976 <span class="quick-add-btn-icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M12.12 20.44H5.6V9.56h12.8v3.73c.06.4.4.69.8.7.44 0 .8-.35.8-.8v-4.5a.792.792 0 0 0-.8-.69H17V6.5C16.9 4 14.7 2 12 2S7 4.09 7 6.67V8H4.71c-.4.04-.71.37-.71.78v12.53a.8.8 0 0 0 .8.69h7.43c.38-.06.67-.39.67-.78 0-.43-.35-.78-.78-.78ZM8.66 6.67c0-1.72 1.49-3.11 3.33-3.11s3.33 1.39 3.33 3.11V8H8.65V6.67Z"/><path d="M20 17.25h-2.4v-2.5a.817.817 0 0 0-.8-.7c-.44 0-.8.36-.8.8v2.4h-2.5c-.4.06-.7.4-.7.8 0 .44.36.8.8.8H16v2.5c.06.4.4.7.8.7.44 0 .8-.36.8-.8v-2.4h2.5c.4-.06.69-.4.7-.8 0-.44-.35-.8-.8-.8Z"/></svg></span> 2977 <span class="quick-add-btn-text">{{#if variants.[1]}}Choose options{{else}}Add to Cart{{/if}}</span> 2978 </button> 2979 2980 <a hawksearch-link href="{{url}}" class="btn btn--secondary quick-add-view-btn">View Details</a> 2981 </div> 2982 {{/unless}} 2983 {{/if}} 2984 2985 2986 2987 </div> 2988 </div> 2989</div> 2990 2991</template><template id="hawksearch-variant-selector-template"> 2992{{#if items.length}} 2993 {{#with (arrayFilterObjects items "color") as |colorItems|}} 2994 {{!-- Gate the .hs-variant-selector wrapper (not just the swatch list) on colorItems so that 2995 products whose variants carry no colour dimension â e.g. size-only House/Garden flags â 2996 render nothing here and reserve no vertical space. This is a colour-swatch picker only; 2997 size variants are chosen via the "Choose options" quick-add drawer. --}} 2998 {{#if colorItems.length}} 2999 <div class="hs-variant-selector"> 3000 <div class="variant-selector-list" data-total="{{colorItems.length}}"> 3001 {{#each colorItems}} 3002 {{#if (lt @index 4)}} 3003 <button 3004 type="button" 3005 hawksearch-variant="{{id}}" 3006 class="variant-selector-list__item{{attribute ' variant-selector-list__item--selected' (eq id @root.selectedItem.id)}}" 3007 title="{{color.name}}" 3008 aria-label="{{color.name}}" 3009 data-color="{{color.name}}" 3010 data-variant-id="{{id}}" 3011 data-price="{{price}}" 3012 >{{#if imageUrl}}<img class="variant-selector-list__item-img" src="{{imageUrl}}" alt="" loading="lazy">{{/if}}</button> 3013 {{/if}} 3014 {{/each}} 3015 {{#if (gt colorItems.length 4)}}
3016 <span class="variant-swatch-overflow">+{{subtract colorItems.length 4}}</span> 3017 {{/if}} 3018 </div> 3019 </div> 3020 {{/if}} 3021 {{/with}} 3022{{/if}} 3023 3024</template> 3025 3026 3027<template id="hawksearch-search-results-template"><hawksearch-modified-query></hawksearch-modified-query> 3028<hawksearch-query-suggestions></hawksearch-query-suggestions> 3029<div class="hs-toolbar"> 3030 <div class="hs-toolbar__filter"> 3031 <button type="button" class="hs-toolbar__filter-btn" aria-label="Show or hide filters"> 3032 <span class="hs-toolbar__filter-label-desktop">Filter</span> 3033 <span class="hs-toolbar__filter-label-mobile">Filter & Sort</span> 3034 <svg width="20" height="20" viewBox="0 0 20 20" stroke-width="1.25" stroke="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path stroke-linecap="round" stroke-linejoin="round" d="M1 6h18M1 14h18"/><circle cx="7" cy="6" r="3"/><circle cx="13" cy="14" r="3"/></svg> 3035 </button> 3036 </div> 3037 <div class="hs-toolbar__sort"> 3038 <hawksearch-sorting></hawksearch-sorting> 3039 </div> 3040 <div class="hs-toolbar__page-size"> 3041 <hawksearch-page-size></hawksearch-page-size> 3042 </div> 3043</div> 3044<div class="row"> 3045 <div class="column column--12 column-md--4"> 3046 <div class="hs-mobile-sort"> 3047 <hawksearch-sorting></hawksearch-sorting> 3048 </div> 3049 <hawksearch-content-zone name="LeftTop"></hawksearch-content-zone> 3050 <hawksearch-content-zone name="BannerLeftTop"></hawksearch-content-zone> 3051 <hawksearch-content-zone name="FeaturedLeftTop"></hawksearch-content-zone> 3052 <hawksearch-facets-list></hawksearch-facets-list> 3053 <hawksearch-content-zone name="LeftBottom"></hawksearch-content-zone> 3054 <hawksearch-content-zone name="BannerLeftBottom"></hawksearch-content-zone> 3055 <hawksearch-content-zone name="FeaturedLeftBottom"></hawksearch-content-zone> 3056 </div> 3057 <div class="column column--12 column-md--8"> 3058 <hawksearch-content-zone name="Top"></hawksearch-content-zone> 3059 <hawksearch-content-zone name="BannerTop"></hawksearch-content-zone> 3060 <hawksearch-content-zone name="FeaturedTop"></hawksearch-content-zone> 3061 <hawksearch-content-zone name="Top2"></hawksearch-content-zone> 3062 <hawksearch-content-zone name="BannerTop2"></hawksearch-content-zone> 3063 <hawksearch-content-zone name="FeaturedTop2"></hawksearch-content-zone> 3064 <hawksearch-tabs></hawksearch-tabs> 3065 <hawksearch-selected-facets></hawksearch-selected-facets> 3066 <hawksearch-search-results-list></hawksearch-search-results-list> 3067 <div class="hs-pagination-bottom"> 3068 <hawksearch-pagination></hawksearch-pagination> 3069 </div> 3070 <hawksearch-content-zone name="Bottom"></hawksearch-content-zone> 3071 <hawksearch-content-zone name="BannerBottom"></hawksearch-content-zone> 3072 <hawksearch-content-zone name="FeaturedBottom"></hawksearch-content-zone> 3073 <hawksearch-content-zone name="Bottom2"></hawksearch-content-zone> 3074 <hawksearch-content-zone name="BannerBottom2"></hawksearch-content-zone> 3075 <hawksearch-content-zone name="FeaturedBottom2"></hawksearch-content-zone> 3076 </div> 3077</div> 3078</template> 3079 3080 3081<template id="hawksearch-visual-search-template"> 3082<div class="visualsearch-field"> 3083 <div class="hs-vs-header"> 3084 <span class="hs-vs-header__title">Search by image</span> 3085 </div> 3086 <div class="visualsearch-field__drop-area" hawksearch-visualsearch-droparea> 3087 <div class="visualsearch-field__drop-area__image-display" hawksearch-visualsearch-display></div> 3088 <div class="hs-vs-icon" aria-hidden="true"> 3089 <svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg"> 3090 <rect width="56" height="56" rx="4" fill="#f0ddd6"/> 3091 <rect x="10" y="14" width="36" height="28" rx="2" fill="none" stroke="#a07060" stroke-width="1.5"/> 3092 <circle cx="20" cy="22" r="3" fill="#a07060"/> 3093 <polyline points="10,34 20,24 28,32 34,26 46,38" fill="none" stroke="#a07060" stroke-width="1.5" stroke-linejoin="round"/> 3094 <circle cx="40" cy="40" r="8" fill="#b07868"/> 3095 <line x1="40" y1="36" x2="40" y2="44" stroke="white" stroke-width="1.5" stroke-linecap="round"/> 3096 <line x1="36" y1="40" x2="44" y2="40" stroke="white" stroke-width="1.5" stroke-linecap="round"/> 3097 </svg> 3098 </div> 3099 <p class="visualsearch-field__drop-area__prompt-msg">{{strings.dragImageMessage}}</p> 3100 <p class="hs-vs-format-note">JPG, PNG, WEBP â up to 4 MB</p> 3101 <button type="button" class="hs-vs-search-btn" disabled>Searching…</button> 3102 <label class="visualsearch-field__drop-area__upload-button"> 3103 <input hawksearch-visualsearch-fileinput type="file" accept=".jpg,.jpeg,.png,.webp" /> 3104 {{strings.uploadImageMessage}} 3105 </label> 3106 <p class="visualsearch-field__drop-area__drop-msg">{{strings.dropImageMessage}}</p> 3107 </div> 3108</div> 3109 3110</template> 3111 3112 3113
3114<script type="text/javascript"> 3115 window._hsDebug = new URLSearchParams(location.search).has('hs_debug'); 3116 3117 // Shared dual-host resolver for the results element (direct /search vs landing-page-wrapped). 3118 // Defined here in config (which loads before the handler snippets) so each handler doesn't 3119 // re-implement the fallback â one that omits it silently no-ops on landing pages. 3120 window.HSShadow = window.HSShadow || {}; 3121 window.HSShadow.resolveResults = function () { 3122 let el = document.querySelector('hawksearch-search-results'); 3123 if (!el) { 3124 const lp = document.querySelector('hawksearch-landing-page'); 3125 if (lp && lp.shadowRoot) el = lp.shadowRoot.querySelector('hawksearch-search-results'); 3126 } 3127 return el; 3128 }; 3129 3130 // HawkSearch.init() and the after-search swatch-overflow listener below both register inside 3131 // this handler; guard against a re-fired hawksearch:loaded so they bind exactly once. 3132 let hsInitDone = false; 3133 addEventListener('hawksearch:loaded', () => { 3134 if (hsInitDone) return; 3135 hsInitDone = true; 3136 HawkSearch.init({ 3137 clientId: '84ad9ef370514a8a9062ccf39b5f2c20', 3138 formatting: { 3139 currencyIsoCode: 'USD', 3140 cultureIsoCode: 'en-US', 3141 }, 3142 search: { 3143 url: '/search', 3144 endpointUrl: 'https://myevergreen.searchapi-na.hawksearch.com', 3145 // Map Shopify's ?q= URL convention to the library's keyword param. 3146 // Without this, the library's default expects ?query= and treats unknown params (including ?q=) as facet selections â so any inbound URL using Shopify's standard search format (Google results, bookmarks, native forms, app integrations) returned the entire catalog instead of keyword-filtered results. Verified live via DevTools: ?q=towels was sending RequestType=DefaultSearch with no Keyword and getting 8,714 results back instead of ~181. 3147 queryStringMappings: { 3148 query: 'q', 3149 }, 3150 itemTypes: { 3151 // The index 'category' field contains category names (e.g. "Wind Spinners"), 3152 // not "item"/"product", so the library default productValues never matches. 3153 // Setting default: 'product' ensures all results render as product cards. 3154 default: 'product', 3155 }, 3156 }, 3157 tracking: { 3158 enabled: true, 3159 endpointUrl: 'https://myevergreen.tracking-na.hawksearch.com', 3160 }, 3161 recommendations: { 3162 endpointUrl: 'https://myevergreen.recs-na.hawksearch.com', 3163 }, 3164 autocomplete: { 3165 endpointUrl: 'https://myevergreen.searchapi-na.hawksearch.com', 3166 minCharacterCount: 3, 3167 recommendationsEnabled: true, 3168 }, 3169 fieldMappings: { 3170 url: 'url', 3171 title: 'title', 3172 description: 'description', 3173 imageUrl: 'imageurl', 3174 rating: 'average_rating', 3175 type: 'product_type', 3176 }, 3177 variants: { 3178 enabled: true, 3179 // trackUsingVariant:false â tracking (Click, RecommendationClick) sends the document primary 3180 // key = parent product_id (= Shopify handle), NOT the Shopify variant id. The index primary 3181 // key is product_id; variant ids are not primary keys, so per HawkSearch's parent-child rule 3182 // tracking must send the parent. /cart/add.js still uses the variant id. 3183 // See .claude/hawksearch-tracking-fix-id-alignment.md. 3184 trackUsingVariant: false, 3185 fieldMappings: { 3186 id: 'variant_id', 3187 url: 'variant_url', 3188 imageUrl: 'variant_image_url', 3189 price: 'price', 3190 salePrice: 'compare_at_price', 3191 sku: 'sku', 3192 color: { 3193 name: 'color', 3194 }, 3195 }, 3196 }, 3197 css: { 3198 customStyles: [ 3199 'hawksearch-styles-global', 3200 'hawksearch-styles-badges-buttons', 3201 'hawksearch-styles-search-field', 3202 'hawksearch-styles-autocomplete', 3203 'hawksearch-styles-recommendations', 3204 'hawksearch-styles-content-zones', 3205 'hawksearch-styles-toolbar', 3206 'hawksearch-styles-variants', 3207 'hawksearch-styles-visual-search', 3208 ] 3209 }, 3210 components: { 3211 'unifiedsearch-field': {
3212 strings: { 3213 placeholder: ['Search for Sassafras Switch Mats', 'Browse House Flags', 'Find popular porch leaners'], 3214 }, 3215 }, 3216 'autocomplete': { 3217 template: 'autocomplete-template', 3218 }, 3219 'search-results': { 3220 template: 'hawksearch-search-results-template', 3221 }, 3222 'search-results-item': { 3223 template: 'hawksearch-result-item-template', 3224 }, 3225 'recommendations-item': { 3226 template: 'hawksearch-result-item-template', 3227 }, 3228 'variant-selector': { 3229 template: 'hawksearch-variant-selector-template', 3230 }, 3231 'visualsearch-field': { 3232 template: 'hawksearch-visual-search-template', 3233 strings: { 3234 dragImageMessage: 'Drag a product image here or', 3235 uploadImageMessage: 'upload a photo', 3236 dropImageMessage: 'Drop your image here', 3237 errorMessage: 'Could not process image. Try a JPG, PNG, or WEBP under 4 MB.', 3238 }, 3239 }, 3240 }, 3241 }); 3242 3243 // Mark the search field as rendered once its shadow DOM contains an input. 3244 // CSS uses :not([data-hs-rendered]) to keep the placeholder visible during 3245 // the ~1s gap between element definition and HawkSearch's first render. 3246 const searchEl = document.querySelector('hawksearch-unifiedsearch-field'); 3247 if (searchEl) { 3248 let markRenderedRetries = 0; 3249 const MARK_RENDERED_MAX_RETRIES = 60; 3250 const markRendered = () => { 3251 if (searchEl.shadowRoot?.querySelector('input')) { 3252 searchEl.setAttribute('data-hs-rendered', ''); 3253 } else if (++markRenderedRetries < MARK_RENDERED_MAX_RETRIES) { 3254 requestAnimationFrame(markRendered); 3255 } else if (window._hsDebug) { 3256 console.warn('[HS] markRendered: gave up after ' + MARK_RENDERED_MAX_RETRIES + ' frames'); 3257 } 3258 }; 3259 customElements.whenDefined('hawksearch-unifiedsearch-field').then(markRendered); 3260 } 3261 3262 // updateInRoot: walks all nested shadow roots from `root` and patches 3263 // .variant-swatch-overflow text. Hoisted so the MutationObserver callback 3264 // can reference it without a closure over the setTimeout. 3265 function updateInRoot(root) { 3266 if (!root) return; 3267 root.querySelectorAll('.variant-swatch-overflow').forEach(function(overflow) { 3268 const list = overflow.closest('.variant-selector-list'); 3269 if (!list) return; 3270 const total = parseInt(list.dataset.total || '0', 10); 3271 overflow.textContent = total > 4 ? '+' + (total - 4) : '+'; 3272 }); 3273 root.querySelectorAll('*').forEach(function(el) { 3274 if (el.shadowRoot) updateInRoot(el.shadowRoot); 3275 }); 3276 } 3277 3278 let swatchObserver = null; 3279 3280 // Fill in swatch overflow button text (+N) after search renders. 3281 // Uses MutationObserver instead of a fixed 300ms delay so it fires as soon 3282 // as .variant-swatch-overflow elements are present, even on throttled CPUs. 3283 // hawksearch-variant-selector elements are nested inside multiple shadow roots â 3284 // document.querySelectorAll() cannot reach them, so we walk shadow roots manually 3285 // inside the observer callback. Disconnects any in-flight observer before creating 3286 // a new one so rapid searches don't produce overlapping update calls. 3287 // The visible-swatch cap is single-sourced from the Liquid variable hs_swatch_cap (set where the 3288 // variant-selector template is registered above); both this observer and the template consume it. 3289 window.addEventListener('hawksearch:after-search-executed', function updateSwatchOverflow() { 3290 // Scope to hawksearch-search-results shadow root â resolve each time to 3291 // support both direct and landing-page host patterns. 3292 const resultsEl = window.HSShadow.resolveResults(); 3293 if (!resultsEl || !resultsEl.shadowRoot) return; 3294 3295 if (swatchObserver) { 3296 swatchObserver.disconnect(); 3297 swatchObserver = null; 3298 } 3299 3300 const targetRoot = resultsEl.shadowRoot; 3301 swatchObserver = new MutationObserver(function(mutations, obs) { 3302 // MutationObserver cannot pierce shadow boundaries, so walk manually 3303 // to check if .variant-swatch-overflow elements have rendered yet. 3304 let found = false;
3305 (function checkInRoot(root) { 3306 if (found || !root) return; 3307 if (root.querySelector('.variant-swatch-overflow')) { found = true; return; } 3308 root.querySelectorAll('*').forEach(function(el) { if (el.shadowRoot) checkInRoot(el.shadowRoot); }); 3309 })(targetRoot); 3310 if (!found) return; 3311 3312 obs.disconnect(); 3313 swatchObserver = null; 3314 updateInRoot(targetRoot); 3315 }); 3316 swatchObserver.observe(targetRoot, { childList: true, subtree: true }); 3317 }); 3318 }); 3319</script>
3319<script type="text/javascript"> 3320 /** 3321 * Autocomplete active-state bridge and close-button handler. 3322 * 3323 * 1. Watches for the autocomplete shadow DOM content to appear/disappear 3324 * via MutationObserver and toggles [data-autocomplete-open] on 3325 * <hawksearch-unifiedsearch-field>. CSS in hawksearch-styles-search-field.liquid 3326 * uses :host([data-autocomplete-open]) to style the active input state. 3327 * 3328 * 2. Handles clicks on .hs-autocomplete-close (the â button rendered in the 3329 * autocomplete template). Clears the input value and dispatches an input 3330 * event so Hawksearch closes the autocomplete. 3331 */ 3332 (function () { 3333 let setupDone = false; 3334 let setupRetries = 0; 3335 const SETUP_MAX_RETRIES = 60; 3336 let observeAcRetries = 0; 3337 3338 function setup() { 3339 if (setupDone) return; // Entry guard â a second early hawksearch:loaded fire self-cancels once the first chain completes 3340 const field = document.querySelector('hawksearch-unifiedsearch-field'); 3341 if (!field || !field.shadowRoot) { 3342 if (++setupRetries < SETUP_MAX_RETRIES) requestAnimationFrame(setup); 3343 else if (window._hsDebug) console.warn('[HS] autocomplete setup: gave up after ' + SETUP_MAX_RETRIES + ' frames'); 3344 return; 3345 } 3346 3347 // Verify that the shadow root has the expected children before proceeding. 3348 const _input = field.shadowRoot.querySelector('input[type="text"]'); 3349 const _ac = field.shadowRoot.querySelector('hawksearch-autocomplete'); 3350 if (!_input || !_ac) { 3351 if (++setupRetries < SETUP_MAX_RETRIES) requestAnimationFrame(setup); 3352 else if (window._hsDebug) console.warn('[HS] autocomplete setup: gave up after ' + SETUP_MAX_RETRIES + ' frames'); 3353 return; 3354 } 3355 3356 // --- Autocomplete open/close state --- 3357 // checkOpen always re-queries input and ac from field.shadowRoot. 3358 // HawkSearch replaces the search field shadow content on the results page 3359 // (to pre-populate the input with the current query), making any cached 3360 // element references stale. Re-querying each time keeps state correct 3361 // regardless of how many times HawkSearch re-renders the field. 3362 function checkOpen() { 3363 const input = field.shadowRoot.querySelector('input[type="text"]'); 3364 const ac = field.shadowRoot.querySelector('hawksearch-autocomplete'); 3365 if (!input || !ac) return; 3366 3367 const acShadow = ac.shadowRoot; 3368 const isOpen = acShadow && acShadow.querySelector('.hs-autocomplete'); 3369 if (isOpen) { 3370 field.setAttribute('data-autocomplete-open', ''); 3371 } else { 3372 field.removeAttribute('data-autocomplete-open'); 3373 } 3374 3375 // Toggle data-has-value on both the autocomplete element (for close 3376 // button visibility) and the field host (for camera button visibility). 3377 if (input.value.trim()) { 3378 ac.setAttribute('data-has-value', ''); 3379 field.setAttribute('data-has-value', ''); 3380 } else { 3381 ac.removeAttribute('data-has-value'); 3382 field.removeAttribute('data-has-value'); 3383 } 3384 3385 // Toggle data-suggestions-empty on .hs-autocomplete so CSS can 3386 // collapse the grid to single-column when suggestions are empty. 3387 if (isOpen) { 3388 const suggestions = isOpen.querySelector('.hs-autocomplete__suggestions'); 3389 const hasSuggestions = suggestions && suggestions.querySelector('.hs-autocomplete__suggestions-heading'); 3390 if (hasSuggestions) { 3391 isOpen.removeAttribute('data-suggestions-empty'); 3392 } else { 3393 isOpen.setAttribute('data-suggestions-empty', ''); 3394 } 3395 3396 // Decode URL-encoded + as spaces in popular query suggestions. 3397 // queries.results[].query is stored URL-encoded in the index; 3398 // DYM (productSuggestedQueries) and categories are not affected. 3399 acShadow.querySelectorAll('[hawksearch-query]').forEach(function (el) { 3400 if (el.textContent.indexOf('+') !== -1) { 3401 el.textContent = el.textContent.replace(/\+/g, ' '); 3402 } 3403 }); 3404 } 3405 } 3406 3407 // observeAc sets up a MutationObserver on the current ac.shadowRoot. 3408 // Uses a guard so re-calling it (e.g. after a re-render) doesn't create 3409 // duplicate observers â it disconnects the previous one first. 3410 let acObserver = null; 3411 let observedAcShadow = null; 3412 3413 function observeAc() { 3414 const ac = field.shadowRoot.querySelector('hawksearch-autocomplete'); 3415 if (!ac) { if (++observeAcRetries < SETUP_MAX_RETRIES) requestAnimationFrame(observeAc); return; } 3416 if (!ac.shadowRoot) { if (++observeAcRetries < SETUP_MAX_RETRIES) requestAnimationFrame(observeAc); return; } 3417 observeAcRetries = 0; 3418 // Already observing this exact shadow root â nothing to do. 3419 if (ac.shadowRoot === observedAcShadow) return; 3420 if (acObserver) acObserver.disconnect(); 3421 observedAcShadow = ac.shadowRoot; 3422 acObserver = new MutationObserver(checkOpen); 3423 acObserver.observe(observedAcShadow, { childList: true, subtree: true }); 3424 checkOpen(); // initial check with the new element 3425 } 3426 setupDone = true; 3427 observeAc(); 3428
3429 // When HawkSearch re-renders the search field shadow root (on the results 3430 // page it replaces the wrapper to pre-populate the input), hawksearch-autocomplete 3431 // is replaced with a new element. Re-run observeAc so we observe the new 3432 // ac.shadowRoot rather than the now-detached old one. 3433 new MutationObserver(observeAc).observe(field.shadowRoot, { 3434 childList: true, 3435 subtree: true, 3436 }); 3437 3438 // Fallback: also check on input events (covers edge cases where 3439 // MutationObserver misses a shadow DOM swap). input event is composed:true 3440 // so attaching to field (the host element) fires even after re-renders. 3441 // 3442 // When the field is emptied, call dismissAutocomplete() rather than 3443 // manipulating data-autocomplete-open directly. This closes the dropdown 3444 // DOM first, then the MutationObserver removes data-autocomplete-open â 3445 // both change together so the border ring and dropdown disappear in sync. 3446 field.addEventListener('input', function () { 3447 const inp = field.shadowRoot && field.shadowRoot.querySelector('input[type="text"]'); 3448 if (inp && !inp.value.trim()) { 3449 dismissAutocomplete(false, true); 3450 } else { 3451 setTimeout(checkOpen, 150); 3452 } 3453 }); 3454 3455 // On Enter, strip the active-state attributes immediately so the 3456 // ::before border ring and box-shadow don't persist during the brief 3457 // gap between submit and the MutationObserver detecting the shadow DOM 3458 // being cleared. checkOpen() can't be used here â the input still has 3459 // text so it would re-add data-autocomplete-open after seeing the shadow 3460 // DOM still populated. keydown is composed:true so it bubbles from the 3461 // input inside the shadow root to the host element. 3462 field.addEventListener('keydown', function (e) { 3463 if (e.key !== 'Enter') return; 3464 field.removeAttribute('data-autocomplete-open'); 3465 field.removeAttribute('data-has-value'); 3466 const ac = field.shadowRoot && field.shadowRoot.querySelector('hawksearch-autocomplete'); 3467 if (ac) ac.removeAttribute('data-has-value'); 3468 }); 3469 } 3470 3471 addEventListener('hawksearch:loaded', function () { 3472 if (!setupDone) { setupRetries = 0; observeAcRetries = 0; requestAnimationFrame(setup); } 3473 }); 3474 3475 // --- Dismiss autocomplete helper --- 3476 // Shared by the close button (â), overlay click-outside, and visual search handlers. 3477 // clearInput: true clears the text (â button), false keeps it (overlay dismiss). 3478 // keepFocus: true keeps the input focused (used when the field is emptied by keyboard). 3479 // Exposed on window so the visual search IIFE can call it. 3480 window.dismissAutocomplete = dismissAutocomplete; 3481 function dismissAutocomplete(clearInput, keepFocus) { 3482 const field = document.querySelector('hawksearch-unifiedsearch-field'); 3483 if (!field || !field.shadowRoot) return; 3484 const input = field.shadowRoot.querySelector('input[type="text"]'); 3485 if (!input) return; 3486 3487 if (clearInput) input.value = ''; 3488 if (!keepFocus) input.blur(); 3489 3490 // Remove autocomplete shadow DOM content to close the dropdown. 3491 // Hawksearch does not expose a close method, and dispatching input 3492 // events does not trigger its internal close. Removing the rendered 3493 // content from the autocomplete shadow root is reliable â our 3494 // MutationObserver detects the removal and clears [data-autocomplete-open]. 3495 // Hawksearch re-renders the content on the next keystroke. 3496 const ac = field.shadowRoot.querySelector('hawksearch-autocomplete'); 3497 if (ac && ac.shadowRoot) { 3498 const overlay = ac.shadowRoot.querySelector('.hs-autocomplete-overlay'); 3499 const dropdown = ac.shadowRoot.querySelector('.hs-autocomplete'); 3500 const closeEl = ac.shadowRoot.querySelector('.hs-autocomplete-close'); 3501 3502 // Fade out overlay, then remove all content 3503 if (overlay) { 3504 overlay.classList.add('is-closing'); 3505 overlay.addEventListener('transitionend', function () { 3506 if (overlay) overlay.remove(); 3507 if (dropdown) dropdown.remove(); 3508 if (closeEl) closeEl.remove(); 3509 }, { once: true }); 3510 // Fallback in case transitionend doesn't fire 3511 setTimeout(function () { 3512 if (overlay && overlay.parentNode) overlay.remove(); 3513 if (dropdown && dropdown.parentNode) dropdown.remove(); 3514 if (closeEl && closeEl.parentNode) closeEl.remove(); 3515 }, 250); 3516 } else { 3517 if (dropdown) dropdown.remove(); 3518 if (closeEl) closeEl.remove(); 3519 } 3520 } 3521 } 3522 3523 // --- Close button (â) â clears input and dismisses --- 3524 // --- Overlay click â dismisses but keeps input text --- 3525 document.addEventListener('click', function (e) { 3526 const path = e.composedPath(); 3527
3528 // --- View-all link â redirect to UnifiedSearch --- 3529 // The library handles hawksearch-view-all navigation internally and does 3530 // not set an href attribute â read the query from the search input instead. 3531 // Keyword param name is pulled from HawkSearch.config.search.queryStringMappings.query 3532 // so it stays in sync with the library's URL convention (defaults to 'q'). 3533 // TODO: right/middle-click fall back to bare /search; to fix, write query-bearing href onto [hawksearch-view-all] on hawksearch:after-autocomplete-executed. 3534 const viewAllEl = path.find((el) => el.hasAttribute && el.hasAttribute('hawksearch-view-all')); 3535 if (viewAllEl) { 3536 e.preventDefault(); 3537 const hsField = document.querySelector('hawksearch-unifiedsearch-field'); 3538 const hsInput = hsField && hsField.shadowRoot && hsField.shadowRoot.querySelector('input[type="text"]'); 3539 const query = hsInput ? hsInput.value.trim() : ''; 3540 const keywordParam = (window.HawkSearch 3541 && HawkSearch.config 3542 && HawkSearch.config.search 3543 && HawkSearch.config.search.queryStringMappings 3544 && HawkSearch.config.search.queryStringMappings.query) || 'q'; 3545 if (query) { 3546 window.location.href = '/search?' + keywordParam + '=' + encodeURIComponent(query) + '&requestType=UnifiedSearch'; 3547 } else { 3548 window.location.href = '/search'; 3549 } 3550 return; 3551 } 3552 3553 // Tab switching for autocomplete Products/Content tabs 3554 const tabBtn = path.find(function (el) { 3555 return el.classList && el.classList.contains('hs-autocomplete__tab'); 3556 }); 3557 if (tabBtn) { 3558 const container = tabBtn.closest('.hs-autocomplete'); 3559 if (container) { 3560 const tabName = tabBtn.getAttribute('data-tab'); 3561 container.setAttribute('data-active-tab', tabName); 3562 container.querySelectorAll('.hs-autocomplete__tab').forEach(function(t) { 3563 const isActive = t.getAttribute('data-tab') === tabName; 3564 t.classList.toggle('hs-autocomplete__tab--active', isActive); 3565 t.setAttribute('aria-selected', isActive ? 'true' : 'false'); 3566 t.setAttribute('tabindex', isActive ? '0' : '-1'); 3567 }); 3568 } 3569 return; 3570 } 3571 3572 const closeBtn = path.find(function (el) { 3573 return el.classList && el.classList.contains('hs-autocomplete-close'); 3574 }); 3575 if (closeBtn) { 3576 e.preventDefault(); 3577 e.stopPropagation(); 3578 dismissAutocomplete(true); 3579 return; 3580 } 3581 3582 const overlayEl = path.find(function (el) { 3583 return el.classList && el.classList.contains('hs-autocomplete-overlay'); 3584 }); 3585 if (overlayEl) { 3586 e.preventDefault(); 3587 dismissAutocomplete(false); 3588 return; 3589 } 3590 }); 3591 3592 // --- Arrow key tab navigation --- 3593 // Left/Right arrows move focus between Products and Content tabs. 3594 // Follows the WAI-ARIA tab pattern: roving tabindex, focus follows selection. 3595 document.addEventListener('keydown', function (e) { 3596 if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return; 3597 const path = e.composedPath(); 3598 const tabEl = path.find(function (el) { 3599 return el.classList && el.classList.contains('hs-autocomplete__tab'); 3600 }); 3601 if (!tabEl) return; 3602 const container = tabEl.closest('.hs-autocomplete'); 3603 if (!container) return; 3604 const tabs = Array.from(container.querySelectorAll('.hs-autocomplete__tab')); 3605 const currentIndex = tabs.indexOf(tabEl); 3606 const nextIndex = e.key === 'ArrowRight' 3607 ? (currentIndex + 1) % tabs.length 3608 : (currentIndex - 1 + tabs.length) % tabs.length; 3609 tabs[nextIndex].click(); 3610 tabs[nextIndex].focus(); 3611 e.preventDefault(); 3612 }); 3613 3614 // --- Zero-results fallback --- 3615 // When the API returns Count === 0 (all arrays empty), the library removes 3616 // the autocomplete shadow DOM entirely. Re-inject a minimal "no results" 3617 // state so the dropdown stays visible while the user keeps typing. 3618 let _fallbackTimer = null;
3619 addEventListener('hawksearch:after-autocomplete-executed', function (e) { 3620 if (!e.detail) return; 3621 // Any completed autocomplete (including one with real results) cancels 3622 // a pending fallback â so we never flash the no-results state while 3623 // a real-results response is still in flight. 3624 clearTimeout(_fallbackTimer); 3625 if (e.detail.Count !== 0) return; 3626 // Capture the query at event time as a secondary stale-check. 3627 const field = document.querySelector('hawksearch-unifiedsearch-field'); 3628 if (!field || !field.shadowRoot) return; 3629 const _input = field.shadowRoot.querySelector('input[type="text"]'); 3630 const queryAtEventTime = _input && _input.value.trim(); 3631 if (!queryAtEventTime) return; 3632 // Wait 500 ms before injecting. If the user types more and triggers 3633 // another event (Count 0 or Count > 0), the timer is cancelled above 3634 // and we start fresh. This prevents flashing during rapid typing. 3635 _fallbackTimer = setTimeout(function () { 3636 const field = document.querySelector('hawksearch-unifiedsearch-field'); 3637 if (!field || !field.shadowRoot) return; 3638 const input = field.shadowRoot.querySelector('input[type="text"]'); 3639 if (!input || !input.value.trim()) return; 3640 // Stale check: input changed since the event fired. 3641 if (input.value.trim() !== queryAtEventTime) return; 3642 const ac = field.shadowRoot.querySelector('hawksearch-autocomplete'); 3643 if (!ac || !ac.shadowRoot) return; 3644 // Only inject if the library left the shadow root empty. 3645 if (ac.shadowRoot.querySelector('.hs-autocomplete')) return; 3646 3647 const query = input.value.trim(); 3648 const safeQuery = query 3649 .replace(/&/g, '&') 3650 .replace(/</g, '<') 3651 .replace(/>/g, '>') 3652 .replace(/"/g, '"'); 3653 const keywordParam = (window.HawkSearch 3654 && HawkSearch.config 3655 && HawkSearch.config.search 3656 && HawkSearch.config.search.queryStringMappings 3657 && HawkSearch.config.search.queryStringMappings.query) || 'q'; 3658 const searchUrl = '/search?' + keywordParam + '=' + encodeURIComponent(query) + '&requestType=UnifiedSearch'; 3659 3660 // Re-inject the library style elements so our CSS rules apply. 3661 // When the library clears the shadow root it removes the <style> tags too. 3662 // The field shadow root keeps its styles intact â clone them in. 3663 field.shadowRoot.querySelectorAll('style').forEach(function (s) { 3664 ac.shadowRoot.appendChild(s.cloneNode(true)); 3665 }); 3666 3667 // Close button â reuses existing shadow-DOM CSS positioning 3668 const closeBtn = document.createElement('button'); 3669 closeBtn.className = 'hs-autocomplete-close'; 3670 closeBtn.type = 'button'; 3671 closeBtn.setAttribute('aria-label', 'Close search'); 3672 closeBtn.innerHTML = 3673 '<svg width="24" height="24" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5" fill="none" aria-hidden="true" focusable="false">' + 3674 '<path d="M5 19 19 5M5 5l14 14"/></svg>'; 3675 ac.shadowRoot.appendChild(closeBtn); 3676 3677 // Dark overlay 3678 const overlay = document.createElement('div'); 3679 overlay.className = 'hs-autocomplete-overlay'; 3680 ac.shadowRoot.appendChild(overlay); 3681 3682 // Dropdown shell â data-suggestions-empty collapses the grid to 1 col 3683 const dropdown = document.createElement('div'); 3684 dropdown.className = 'hs-autocomplete'; 3685 dropdown.setAttribute('data-suggestions-empty', ''); 3686 dropdown.innerHTML = 3687 '<p class="hs-autocomplete__no-results-heading">No suggestions for \u201c' + safeQuery + '\u201d</p>' + 3688 '<div class="hs-autocomplete__view-all">' + 3689 '<a href="' + searchUrl + '">' + 3690 'View all results for \u201c' + safeQuery + '\u201d' + 3691 ' <svg width="24" height="24" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5" fill="none" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M4.696 12h14.686m-7.007-7.5 7.5 7.5-7.5 7.5"/></svg>
3691' + 3692 '</a>' + 3693 '</div>'; 3694 ac.shadowRoot.appendChild(dropdown); 3695 3696 // The library sets display:none on the hawksearch-autocomplete host 3697 // when there are no results. Un-hide it so our injected content shows. 3698 ac.style.display = 'block'; 3699 3700 // Sync state bridge attributes 3701 ac.setAttribute('data-has-value', ''); 3702 field.setAttribute('data-autocomplete-open', ''); 3703 field.setAttribute('data-has-value', ''); 3704 }, 500); // end setTimeout 3705 }); 3706 })(); 3707</script>
vendor: 1 bytes, line 3707
3707
3708<script type="text/javascript"> 3709 /** 3710 * Visual Search integration. 3711 * 3712 * 1. Injects a camera icon button into the unified search field shadow DOM. 3713 * Clicking it toggles the visual search drop area overlay. 3714 * 3715 * 2. Injects an overlay backdrop and close button into the 3716 * <hawksearch-visualsearch-field> shadow DOM. This mirrors the 3717 * autocomplete pattern â all UI lives in the same shadow root so 3718 * it can break out of the header's stacking context via 3719 * position:fixed on the host element. 3720 * 3721 * 3. Validates uploaded files client-side (type + 4MB size limit) before 3722 * the library processes them. Shows inline errors for invalid files. 3723 * 3724 * 4. Manages a shadow-DOM-aware focus trap when the modal is open. 3725 * Tab/Shift+Tab cycle between close, upload, and search buttons. 3726 * Focus moves into the modal on open and returns to the camera 3727 * button on close. 3728 */ 3729 (function () { 3730 const cameraSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>'; 3731 const closeSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>'; 3732 3733 // ââ File validation âââââââââââââââââââââââââââââââââââââââââââââââââ 3734 const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/webp']; 3735 const MAX_FILE_SIZE = 4_000_000; // 4 MB 3736 3737 function validateFile(file) { 3738 if (!file) return null; 3739 if (!ALLOWED_TYPES.includes(file.type)) { 3740 return 'Unsupported file type. Use JPG, PNG, or WEBP.'; 3741 } 3742 if (file.size > MAX_FILE_SIZE) { 3743 return 'File is too large. Maximum size is 4\u2009MB.'; 3744 } 3745 return null; 3746 } 3747 3748 function waitForShadowRoot(el, cb) { 3749 if (el.shadowRoot) { cb(el.shadowRoot); return; } 3750 new MutationObserver((_, obs) => { 3751 if (el.shadowRoot) { obs.disconnect(); cb(el.shadowRoot); } 3752 }).observe(el, { childList: true, subtree: true }); 3753 } 3754 3755 let setupRetries = 0; 3756 let setupDone = false; 3757 const SETUP_MAX_RETRIES = 60; 3758 3759 function setupVisualSearch() { 3760 if (setupDone) return; // Re-entry guard â prevents duplicate observers/global listeners on a loaded re-fire 3761 const field = document.querySelector('hawksearch-unifiedsearch-field'); 3762 const vsField = document.querySelector('hawksearch-visualsearch-field'); 3763 if (!field || !field.shadowRoot || !vsField) { 3764 if (++setupRetries < SETUP_MAX_RETRIES) requestAnimationFrame(setupVisualSearch); 3765 else if (window._hsDebug) console.warn('[HS] visual search setup: gave up after ' + SETUP_MAX_RETRIES + ' frames'); 3766 return; 3767 } 3768 3769 const wrapper = field.shadowRoot.querySelector('.unifiedsearch-field'); 3770 if (!wrapper) { 3771 if (++setupRetries < SETUP_MAX_RETRIES) requestAnimationFrame(setupVisualSearch); 3772 else if (window._hsDebug) console.warn('[HS] visual search setup: gave up after ' + SETUP_MAX_RETRIES + ' frames'); 3773 return; 3774 } 3775 setupRetries = 0; 3776 setupDone = true; // Set only after field + wrapper resolve, so a not-ready frame can't permanently block setup 3777 3778 // Create camera button â injected into the search field shadow DOM. 3779 // HawkSearch re-renders the shadow root on the results page (to populate 3780 // the input with the search query), replacing the wrapper and wiping our 3781 // button. We observe the shadow root (not the wrapper, which may be 3782 // replaced) and re-inject into the current wrapper whenever it disappears. 3783 const btn = document.createElement('button'); 3784 btn.type = 'button'; 3785 btn.className = 'hs-vs-camera-btn'; 3786 btn.setAttribute('aria-label', 'Search by image'); 3787 btn.innerHTML = cameraSvg; 3788 3789 function injectCameraBtn() { 3790 const currentWrapper = field.shadowRoot.querySelector('.unifiedsearch-field'); 3791 if (currentWrapper && !currentWrapper.querySelector('.hs-vs-camera-btn')) { 3792 currentWrapper.appendChild(btn); 3793 } 3794 } 3795 3796 injectCameraBtn(); 3797 new MutationObserver(injectCameraBtn).observe(field.shadowRoot, { childList: true, subtree: false }); 3798 3799 // ââ Focus trap helpers (shadow-DOM-aware) âââââââââââââââââââââââââââââ 3800 // The theme's global trapFocus() can't traverse shadow boundaries, so 3801 // we manage a minimal focus cycle between the 3 interactive elements 3802 // inside vsField.shadowRoot: close button, file input, search button. 3803 function getShadowFocusable() {
3804 if (!vsField.shadowRoot) return []; 3805 const els = []; 3806 const close = vsField.shadowRoot.querySelector('.hs-vs-close'); 3807 const upload = vsField.shadowRoot.querySelector('[hawksearch-visualsearch-fileinput]'); 3808 const search = vsField.shadowRoot.querySelector('.hs-vs-search-btn'); 3809 if (close) els.push(close); 3810 if (upload) els.push(upload); 3811 if (search && !search.disabled && search.style.display !== 'none') els.push(search); 3812 return els; 3813 } 3814 3815 // ââ Open / close helpers ââââââââââââââââââââââââââââââââââââââââââââââ 3816 function openVisualSearch() { 3817 vsField.setAttribute('data-vs-open', ''); 3818 if (window.dismissAutocomplete) window.dismissAutocomplete(false); 3819 // Move focus into the modal (close button is always present) 3820 const close = vsField.shadowRoot && vsField.shadowRoot.querySelector('.hs-vs-close'); 3821 if (close) close.focus(); 3822 } 3823 3824 function closeVisualSearch() { 3825 vsField.removeAttribute('data-vs-open'); 3826 clearError(); 3827 // Clear the image preview so the modal reopens in its initial empty state. 3828 // Without this, reopening shows the previous image with a stale button label. 3829 if (vsField.shadowRoot) { 3830 vsField.shadowRoot.querySelectorAll('[hawksearch-visualsearch-display]').forEach((el) => { 3831 while (el.lastChild) el.removeChild(el.lastChild); 3832 }); 3833 // Reset search button to initial state 3834 const searchBtn = vsField.shadowRoot.querySelector('.hs-vs-search-btn'); 3835 if (searchBtn) { 3836 searchBtn.textContent = 'Searching\u2026'; 3837 searchBtn.disabled = true; 3838 } 3839 } 3840 // Reset the file input so the same file can be re-selected on reopen. 3841 // Chrome won't fire a change event if the same file is chosen twice without this. 3842 const fileInput = vsField.shadowRoot && vsField.shadowRoot.querySelector('[hawksearch-visualsearch-fileinput]'); 3843 if (fileInput) fileInput.value = ''; 3844 // Return focus to the camera button that opened the modal 3845 btn.focus(); 3846 } 3847 3848 // Camera button toggles visual search 3849 btn.addEventListener('click', (e) => { 3850 e.preventDefault(); 3851 e.stopPropagation(); 3852 if (vsField.hasAttribute('data-vs-open')) { 3853 closeVisualSearch(); 3854 } else { 3855 openVisualSearch(); 3856 } 3857 }); 3858 3859 // ââ Inject overlay + close button into visual search shadow DOM âââââââ 3860 // HawkSearch may re-render the shadow DOM after our injection; a 3861 // MutationObserver on the shadow root re-appends them if removed. 3862 waitForShadowRoot(vsField, (shadow) => { 3863 const overlay = document.createElement('div'); 3864 overlay.className = 'hs-vs-overlay'; 3865 3866 const closeBtn = document.createElement('button'); 3867 closeBtn.type = 'button'; 3868 closeBtn.className = 'hs-vs-close'; 3869 closeBtn.setAttribute('aria-label', 'Close visual search'); 3870 closeBtn.innerHTML = closeSvg; 3871 3872 overlay.addEventListener('click', closeVisualSearch); 3873 closeBtn.addEventListener('click', (e) => { 3874 e.preventDefault(); 3875 closeVisualSearch(); 3876 }); 3877 3878 // Wire the search button â click closes the modal once results are ready. 3879 // Guard with _vsWired so re-renders don't attach duplicate listeners. 3880 function wireSearchBtn() { 3881 const searchBtn = shadow.querySelector('.hs-vs-search-btn'); 3882 if (!searchBtn || searchBtn._vsWired) return; 3883 searchBtn._vsWired = true; 3884 searchBtn.addEventListener('click', (e) => { 3885 e.preventDefault(); 3886 closeVisualSearch(); 3887 }); 3888 } 3889 3890 // Watch [hawksearch-visualsearch-display] for image insertion. 3891 // The library appends an <img> as soon as FileReader finishes â that's 3892 // when the search fires. Flip the button to "Searchingâ¦" (disabled) at 3893 // that moment so the user knows something is happening. 3894 function observeDisplay() { 3895 const display = shadow.querySelector('[hawksearch-visualsearch-display]'); 3896 if (!display || display._vsObserved) return; 3897 display._vsObserved = true; 3898 new MutationObserver(() => { 3899 const searchBtn = shadow.querySelector('.hs-vs-search-btn'); 3900 if (!searchBtn) return; 3901 searchBtn.textContent = 'Searching\u2026'; 3902 searchBtn.disabled = true; 3903 }).observe(display, { childList: true }); 3904 } 3905 3906 // ââ File input validation ââââââââââââââââââââââââââââââââââââââââââ 3907 // Intercept file selection and reject invalid files before the 3908 // library processes them. Guard with _vsValidated to avoid 3909 // duplicate listeners after shadow DOM re-renders. 3910 function wireFileValidation() { 3911 const fileInput = shadow.querySelector('[hawksearch-visualsearch-fileinput]'); 3912 if (!fileInput || fileInput._vsValidated) return; 3913 fileInput._vsValidated = true; 3914 fileInput.addEventListener('change', () => { 3915 const file = fileInput.files && fileInput.files[0]; 3916 if (!file) return; 3917 const error = validateFile(file); 3918 if (error) { 3919 // Clear the input so the library doesn't process the file. 3920 // Reset via form or value â value='' works in all modern browsers. 3921 fileInput.value = ''; 3922 showError(error); 3923 } 3924 }); 3925 } 3926 3927 // ââ ARIA: mark the dialog container âââââââââââââââââââââââââââââââââ 3928 function setDialogAttrs() { 3929 const dialog = shadow.querySelector('.visualsearch-field'); 3930 if (dialog && !dialog.getAttribute('role')) { 3931 dialog.setAttribute('role', 'dialog'); 3932 dialog.setAttribute('aria-modal', 'true'); 3933 dialog.setAttribute('aria-label', 'Search by image'); 3934 } 3935 } 3936 3937 function ensureInjected() { 3938 if (!shadow.querySelector('.hs-vs-overlay')) shadow.appendChild(overlay); 3939 if (!shadow.querySelector('.hs-vs-close')) shadow.appendChild(closeBtn); 3940 wireSearchBtn(); 3941 observeDisplay(); 3942 wireFileValidation(); 3943 setDialogAttrs(); 3944 } 3945 3946 ensureInjected(); 3947 new MutationObserver(ensureInjected).observe(shadow, { childList: true }); 3948 }); 3949
3950 // ââ Keyboard handler: Escape to close + focus trap ââââââââââââââââââ 3951 document.addEventListener('keydown', (e) => { 3952 if (!vsField.hasAttribute('data-vs-open')) return; 3953 3954 if (e.key === 'Escape') { 3955 closeVisualSearch(); 3956 return; 3957 } 3958 3959 // Focus trap â cycle Tab/Shift+Tab within shadow DOM elements. 3960 // document.activeElement points to the shadow host; the real 3961 // focused element is in vsField.shadowRoot.activeElement. 3962 if (e.key === 'Tab') { 3963 const focusable = getShadowFocusable(); 3964 if (focusable.length === 0) return; 3965 const active = vsField.shadowRoot ? vsField.shadowRoot.activeElement : null; 3966 const first = focusable[0]; 3967 const last = focusable[focusable.length - 1]; 3968 3969 if (e.shiftKey) { 3970 if (!active || active === first) { 3971 e.preventDefault(); 3972 last.focus(); 3973 } 3974 } else { 3975 if (!active || active === last) { 3976 e.preventDefault(); 3977 first.focus(); 3978 } 3979 } 3980 } 3981 }); 3982 3983 // ââ Error handling (injected into visual search shadow DOM) âââââââââââ 3984 let _vsErrTimer = null; 3985 function showError(msg) { 3986 if (!vsField.shadowRoot) return; 3987 let errorEl = vsField.shadowRoot.querySelector('.hs-vs-error'); 3988 if (!errorEl) { 3989 errorEl = document.createElement('div'); 3990 errorEl.className = 'hs-vs-error'; 3991 errorEl.setAttribute('role', 'alert'); 3992 vsField.shadowRoot.appendChild(errorEl); 3993 } 3994 errorEl.textContent = msg || 'Could not process image. Try a JPG, PNG, or WEBP under 4 MB.'; 3995 errorEl.hidden = false; 3996 clearTimeout(_vsErrTimer); 3997 _vsErrTimer = setTimeout(clearError, 5000); 3998 } 3999 4000 function clearError() { 4001 clearTimeout(_vsErrTimer); 4002 _vsErrTimer = null; 4003 if (!vsField.shadowRoot) return; 4004 const errorEl = vsField.shadowRoot.querySelector('.hs-vs-error'); 4005 if (errorEl) errorEl.hidden = true; 4006 } 4007 4008 addEventListener('hawksearch:visualsearch-upload-failed', (e) => { 4009 // Skip if our validation error is already showing â prevents 4010 // duplicate messages when the library also rejects the file. 4011 if (vsField.shadowRoot) { 4012 const errorEl = vsField.shadowRoot.querySelector('.hs-vs-error'); 4013 if (errorEl && !errorEl.hidden) return; 4014 } 4015 const detail = e.detail || {}; 4016 showError(detail.message || detail.error); 4017 }); 4018 4019 // When the search completes, flip the button from "Searchingâ¦" to 4020 // "View Results" (enabled) so the user can dismiss the modal at their 4021 // own pace rather than having it close automatically. 4022 addEventListener('hawksearch:after-search-executed', () => { 4023 if (!vsField.hasAttribute('data-vs-open')) return; 4024 if (!vsField.shadowRoot) return; 4025 const searchBtn = vsField.shadowRoot.querySelector('.hs-vs-search-btn'); 4026 if (!searchBtn) return; 4027 searchBtn.textContent = 'View Results'; 4028 searchBtn.disabled = false; 4029 }); 4030 } 4031 4032 addEventListener('hawksearch:loaded', () => { 4033 if (setupDone) return; 4034 setupRetries = 0; 4035 requestAnimationFrame(setupVisualSearch); 4036 }); 4037 })(); 4038</script>
vendor: 1 bytes, line 4038
4038
4039<script type="text/javascript"> 4040 /** 4041 * AJAX Add-to-Cart for Hawksearch search result cards (.hs-atc-btn). 4042 * 4043 * Uses event delegation so it works on dynamically rendered Hawksearch items. 4044 * Variant data is embedded at render time from the HawkSearch index â no 4045 * /products/{handle}.js fetch is made at any point. 4046 * 4047 * Flow: 4048 * - Multi-variant (data-multi-variant="true"): delegate to native quick-add drawer. 4049 * The drawer fetches the full product page and handles variant selection natively. 4050 * If data-selected-color is set (user clicked a swatch), the drawer pre-selects 4051 * that color option via setActiveVariant(). 4052 * - Single-variant: read variant ID from data-variant-id (always populated by 4053 * the template from selectedVariant.id), POST to /cart/add.js, update cart. 4054 * 4055 * Reuses the theme's native cart/event contract from product-form.js: 4056 * - window.Shopify.routes.root + 'cart/add.js' for the endpoint (AJAX JSON endpoint) 4057 * - cartDrawer.renderContents(data, open) for drawer update 4058 * - on:cart:add / on:cart:error custom events (bubbling) 4059 * - theme.settings.afterAtc for post-add behaviour 4060 */ 4061 (function () { 4062 const hsDebug = window._hsDebug; 4063 4064 document.addEventListener('click', async function handleHsAtcClick(e) { 4065 const btn = e.composedPath().find(el => el.classList?.contains('hs-atc-btn')); 4066 if (!btn || btn.getAttribute('aria-disabled') === 'true') return; 4067 4068 const card = btn.closest('.search-results-list__item'); 4069 const errorEl = card && card.querySelector('.js-form-error'); 4070 4071 // ââ Multi-variant: delegate to native quick-add drawer ââââââââââââââââ 4072 if (btn.dataset.multiVariant === 'true') { 4073 const quickAddDrawer = document.querySelector('quick-add-drawer'); 4074 if (!quickAddDrawer) { 4075 if (btn.dataset.productUrl) { 4076 window.location.href = btn.dataset.productUrl; 4077 } else if (errorEl) { 4078 errorEl.textContent = 'View the product page to select options.'; 4079 errorEl.hidden = false; 4080 clearTimeout(errorEl._hideTimer); 4081 errorEl._hideTimer = setTimeout(() => { errorEl.hidden = true; errorEl._hideTimer = null; }, 4000); 4082 } 4083 return; 4084 } 4085 quickAddDrawer.open(btn); 4086 if (hsDebug) console.log('[HS ATC] Multi-variant â quick-add drawer', { 4087 productUrl: btn.dataset.productUrl, 4088 selectedColor: btn.dataset.selectedColor || '(none)', 4089 }); 4090 return; 4091 } 4092 4093 // ââ Single-variant: POST directly âââââââââââââââââââââââââââââââââââââ 4094 btn.setAttribute('aria-disabled', 'true'); 4095 clearTimeout(btn._hsResetTimer); 4096 btn.classList.remove('is-success'); 4097 btn.classList.add('is-loading'); 4098 if (errorEl) { clearTimeout(errorEl._hideTimer); errorEl.hidden = true; } 4099 4100 try { 4101 if (typeof theme !== 'undefined' && theme.settings?.vibrateOnATC && navigator.vibrate) navigator.vibrate(100); 4102 4103 const variantId = btn.dataset.variantId; 4104 const rawPrice = btn.dataset.price || '0'; 4105 4106 if (!variantId) { 4107 throw new Error('Could not resolve variant. Please use View Details to add this item.'); 4108 } 4109 if (hsDebug) console.log('[HS ATC] Single-variant:', variantId); 4110 4111 // ââ Build sections string (matches product-form.js pattern) ââââââââââ 4112 const cartDrawer = document.querySelector('cart-drawer'); 4113 let sections = 'cart-icon-bubble'; 4114 if (cartDrawer) { 4115 const drawerSection = cartDrawer.closest('.shopify-section'); 4116 if (drawerSection) sections += ',' + drawerSection.id.replace('shopify-section-', ''); 4117 } 4118 4119 // ââ POST /cart/add.js ââââââââââââââââââââââââââââââââââââââââââââââââ 4120 // IMPORTANT: Use window.Shopify.routes.root + 'cart/add.js', NOT theme.routes.cartAdd. 4121 // theme.routes.cartAdd resolves to /cart/add (the HTML form endpoint) which returns 4122 // an HTML redirect to /cart when no AJAX-signaling headers are present â resp.ok is 4123 // true on the redirected 200, but resp.json() then throws "Unexpected token '<'". 4124 // /cart/add.js is Shopify's documented AJAX endpoint and always returns JSON. 4125 // See: https://shopify.dev/docs/api/ajax/reference/cart 4126 const resp = await fetch(window.Shopify.routes.root + 'cart/add.js', { 4127 method: 'POST', 4128 headers: { 'Content-Type': 'application/json' }, 4129 body: JSON.stringify({ 4130 items: [{ id: variantId, quantity: 1 }], 4131 sections: sections, 4132 sections_url: location.pathname, 4133 }), 4134 }); 4135 if (!resp.ok) { 4136 const errJson = await resp.json().catch(() => ({})); 4137 throw new Error(errJson.description || 'Could not add to cart.'); 4138 } 4139 const data = await resp.json(); 4140 4141 // ââ Post-add behaviour â reuses native contract ââââââââââââââââââââââ 4142 if (theme?.settings?.afterAtc === 'page') { 4143 window.location.href = theme?.routes?.cart || (window.Shopify?.routes?.root || '/') + 'cart'; 4144 } else { 4145 const bubble = document.getElementById('cart-icon-bubble'); 4146 if (bubble && data.sections?.['cart-icon-bubble']) { 4147 bubble.innerHTML = data.sections['cart-icon-bubble']; 4148 } 4149 if (cartDrawer) { 4150 cartDrawer.renderContents(data, theme?.settings?.afterAtc === 'drawer'); 4151 } 4152 } 4153 4154 // ââ HawkSearch ATC tracking ââââââââââââââââââââââââââââââââââââââââââ
4155 try { 4156 if (typeof HawkSearch !== 'undefined' && HawkSearch.services?.tracking) { 4157 // Send the parent product_id (= Shopify handle), matching the index primary key and the 4158 // library-fired Click/Recs events â NOT the Shopify variant id (which /cart/add.js above 4159 // still uses, as Shopify requires it). data-product-id is set in hawksearch-results-item. 4160 const trackProductId = btn.dataset.productId; 4161 const trackPrice = parseFloat(rawPrice) || 0; 4162 if (trackProductId) { 4163 HawkSearch.services.tracking.trackAddToCart( 4164 String(trackProductId), 1, trackPrice, 'USD' 4165 ); 4166 if (hsDebug) console.log('[HS Tracking] trackAddToCart:', trackProductId, trackPrice); 4167 } else if (hsDebug) { 4168 console.warn('[HS Tracking] trackAddToCart skipped â no data-product-id on card'); 4169 } 4170 } 4171 } catch (trackErr) { 4172 if (hsDebug) console.warn('[HS Tracking] error:', trackErr); 4173 } 4174 4175 // ââ Fire native on:cart:add event ââââââââââââââââââââââââââââââââââââ 4176 btn.dispatchEvent(new CustomEvent('on:cart:add', { 4177 bubbles: true, 4178 composed: true, 4179 detail: { cart: data, variantId: variantId, source: 'hawksearch' }, 4180 })); 4181 4182 // ââ Success state ââââââââââââââââââââââââââââââââââââââââââââââââââââ 4183 btn.classList.add('is-success'); 4184 btn.removeAttribute('aria-disabled'); 4185 clearTimeout(btn._hsResetTimer); 4186 btn._hsResetTimer = setTimeout(() => { btn.classList.remove('is-loading', 'is-success'); }, 1400); 4187 4188 } catch (err) { 4189 btn.dispatchEvent(new CustomEvent('on:cart:error', { 4190 bubbles: true, 4191 composed: true, 4192 detail: { error: err.message }, 4193 })); 4194 if (errorEl) { 4195 errorEl.textContent = err.message || 'Could not add to cart.'; 4196 errorEl.hidden = false; 4197 clearTimeout(errorEl._hideTimer); 4198 errorEl._hideTimer = setTimeout(() => { errorEl.hidden = true; errorEl._hideTimer = null; }, 4000); 4199 } 4200 btn.classList.remove('is-loading'); 4201 btn.removeAttribute('aria-disabled'); 4202 } 4203 }); 4204 })(); 4205</script>
vendor: 1 bytes, line 4205
4205
4206<script type="text/javascript"> 4207 /** 4208 * Search results toolbar handler. 4209 * 4210 * Manages the filter panel open/close state at ALL breakpoints 4211 * via a single .hs-toolbar__filter-btn button and the 4212 * [data-filters-open] attribute on the host element. 4213 * 4214 * Desktop (>= 990px): sidebar starts open, simple inline toggle. 4215 * Mobile (< 990px): sidebar opens as a native-theme-style drawer 4216 * with left-slide animation, overlay, body scroll lock, focus trap, 4217 * ESC/overlay close, header with close button, and sticky footer 4218 * with "Show Results (N)" CTA. Mirrors the theme's SideDrawer class 4219 * (main.js:591-687) adapted for shadow DOM. 4220 * 4221 * CSS in hawksearch-styles-toolbar.liquid uses :host() selectors to 4222 * show/hide .column-md--4 based on [data-filters-open]. On mobile the 4223 * column becomes a position:fixed drawer with translate3d transitions. 4224 * 4225 * Filter icon animation reacts to [data-filters-open] at all breakpoints 4226 * via :host(hawksearch-search-results:not([data-filters-open])) rules. 4227 * 4228 * Also toggles [data-hs-no-facets] on the host when a search returns 4229 * Facets: [] (Concept Search fallback). CSS disables the filter button 4230 * and hides the empty sidebar column in that state. 4231 */ 4232 (function () { 4233 const DESKTOP_MIN = 990; 4234 4235 // Cached after setup() confirms the element exists. 4236 let host = null; 4237 4238 // Drawer state 4239 let isDrawerOpen = false; 4240 let savedScrollY = 0; 4241 let resultCount = 0; 4242 let overlay = null; 4243 let focusTrapCleanup = null; 4244 // In-flight MutationObserver for after-search re-sync. Stored at module 4245 // scope so a rapid second search disconnects the first observer before it 4246 // fires, preventing the focusTrapCleanup slot from being overwritten by a 4247 // stale callback (listener-leak fix). 4248 let afterSearchObserver = null; 4249 4250 // Cap rAF retries so setup() does not loop indefinitely on pages that 4251 // never mount hawksearch-search-results (home, PDP, cart, etc.). 4252 // 60 frames â 1 second at 60fps â long enough for any realistic HS init. 4253 let setupRetries = 0; 4254 const SETUP_MAX_RETRIES = 60; 4255 4256 function setup() { 4257 if (!host) { 4258 host = window.HSShadow.resolveResults(); 4259 } 4260 if (!host || !host.shadowRoot) { 4261 if (++setupRetries < SETUP_MAX_RETRIES) requestAnimationFrame(setup); 4262 return; 4263 } 4264 4265 const filterBtn = host.shadowRoot.querySelector('.hs-toolbar__filter-btn'); 4266 if (!filterBtn) { 4267 if (++setupRetries < SETUP_MAX_RETRIES) requestAnimationFrame(setup); 4268 return; 4269 } 4270 4271 if (window.innerWidth >= DESKTOP_MIN) { 4272 host.setAttribute('data-filters-open', ''); 4273 filterBtn.setAttribute('aria-expanded', 'true'); 4274 } else { 4275 host.removeAttribute('data-filters-open'); 4276 filterBtn.setAttribute('aria-expanded', 'false'); 4277 } 4278 } 4279 4280 // ââ Drawer chrome injection âââââââââââââââââââââââââââââââââââââââââ 4281 // Creates header, scrollable body wrapper, and footer inside the 4282 // shadow DOM .column-md--4. Idempotent â checks for .hs-drawer__header. 4283 // Must re-run after every hawksearch:after-search-executed because 4284 // HawkSearch destroys and rebuilds the shadow DOM on each search. 4285 4286 function injectDrawerChrome() { 4287 if (!host || !host.shadowRoot) return; 4288 const col = host.shadowRoot.querySelector('.column-md--4'); 4289 if (!col || col.querySelector('.hs-drawer__header')) return; 4290 4291 const header = document.createElement('div'); 4292 header.className = 'hs-drawer__header'; 4293 header.innerHTML = 4294 '<h2 class="hs-drawer__title">Filter & Sort</h2>' + 4295 '<button type="button" class="hs-drawer__close" aria-label="Close filters">' + 4296 '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">' + 4297 '<line x1="18" y1="6" x2="6" y2="18"></line>' + 4298 '<line x1="6" y1="6" x2="18" y2="18"></line>' + 4299 '</svg>' + 4300 '</button>'; 4301 4302 const footer = document.createElement('div'); 4303 footer.className = 'hs-drawer__footer'; 4304 footer.innerHTML = 4305 '<button type="button" class="hs-drawer__cta">' + 4306 'Show Results' + (resultCount ? ' (' + resultCount + ')' : '') + 4307 '</button>'; 4308 4309 // Insert header BEFORE existing HS content, footer AFTER. 4310 // Never move HS custom elements â appendChild/insertBefore on them 4311 // re-triggers connectedCallback which wipes their rendered shadow DOM. 4312 col.insertBefore(header, col.firstChild); 4313 col.appendChild(footer); 4314 } 4315 4316 function updateResultCount() { 4317 if (!host || !host.shadowRoot) return; 4318 const cta = host.shadowRoot.querySelector('.hs-drawer__cta'); 4319 if (cta) { 4320 cta.textContent = 'Show Results' + (resultCount ? ' (' + resultCount + ')' : ''); 4321 } 4322 } 4323 4324 // ââ Drawer open/close âââââââââââââââââââââââââââââââââââââââââââââââ 4325 // Mirrors the theme's SideDrawer.open() / .close() (main.js:613-687): 4326 // body scroll lock, global overlay, ARIA dialog, focus trap, ESC close. 4327 4328 function openDrawer() { 4329 if (isDrawerOpen) return; 4330 isDrawerOpen = true; 4331
4332 if (!overlay) overlay = document.querySelector('.js-overlay'); 4333 4334 injectDrawerChrome(); 4335 updateResultCount(); 4336 4337 // Save scroll position and lock body (mirrors SideDrawer.open) 4338 savedScrollY = window.scrollY; 4339 document.body.classList.add('fixed'); 4340 document.body.style.top = '-' + savedScrollY + 'px'; 4341 document.documentElement.style.height = '100svh'; 4342 4343 if (overlay) overlay.classList.add('is-visible'); 4344 4345 host.setAttribute('data-filters-open', ''); 4346 4347 // ARIA dialog on the drawer column 4348 const col = host.shadowRoot.querySelector('.column-md--4'); 4349 applyDialogAria(col); 4350 4351 const btn = host.shadowRoot.querySelector('.hs-toolbar__filter-btn'); 4352 if (btn) btn.setAttribute('aria-expanded', 'true'); 4353 4354 trapDrawerFocus(true); 4355 4356 document.addEventListener('keyup', onDrawerKeyup); 4357 if (overlay) overlay.addEventListener('click', onOverlayClick); 4358 } 4359 4360 function closeDrawer() { 4361 if (!isDrawerOpen) return; 4362 isDrawerOpen = false; 4363 4364 host.removeAttribute('data-filters-open'); 4365 4366 const btn = host.shadowRoot.querySelector('.hs-toolbar__filter-btn'); 4367 if (btn) { 4368 btn.setAttribute('aria-expanded', 'false'); 4369 btn.focus(); 4370 } 4371 4372 if (overlay) overlay.classList.remove('is-visible'); 4373 4374 const col = host.shadowRoot.querySelector('.column-md--4'); 4375 if (col) { 4376 col.removeAttribute('role'); 4377 col.removeAttribute('aria-modal'); 4378 col.removeAttribute('aria-label'); 4379 } 4380 4381 releaseDrawerFocus(); 4382 4383 // Restore body scroll (mirrors SideDrawer.close) 4384 document.documentElement.style.height = ''; 4385 document.body.style.top = ''; 4386 document.body.classList.remove('fixed'); 4387 window.scrollTo(0, savedScrollY); 4388 4389 document.removeEventListener('keyup', onDrawerKeyup); 4390 if (overlay) overlay.removeEventListener('click', onOverlayClick); 4391 } 4392 4393 function onDrawerKeyup(e) { 4394 if (e.key === 'Escape') closeDrawer(); 4395 } 4396 4397 function onOverlayClick() { 4398 closeDrawer(); 4399 } 4400 4401 // ââ Focus trap ââââââââââââââââââââââââââââââââââââââââââââââââââââââ 4402 // Uses focusin + composedPath() to catch focus leaving the drawer. 4403 // Works across nested shadow DOMs (facet controls inside 4404 // <hawksearch-facets-list>'s own shadow root) because focusin events 4405 // compose through all shadow boundaries. When focus escapes the drawer 4406 // column, it is redirected back to the close button. 4407 4408 // moveFocus: pass true on initial open to move focus to the close button. 4409 // Pass false on re-render (after-search-executed) to re-wire the trap 4410 // without stealing keyboard focus from wherever the user currently is. 4411 function trapDrawerFocus(moveFocus) { 4412 releaseDrawerFocus(); 4413 const col = host.shadowRoot.querySelector('.column-md--4'); 4414 if (!col) return; 4415 4416 if (moveFocus) { 4417 const closeBtn = col.querySelector('.hs-drawer__close'); 4418 if (closeBtn) closeBtn.focus(); 4419 } 4420 4421 function onFocusin(e) { 4422 if (!isDrawerOpen) return; 4423 // Re-query col each time â the shadow DOM may have been rebuilt since 4424 // the trap was set up, making a closed-over reference stale/detached. 4425 const currentCol = host.shadowRoot && host.shadowRoot.querySelector('.column-md--4'); 4426 if (!currentCol) return; 4427 const path = e.composedPath(); 4428 const insideDrawer = path.indexOf(currentCol) !== -1; 4429 if (!insideDrawer) { 4430 const close = currentCol.querySelector('.hs-drawer__close'); 4431 if (close) close.focus(); 4432 } 4433 } 4434 4435 document.addEventListener('focusin', onFocusin, true); 4436 focusTrapCleanup = function () { 4437 document.removeEventListener('focusin', onFocusin, true); 4438 }; 4439 } 4440 4441 function releaseDrawerFocus() { 4442 if (focusTrapCleanup) { 4443 focusTrapCleanup(); 4444 focusTrapCleanup = null; 4445 } 4446 } 4447 4448 function applyDialogAria(col) { 4449 if (!col) return; 4450 col.setAttribute('role', 'dialog'); 4451 col.setAttribute('aria-modal', 'true'); 4452 col.setAttribute('aria-label', 'Filter & Sort'); 4453 } 4454 4455 // ââ Click handler âââââââââââââââââââââââââââââââââââââââââââââââââââ 4456 // Uses composedPath() to pierce the search-results shadow boundary.
4457 // Breakpoint-aware: mobile toggles the drawer, desktop toggles inline. 4458 4459 document.addEventListener('click', function (e) { 4460 const path = e.composedPath(); 4461 4462 // Filter button click 4463 const btn = path.find(function (el) { 4464 return el.classList && el.classList.contains('hs-toolbar__filter-btn'); 4465 }); 4466 if (btn && host) { 4467 // No-facets state: button is visually disabled. Covers keyboard 4468 // Enter during the brief window before rAF applies aria-disabled. 4469 if (host.hasAttribute('data-hs-no-facets')) return; 4470 if (window.innerWidth < DESKTOP_MIN) { 4471 if (isDrawerOpen) { 4472 closeDrawer(); 4473 } else { 4474 openDrawer(); 4475 } 4476 } else { 4477 // Desktop: simple attribute toggle (unchanged behavior) 4478 const isOpen = host.hasAttribute('data-filters-open'); 4479 if (isOpen) { 4480 host.removeAttribute('data-filters-open'); 4481 btn.setAttribute('aria-expanded', 'false'); 4482 } else { 4483 host.setAttribute('data-filters-open', ''); 4484 btn.setAttribute('aria-expanded', 'true'); 4485 } 4486 } 4487 return; 4488 } 4489 4490 // Drawer close button or footer CTA click (from shadow DOM) 4491 const closeBtn = path.find(function (el) { 4492 return el.classList && (el.classList.contains('hs-drawer__close') || el.classList.contains('hs-drawer__cta')); 4493 }); 4494 if (closeBtn && isDrawerOpen) { 4495 closeDrawer(); 4496 } 4497 }); 4498 4499 // ââ HawkSearch lifecycle events âââââââââââââââââââââââââââââââââââââ 4500 4501 window.addEventListener('hawksearch:loaded', function () { 4502 // Reset retry counter so a fresh HS init gets the full 60-frame budget. 4503 // Only re-run setup if it hasn't already found the host element â guards 4504 // against hawksearch:loaded firing more than once and stacking listeners. 4505 if (!host) { 4506 setupRetries = 0; 4507 requestAnimationFrame(setup); 4508 } 4509 }); 4510 4511 // Re-sync state after each search execution. HawkSearch re-renders 4512 // the shadow DOM, destroying any injected drawer chrome. Uses 4513 // MutationObserver instead of a fixed delay so re-sync fires as soon as 4514 // .hs-toolbar__filter-btn is present, even on throttled CPUs. Disconnects 4515 // any in-flight observer before creating a new one so rapid searches 4516 // cannot produce overlapping trapDrawerFocus() calls. 4517 window.addEventListener('hawksearch:after-search-executed', function (e) { 4518 if (e.detail && e.detail.Pagination) { 4519 resultCount = e.detail.Pagination.NofResults || 0; 4520 } 4521 4522 if (!host || !host.shadowRoot) return; 4523 4524 // Concept Search fallback (multi-word queries with thin UnifiedSearch 4525 // keyword match) returns Facets: []. No server-side toggle controls 4526 // this. Host attribute â CSS disables the filter button and hides the 4527 // empty sidebar. Zero-results responses are left to HS's no-results UI. 4528 const facets = (e.detail && e.detail.Facets) || []; 4529 if (facets.length === 0 && resultCount > 0) { 4530 if (isDrawerOpen) closeDrawer(); 4531 host.setAttribute('data-hs-no-facets', ''); 4532 } else { 4533 host.removeAttribute('data-hs-no-facets'); 4534 } 4535 4536 if (afterSearchObserver) { 4537 afterSearchObserver.disconnect(); 4538 afterSearchObserver = null; 4539 } 4540 4541 afterSearchObserver = new MutationObserver(function (mutations, obs) { 4542 const btn = host.shadowRoot.querySelector('.hs-toolbar__filter-btn'); 4543 const col = host.shadowRoot.querySelector('.column-md--4'); 4544 if (!btn || !col) return; // shadow DOM still rebuilding â toolbar renders before .row 4545 4546 obs.disconnect(); 4547 afterSearchObserver = null; 4548 4549 // Defer until HS's synchronous render cycle exits the call stack. 4550 // The observer fires while HS render() is still executing â calling 4551 // injectDrawerChrome() now moves HS custom elements mid-render, which 4552 // re-triggers connectedCallback on elements that already have a shadow 4553 // root, causing NotSupportedError. rAF pushes this work to after paint. 4554 requestAnimationFrame(function () { 4555 if (!host || !host.shadowRoot) return; 4556 const rafBtn = host.shadowRoot.querySelector('.hs-toolbar__filter-btn'); 4557 if (!rafBtn) return; 4558 4559 rafBtn.setAttribute('aria-expanded', host.hasAttribute('data-filters-open') ? 'true' : 'false'); 4560 4561 // Re-apply aria-disabled after shadow DOM rebuild â same lifecycle 4562 // as aria-expanded. Matches the CSS disabled-look on the button. 4563 if (host.hasAttribute('data-hs-no-facets')) { 4564 rafBtn.setAttribute('aria-disabled', 'true'); 4565 } else { 4566 rafBtn.removeAttribute('aria-disabled'); 4567 } 4568 4569 if (window.innerWidth < DESKTOP_MIN) { 4570 // Column is hidden on no-facets state â skip chrome injection. 4571 if (host.hasAttribute('data-hs-no-facets')) return; 4572 injectDrawerChrome(); 4573 updateResultCount(); 4574 4575 if (isDrawerOpen) { 4576 // Re-apply ARIA dialog attributes â HawkSearch destroys and rebuilds 4577 // the shadow DOM on each search, so these are lost after re-render. 4578 const rebuiltCol = host.shadowRoot.querySelector('.column-md--4'); 4579 applyDialogAria(rebuiltCol); 4580 trapDrawerFocus(false); 4581 // If the re-render destroyed the focused node, the browser drops focus to 4582 // <body> WITHOUT firing focusin, so the trap can't recover it. Restore focus to the
4583 // drawer close button only when focus was actually orphaned â preserved focus lands 4584 // on the shadow host (not body), so === body cleanly distinguishes the two cases. 4585 if (document.activeElement === document.body) { 4586 const rebuiltClose = rebuiltCol && rebuiltCol.querySelector('.hs-drawer__close'); 4587 if (rebuiltClose) rebuiltClose.focus(); 4588 } 4589 } 4590 } 4591 }); 4592 }); 4593 4594 afterSearchObserver.observe(host.shadowRoot, { childList: true, subtree: true }); 4595 }); 4596 4597 // ââ Resize handler ââââââââââââââââââââââââââââââââââââââââââââââââââ 4598 // Mobile->desktop with drawer open: clean up drawer behaviors, keep 4599 // data-filters-open so desktop sidebar stays visible. 4600 // Desktop->mobile with sidebar open: close it to prevent drawer 4601 // appearing without overlay, scroll lock, or focus trap. 4602 4603 window.addEventListener('resize', (function () { 4604 let timer; 4605 let wasMobile = window.innerWidth < DESKTOP_MIN; 4606 return function () { 4607 clearTimeout(timer); 4608 timer = setTimeout(function () { 4609 const isMobile = window.innerWidth < DESKTOP_MIN; 4610 4611 if (!isMobile && wasMobile && isDrawerOpen) { 4612 isDrawerOpen = false; 4613 if (overlay) overlay.classList.remove('is-visible'); 4614 releaseDrawerFocus(); 4615 document.documentElement.style.height = ''; 4616 document.body.style.top = ''; 4617 document.body.classList.remove('fixed'); 4618 document.removeEventListener('keyup', onDrawerKeyup); 4619 if (overlay) overlay.removeEventListener('click', onOverlayClick); 4620 const col = host && host.shadowRoot && host.shadowRoot.querySelector('.column-md--4'); 4621 if (col) { 4622 col.removeAttribute('role'); 4623 col.removeAttribute('aria-modal'); 4624 col.removeAttribute('aria-label'); 4625 } 4626 } 4627 4628 if (isMobile && !wasMobile && host && host.hasAttribute('data-filters-open')) { 4629 host.removeAttribute('data-filters-open'); 4630 const btn = host.shadowRoot && host.shadowRoot.querySelector('.hs-toolbar__filter-btn'); 4631 if (btn) btn.setAttribute('aria-expanded', 'false'); 4632 } 4633 4634 wasMobile = isMobile; 4635 }, 150); 4636 }; 4637 })()); 4638 })(); 4639</script>
vendor: 1 bytes, line 4639
4639
4640<script type="text/javascript"> 4641 /** 4642 * Range slider facet handler. 4643 * 4644 * Runs after each search execution to: 4645 * 1. Reset input values to rounded whole numbers ($ prefix shown via CSS ::before). 4646 * 2. Reset the slider track to span the result-set price range, with both 4647 * handles at the extremes (result min â result max). 4648 * 4649 * Root cause: the library positions handles relative to the full index 4650 * price range (e.g. $17â$1,400). Narrow result sets (e.g. $50â$223) 4651 * cause both handles to cluster near the left end of the track. 4652 * 4653 * Event detail uses PascalCase (matches the HawkSearch API response). 4654 * Range data lives in Facets[n].Values[0] â not Facets[n].Ranges. 4655 * 4656 * Shadow DOM path: 4657 * hawksearch-search-results (shadow) 4658 * hawksearch-facets-list (shadow) 4659 * hawksearch-facet-wrapper (shadow) â one per facet; find the slider one 4660 * hawksearch-range-slider-facet (shadow) 4661 * input[hawksearch-start] â min price text input 4662 * input[hawksearch-end] â max price text input 4663 * hawksearch-range-slider (shadow) 4664 * .range-slider__handle--start 4665 * .range-slider__handle--end 4666 * .range-slider__bar__active 4667 */ 4668 (function () { 4669 let _poll = null; 4670 4671 addEventListener('hawksearch:after-search-executed', function (e) { 4672 clearInterval(_poll); 4673 if (!e.detail || !e.detail.Facets) return; 4674 4675 // Find the price slider facet â FieldType 'range', Field 'price' 4676 let priceFacet = null; 4677 for (let i = 0; i < e.detail.Facets.length; i++) { 4678 const f = e.detail.Facets[i]; 4679 if (f.Field === 'price' && f.FieldType === 'range' && f.Values && f.Values.length) { 4680 priceFacet = f; 4681 break; 4682 } 4683 } 4684 if (!priceFacet) return; 4685 4686 // RangeStart/RangeEnd are the result-set bounds (what the handles represent). 4687 // RangeMin/RangeMax are the full index bounds (what the track spans by default). 4688 const v = priceFacet.Values[0]; 4689 const resultMin = parseFloat(v.RangeStart); 4690 const resultMax = parseFloat(v.RangeEnd); 4691 if (isNaN(resultMin) || isNaN(resultMax) || resultMin >= resultMax) return; 4692 4693 // Poll every 50ms until the slider renders (typically ~350ms after the event). 4694 // Fixed timeouts are unreliable â the slider shadow DOM isn't available until 4695 // hawksearch-facets-list finishes its async rendering cycle. 4696 let attempts = 0; 4697 _poll = setInterval(function () { 4698 attempts++; 4699 if (applySliderFix(resultMin, resultMax) || attempts >= 20) { 4700 clearInterval(_poll); 4701 } 4702 }, 50); 4703 }); 4704 4705 function applySliderFix(resultMin, resultMax) { 4706 const results = window.HSShadow.resolveResults(); 4707 if (!results || !results.shadowRoot) return false; 4708 4709 const facetsList = results.shadowRoot.querySelector('hawksearch-facets-list'); 4710 if (!facetsList || !facetsList.shadowRoot) return false; 4711 4712 // Find the hawksearch-facet-wrapper whose shadow DOM contains the range slider 4713 const wrappers = facetsList.shadowRoot.querySelectorAll('hawksearch-facet-wrapper'); 4714 let sliderFacet = null; 4715 for (let i = 0; i < wrappers.length; i++) { 4716 const sr = wrappers[i].shadowRoot; 4717 if (sr && sr.querySelector('hawksearch-range-slider-facet')) { 4718 sliderFacet = sr.querySelector('hawksearch-range-slider-facet'); 4719 break; 4720 } 4721 } 4722 if (!sliderFacet || !sliderFacet.shadowRoot) return false; 4723 4724 const facetSR = sliderFacet.shadowRoot; 4725 4726 // --- Part 1: Reset input values to rounded whole numbers --- 4727 // The $ prefix is shown via CSS ::before on .column â the input value 4728 // stays a plain number so the library can parse it normally for filtering. 4729 const startInput = facetSR.querySelector('input[hawksearch-start]'); 4730 const endInput = facetSR.querySelector('input[hawksearch-end]'); 4731 if (startInput) startInput.value = Math.round(resultMin); 4732 if (endInput) endInput.value = Math.round(resultMax); 4733 4734 // --- Part 2: Reset handles to span the full result-set range --- 4735 // The inner <hawksearch-range-slider>
4735 element holds start/end as 4736 // percentage attributes and owns the handle/bar shadow DOM. 4737 const innerSlider = facetSR.querySelector('hawksearch-range-slider'); 4738 if (!innerSlider) return false; 4739 4740 innerSlider.setAttribute('start', '0'); 4741 innerSlider.setAttribute('end', '100'); 4742 4743 const innerSR = innerSlider.shadowRoot; 4744 if (!innerSR) return false; 4745 4746 const handleStart = innerSR.querySelector('.range-slider__handle--start'); 4747 const handleEnd = innerSR.querySelector('.range-slider__handle--end'); 4748 const activeBar = innerSR.querySelector('.range-slider__bar__active'); 4749 4750 if (handleStart) handleStart.style.left = '0%'; 4751 if (handleEnd) handleEnd.style.left = '100%'; 4752 if (activeBar) { 4753 activeBar.style.left = '0%'; 4754 activeBar.style.right = '0%'; 4755 } 4756 4757 return true; 4758 } 4759 })(); 4760</script>
vendor: 1 bytes, line 4760
4760
4761<script type="text/javascript"> 4762 addEventListener('hawksearch:before-search-executed', function (e) { 4763 const request = e.detail && e.detail.request ? e.detail.request : e.detail; 4764 if (!request) return; 4765 4766 // hasSort gate commented out (2026-06-08) to force DefaultSearch on ALL searches, 4767 // not just sorted ones. To revert to the original sort-only fallback, uncomment 4768 // hasSort and restore `if (hasSort && isUnified)`. 4769 // const hasSort = request.SortBy && String(request.SortBy).length > 0; 4770 const isUnified = request.RequestType === 'UnifiedSearch'; 4771 4772 if (/* hasSort && */ isUnified) { 4773 request.RequestType = 'DefaultSearch'; 4774 if (window._hsDebug) { 4775 console.log('[HS Sort Fallback] UnifiedSearch â DefaultSearch (SortBy=' + (request.SortBy || '') + ', Keyword=' + (request.Keyword || '') + ')'); 4776 } 4777 } 4778 }); 4779</script>
vendor: 1 bytes, line 4779
4779
4780<script type="text/javascript"> 4781 // ââ Conversion attribution bridge âââââââââââââââââââââââââââââââââââââââââ 4782 // The Sale/conversion pixel (Admin â Customer events) fires on the cross-origin 4783 // thank-you page (e.g. Shop Pay on shop.app), where it cannot read this 4784 // storefront's localStorage/sessionStorage or cookies. Shopify carries CART 4785 // ATTRIBUTES into the order and exposes them on the pixel's checkout.attributes, 4786 // so we stash the Rapid-UI VisitorId/VisitId there. Written once per session 4787 // (guarded); attributes-only, so /cart/update.js leaves line items intact, and 4788 // it never blocks the storefront. 4789 // 4790 // Triggered by the library's own search/autocomplete/recs events (which fire 4791 // reliably here, unlike hawksearch:initialized) AND once immediately for 4792 // returning visitors whose IDs are already in storage. These inline listeners 4793 // attach at parse time, so they catch the initial after-search-executed that 4794 // fires on a search results page load. 4795 (function () { 4796 const writeHsCartAttributes = function () { 4797 try { 4798 const visitorId = localStorage.getItem('VisitorId'); 4799 const visitId = sessionStorage.getItem('VisitId'); 4800 if (!visitorId || !visitId) return; 4801 const sentinel = visitorId + '|' + visitId; 4802 if (sessionStorage.getItem('_hs_cart_attr_synced') === sentinel) return; 4803 fetch('/cart/update.js', { 4804 method: 'POST', 4805 headers: { 'Content-Type': 'application/json' }, 4806 body: JSON.stringify({ 4807 attributes: { 4808 hawksearch_visitor_id: visitorId, 4809 hawksearch_visit_id: visitId, 4810 }, 4811 }), 4812 }) 4813 .then(function () { 4814 sessionStorage.setItem('_hs_cart_attr_synced', sentinel); 4815 if (window._hsDebug) console.log('[HS Tracking] cart attributes synced:', sentinel); 4816 }) 4817 .catch(function () { /* tracking must never block the storefront */ }); 4818 } catch (e) { /* storage unavailable â skip silently */ } 4819 }; 4820 4821 writeHsCartAttributes(); // returning visitor: IDs may already be present 4822 [ 4823 'hawksearch:after-search-executed', 4824 'hawksearch:after-autocomplete-executed', 4825 'hawksearch:after-recommendations-executed', 4826 ].forEach(function (ev) { addEventListener(ev, writeHsCartAttributes); }); 4827 })(); 4828 4829 // ââ Native PDP Add-to-Cart tracking ââââââââââââââââââââââââââââââââââââââ 4830 // Listens for on:cart:add dispatched by product-form.js after a successful 4831 // /cart/add.js request. Covers both new items and variants already in cart. 4832 // Skips events from Hawksearch search result cards (already tracked above). 4833 // Note: on:line-item:change was removed â it fires for cart-page quantity 4834 // changes (increments AND decrements), which are not add-to-cart events. 4835 (function () { 4836 const hsDebug = window._hsDebug; 4837 function handleNativeAtcTracking(e) { 4838 if (hsDebug) console.log('[HS Tracking] ATC event received:', e.type, 'from:', e.target && e.target.tagName); 4839 4840 // Skip events from Hawksearch search result cards â already tracked 4841 // in handleHsAtcClick via HawkSearch.services.tracking.trackAddToCart(). 4842 const detail = e.detail || {}; 4843 if (detail.source === 'hawksearch') { 4844 if (hsDebug) console.log('[HS Tracking] Skipping ATC â already tracked by Hawksearch handler'); 4845 return; 4846 } 4847 4848 if (typeof HawkSearch === 'undefined' || !HawkSearch.services || !HawkSearch.services.tracking) { 4849 if (hsDebug) console.warn('[HS Tracking] trackAddToCart skipped - tracking not available'); 4850 return; 4851 } 4852 4853 const cart = detail.cart; 4854 const variantId = detail.variantId; 4855 if (!cart || !variantId) return; 4856 4857 const item = cart.items.find(function (i) { return i.variant_id === variantId; }); 4858 if (!item) return; 4859 4860 const price = item.price / 100; 4861 const currency = cart.currency || 'USD'; 4862 4863 // Send the parent product_id (= Shopify product handle from the cart line item), matching the 4864 // index primary key and the library-fired Click/Recs events â NOT the Shopify variant id. 4865 const trackProductId = item.handle; 4866 HawkSearch.services.tracking.trackAddToCart(String(trackProductId), 1, price, currency); 4867 if (hsDebug) { 4868 console.log('[HS Tracking] trackAddToCart (native PDP):', { 4869 event: e.type, productId: String(trackProductId), variantId: variantId, price: price, currency: currency 4870 }); 4871 } 4872 } 4873 document.addEventListener('on:cart:add', handleNativeAtcTracking); 4874 })(); 4875 4876 // ââ Page-load tracking + debug âââââââââââââââââââââââââââââââââââââââââââ 4877 // Guard against a re-fired hawksearch:initialized â it would double-count the page-load 4878 // ping and stack the debug listeners. Flag is set only AFTER tracking is confirmed available. 4879 let hsTrackInitDone = false;
4880 addEventListener('hawksearch:initialized', function () { 4881 if (hsTrackInitDone) return; 4882 const hsDebug = window._hsDebug; 4883 const tracking = HawkSearch.services && HawkSearch.services.tracking; 4884 4885 if (!tracking) { 4886 if (hsDebug) console.warn('[HS Tracking] HawkSearch.services.tracking not available'); 4887 return; 4888 } 4889 hsTrackInitDone = true; 4890 4891 // ââ Page-load tracking âââââââââââââââââââââââââââââââââââââââââââââââââ 4892 // De-dup: the library's own search-results and landing-page components already 4893 // auto-fire trackPageLoad (search â Custom/5, landing â Landing/2). Skip our call 4894 // when one of those server-rendered elements is present so PageLoad isn't sent twice. 4895 // We still cover the surfaces the library ignores: PDP, cart, and everything else. 4896 // (Same selectors the search-failed handler below uses to locate the HS section.) 4897 const libraryTracksPageLoad = 4898 document.querySelector('hawksearch-search-results') || 4899 document.querySelector('hawksearch-landing-page'); 4900 4901 if (libraryTracksPageLoad) { 4902 if (hsDebug) console.log('[HS Tracking] trackPageLoad skipped â library auto-tracks this surface (search/landing)'); 4903 } else { 4904 const template = 'product'; 4905 let pageType = 5; // default: Other 4906 let productId = undefined; 4907 4908 if (template === 'product') { 4909 pageType = 1; // PDP 4910 const canonicalEl = document.querySelector('link[rel="canonical"]'); 4911 if (canonicalEl) { 4912 const match = canonicalEl.href.match(/\/products\/([^/?#]+)/); 4913 if (match) productId = match[1]; 4914 } 4915 } else if (template === 'cart') { 4916 pageType = 3; // Cart 4917 } 4918 4919 tracking.trackPageLoad(pageType, productId); 4920 if (hsDebug) console.log('[HS Tracking] trackPageLoad:', { pageType: pageType, productId: productId, template: template }); 4921 } 4922 4923 // ââ Debug: log search and autocomplete tracking events âââââââââââââââââ 4924 if (hsDebug) { 4925 addEventListener('hawksearch:after-search-executed', function (e) { 4926 const detail = e.detail || {}; 4927 console.log('[HS Tracking] Search executed:', { 4928 trackingId: detail.TrackingId || detail.trackingId, 4929 keyword: detail.Keyword || detail.keyword, 4930 totalResults: detail.Pagination ? detail.Pagination.NofResults : undefined, 4931 }); 4932 if (detail.Merchandising || detail.PageContent) { 4933 console.log('[HS Content Zones] Merchandising:', detail.Merchandising); 4934 console.log('[HS Content Zones] PageContent:', detail.PageContent); 4935 } 4936 }); 4937 4938 addEventListener('hawksearch:after-autocomplete-executed', function (e) { 4939 console.log('[HS Tracking] Autocomplete executed:', e.detail); 4940 }); 4941 4942 addEventListener('hawksearch:before-recommendations-executed', function (e) { 4943 console.log('[HS Tracking] Recommendations request:', e.detail); 4944 }); 4945 addEventListener('hawksearch:after-recommendations-executed', function (e) { 4946 const detail = e.detail || {}; 4947 console.log('[HS Tracking] Recommendations response:', { 4948 widgetId: detail.WidgetId || detail.widgetId, 4949 itemCount: detail.Items ? detail.Items.length : 0, 4950 }); 4951 }); 4952 4953 console.log('[HS Tracking] Debug mode enabled. VisitorId:', 4954 localStorage.getItem('VisitorId'), 4955 'VisitId:', sessionStorage.getItem('VisitId') 4956 ); 4957 } 4958 }); 4959 4960 // ââ Search-failed error handler (v6.2.1+) ââââââââââââââââââââââââââââââââ 4961 // Injects a visible error message into the light DOM above 4962 // <hawksearch-search-results> when the search API call fails. 4963 // Clears automatically when a subsequent search succeeds. 4964 (function () { 4965 const ERROR_ID = 'hs-search-error'; 4966 4967 function getSection() { 4968 // Walk up from the HS custom element â works regardless of how Shopify 4969 // generates the section id (legacy: shopify-section-hawksearch-results; 4970 // JSON template: shopify-section-template--XXXXX__hawksearch-results). 4971 const hsEl = document.querySelector('hawksearch-search-results') || 4972 document.querySelector('hawksearch-landing-page'); 4973 if (hsEl) return hsEl.closest('[id^="shopify-section-"]') || hsEl; 4974 return null; 4975 } 4976 4977 function showSearchError(message) { 4978 const section = getSection(); 4979 if (!section) return; 4980 4981 const existing = document.getElementById(ERROR_ID); 4982 if (existing) existing.remove(); 4983 4984 const el = document.createElement('div'); 4985 el.id = ERROR_ID; 4986 el.setAttribute('role', 'alert'); 4987 el.className = 'alert bg-error-bg text-error-text mb-8'; 4988 el.style.cssText = 'padding: 1rem 1.25rem; border-radius: 4px; margin: 1rem 0;'; 4989 el.textContent = message || 'Search is temporarily unavailable. Please try again in a moment.'; 4990 section.insertBefore(el, section.firstChild); 4991 } 4992 4993 function clearSearchError() { 4994 const el = document.getElementById(ERROR_ID); 4995 if (el) el.remove(); 4996 } 4997 4998 const hsDebug = window._hsDebug; 4999 addEventListener('hawksearch:search-failed', function (e) { 5000 const detail = e.detail || {}; 5001 if (hsDebug) console.warn('[HS] Search failed:', detail); 5002 showSearchError(detail.message || detail.error || null); 5003 }); 5004 5005 addEventListener('hawksearch:after-search-executed', clearSearchError); 5006 })(); 5007 5008 // ââ Elevar dl_view_search_results bridge âââââââââââââââââââââââââââââââââ 5009 // Elevar's Shopify listener built dl_view_search_results by reading the native 5010 // product grid from the DOM. HawkSearch renders results into shadow DOM, which 5011 // Elevar can't read, so the event stopped firing â taking GTM trigger 1166 and 5012 // its search tags (GA4 - Search, Facebook, Google Ads, TikTok) down with it. 5013 // We re-push the event in the same shape on hawksearch:after-search-executed. 5014 // 5015 // Push to ElevarDataLayer (NOT window.dataLayer): Elevar enriches it (event_id, 5016 // user_properties via its own context push) and mirrors it to window.dataLayer, 5017 // keeping consent-gating and server-side forwarding consistent with every other 5018 // dl_ event. Hosted in the theme, not GTM, so the listener arms at parse time. 5019 // 5020 // ORDERING (critical): GTM's "GA4 Base Tag Configuration" (googtag) fires ONLY on 5021 // Elevar's dl_user_data event (trigger 1148). The GA4 - Search event tag (trigger 5022 // 1166) has no config dependency of its own, so if our event reaches GTM BEFORE 5023 // dl_user_data, GA4 isn't configured yet and the event is silently dropped. On a 5024 // hard /search load HawkSearch fires after-search-executed (~3.5s) well before 5025 // Elevar boots and emits dl_user_data (~7.4s) â so the FIRST search would be lost 5026 // (in-page re-searches work because the context already exists). We therefore mirror 5027 // Elevar's own native ordering: hold the push until dl_user_data has reached 5028 // window.dataLayer. This also avoids the duplicate Elevar produces when it 5029 // reprocesses a push that arrived before it initialized. 5030 (function () { 5031 const IMPRESSION_CAP = 14; // keep serialized event < 4000 chars (Elevar limit) 5032 const CONTEXT_TIMEOUT = 12000; // ms: push anyway so the event is never silently lost 5033 const hsDebug = window._hsDebug; 5034 let lastKeyword = null; 5035 const first = function (a) { return (Array.isArray(a) && a.length) ? a[0] : ''; }; 5036 5037 const contextReady = function () { 5038 return (window.dataLayer || []).some(function (e) { return e && e.event === 'dl_user_data'; }); 5039 }; 5040 5041 const pushSearchEvent = function (evt, keyword) { 5042 // No user_properties: Elevar (Shopify source) supplies it via its own context push. 5043 window.ElevarDataLayer = window.ElevarDataLayer || []; 5044 window.ElevarDataLayer.push(evt); 5045 if (hsDebug) { 5046 console.log('[HS Tracking] dl_view_search_results pushed:', { 5047 keyword: keyword, impressions: evt.ecommerce.impressions.length 5048 }); 5049 } 5050 }; 5051 5052 const pushWhenContextReady = function (evt, keyword) { 5053 if (contextReady()) { pushSearchEvent(evt, keyword); return; } 5054 let waited = 0; 5055 const interval = setInterval(function () { 5056 waited += 200; 5057 if (contextReady()) { 5058 clearInterval(interval); 5059 pushSearchEvent(evt, keyword); 5060 } else if (waited >= CONTEXT_TIMEOUT) { 5061 clearInterval(interval); 5062 if (hsDebug) console.warn('[HS Tracking] dl_user_data not seen after ' + CONTEXT_TIMEOUT + 'ms â pushing search event anyway'); 5063 pushSearchEvent(evt, keyword); 5064 } 5065 }, 200); 5066 }; 5067 5068 addEventListener('hawksearch:after-search-executed', function (e) { 5069 const detail = e.detail || {}; 5070 const items = detail.Results || []; 5071 if (!Array.isArray(items) || !items.length) return; 5072
5073 const keyword = detail.Keyword || ''; 5074 // Only track genuine keyword searches. hawksearch:after-search-executed ALSO 5075 // fires on HawkSearch landing pages (e.g. /pages/hawksearch) â verified live: 5076 // 48 results but Keyword "". Pushing there would fire the search GTM tags 5077 // (GA4 - Search et al.) on a non-search page with a blank search_query. 5078 if (!keyword) return; 5079 if (keyword === lastKeyword) return; // de-dup re-renders/filters for same keyword 5080 lastKeyword = keyword; 5081 5082 const impressions = items.slice(0, IMPRESSION_CAP).map(function (it, i) { 5083 const doc = it.Document || {}; 5084 const v = (doc.hawk_child_attributes && doc.hawk_child_attributes[0]) || {}; 5085 // price/compare_at_price live on the variant child in this index (myeg/PH â verified live 5086 // 2026-07-24: doc has no price field, hawk_child_attributes[0].price is populated). Fall back 5087 // to the document level so the bridge stays correct on index schemas that store them at the 5088 // parent instead â otherwise those would push a blank price on every impression. 5089 const cmp = first(v.compare_at_price) || first(doc.compare_at_price); 5090 return { 5091 id: first(v.sku) || first(doc.product_id) || first(doc.key), 5092 name: first(doc.title) || first(doc.name), // raw index title field: 'title' (myeg/PH) or 'name' (tsa) 5093 brand: first(doc.brand), 5094 category: Array.isArray(doc.category) ? doc.category.join('/') : '', 5095 variant: first(v.size) || first(v.color), // variant dimension field: 'size' (myeg/PH) or 'color' (tsa) 5096 price: first(v.price) || first(doc.price), 5097 compare_at_price: (cmp && cmp !== '0.00') ? cmp : '', 5098 product_id: first(doc.product_id) || first(doc.key), // raw index id field: 'product_id' (myeg/PH) or 'key' (tsa) 5099 variant_id: first(v.variant_id), 5100 position: i + 1, 5101 }; 5102 }); 5103 5104 pushWhenContextReady({ 5105 event: 'dl_view_search_results', 5106 ecommerce: { 5107 currencyCode: 'USD', 5108 actionField: { list: 'search results' }, 5109 impressions: impressions, 5110 }, 5111 }, keyword); 5112 }); 5113 })(); 5114</script>
5114 5115 5116 <!-- End Hawksearch --><style data-shopify> 5117@font-face { 5118 font-family: Lato; 5119 font-weight: 500; 5120 font-style: normal; 5121 font-display: swap; 5122 src: url("//myevergreen.com/cdn/fonts/lato/lato_n5.b2fec044fbe05725e71d90882e5f3b21dae2efbd.woff2") format("woff2"), 5123 url("//myevergreen.com/cdn/fonts/lato/lato_n5.f25a9a5c73ff9372e69074488f99e8ac702b5447.woff") format("woff"); 5124} 5125@font-face { 5126 font-family: Lato; 5127 font-weight: 700; 5128 font-style: normal; 5129 font-display: swap; 5130 src: url("//myevergreen.com/cdn/fonts/lato/lato_n7.900f219bc7337bc57a7a2151983f0a4a4d9d5dcf.woff2") format("woff2"), 5131 url("//myevergreen.com/cdn/fonts/lato/lato_n7.a55c60751adcc35be7c4f8a0313f9698598612ee.woff") format("woff"); 5132} 5133@font-face { 5134 font-family: Lato; 5135 font-weight: 500; 5136 font-style: italic; 5137 font-display: swap; 5138 src: url("//myevergreen.com/cdn/fonts/lato/lato_i5.9501f9e8a9e09e142687495e156dec167f6a3ea3.woff2") format("woff2"), 5139 url("//myevergreen.com/cdn/fonts/lato/lato_i5.eca6cbf1aa9c70cc6dbfed0353a2f57e5065c864.woff") format("woff"); 5140} 5141@font-face { 5142 font-family: Lato; 5143 font-weight: 700; 5144 font-style: italic; 5145 font-display: swap; 5146 src: url("//myevergreen.com/cdn/fonts/lato/lato_i7.16ba75868b37083a879b8dd9f2be44e067dfbf92.woff2") format("woff2"), 5147 url("//myevergreen.com/cdn/fonts/lato/lato_i7.4c07c2b3b7e64ab516aa2f2081d2bb0366b9dce8.woff") format("woff"); 5148} 5149@font-face { 5150 font-family: Merriweather; 5151 font-weight: 400; 5152 font-style: normal; 5153 font-display: swap; 5154 src: url("//myevergreen.com/cdn/fonts/merriweather/merriweather_n4.349a72bc63b970a8b7f00dc33f5bda2ec52f79cc.woff2") format("woff2"), 5155 url("//myevergreen.com/cdn/fonts/merriweather/merriweather_n4.5a396c75a89c25b516c9d3cb026490795288d821.woff") format("woff"); 5156} 5157@font-face { 5158 font-family: Lato; 5159 font-weight: 700; 5160 font-style: normal; 5161 font-display: swap; 5162 src: url("//myevergreen.com/cdn/fonts/lato/lato_n7.900f219bc7337bc57a7a2151983f0a4a4d9d5dcf.woff2") format("woff2"), 5163 url("//myevergreen.com/cdn/fonts/lato/lato_n7.a55c60751adcc35be7c4f8a0313f9698598612ee.woff") format("woff"); 5164} 5165:root { 5166 --bg-color: 255 255 255 / 1.0; 5167 --bg-color-og: 255 255 255 / 1.0; 5168 --heading-color: 9 3 2; 5169 --text-color: 34 34 34; 5170 --text-color-og: 34 34 34; 5171 --scrollbar-color: 34 34 34; 5172 --link-color: 218 82 86; 5173 --link-color-og: 218 82 86; 5174 --star-color: 243 224 36;--swatch-border-color-default: 211 211 211; 5175 --swatch-border-color-active: 145 145 145; 5176 --swatch-card-size: 32px; 5177 --swatch-variant-picker-size: 50px;--color-scheme-1-bg: 0 145 116 / 1.0; 5178 --color-scheme-1-grad: ; 5179 --color-scheme-1-heading: 255 255 255; 5180 --color-scheme-1-text: 255 255 255; 5181 --color-scheme-1-btn-bg: 255 255 255; 5182 --color-scheme-1-btn-text: 0 145 116; 5183 --color-scheme-1-btn-bg-hover: 228 244 240;--color-scheme-2-bg: 255 255 255 / 1.0; 5184 --color-scheme-2-grad: ; 5185 --color-scheme-2-heading: 0 145 116; 5186 --color-scheme-2-text: 34 34 34; 5187 --color-scheme-2-btn-bg: 255 255 255; 5188 --color-scheme-2-btn-text: 0 145 116; 5189 --color-scheme-2-btn-bg-hover: 228 244 240;--color-scheme-3-bg: 0 0 0 / 0.0; 5190 --color-scheme-3-grad: ; 5191 --color-scheme-3-heading: 34 34 34; 5192 --color-scheme-3-text: 34 34 34; 5193 --color-scheme-3-btn-bg: 255 255 255; 5194 --color-scheme-3-btn-text: 0 145 116; 5195 --color-scheme-3-btn-bg-hover: 228 244 240; 5196 5197 --drawer-bg-color: 255 255 255 / 1.0; 5198 --drawer-text-color: 9 3 2; 5199 5200 --panel-bg-color: 242 242 242 / 1.0; 5201 --panel-heading-color: 9 3 2; 5202 --panel-text-color: 9 3 2; 5203 5204 --in-stock-text-color: 44 126 63; 5205 --low-stock-text-color: 210 134 26; 5206 --very-low-stock-text-color: 180 12 28; 5207 --no-stock-text-color: 119 119 119; 5208 --no-stock-backordered-text-color: 119 119 119; 5209 5210 --error-bg-color: 252 237 238; 5211 --error-text-color: 180 12 28; 5212 --success-bg-color: 232 246 234; 5213 --success-text-color: 44 126 63; 5214 --info-bg-color: 228 237 250; 5215 --info-text-color: 26 102 210; 5216 5217 --heading-font-family: Merriweather, serif; 5218 --heading-font-style: normal;
5219 --heading-font-weight: 400; 5220 --heading-scale-start: 6; 5221 5222 --navigation-font-family: Lato, sans-serif; 5223 --navigation-font-style: normal; 5224 --navigation-font-weight: 700;--heading-text-transform: none; 5225--subheading-text-transform: none; 5226 --body-font-family: Lato, sans-serif; 5227 --body-font-style: normal; 5228 --body-font-weight: 500; 5229 --body-font-size: 16; 5230 5231 --section-gap: 32; 5232 --heading-gap: calc(8 * var(--space-unit));--heading-gap: calc(6 * var(--space-unit));--grid-column-gap: 20px;--btn-bg-color: 218 82 86; 5233 --btn-bg-hover-color: 227 121 123; 5234 --btn-text-color: 255 255 255; 5235 --btn-bg-color-og: 218 82 86; 5236 --btn-text-color-og: 255 255 255; 5237 --btn-alt-bg-color: 255 255 255; 5238 --btn-alt-bg-alpha: 1.0; 5239 --btn-alt-text-color: 218 82 86; 5240 --btn-border-width: 2px; 5241 --btn-padding-y: 12px; 5242 5243 5244 5245 --btn-lg-border-radius: 50%; 5246 --btn-icon-border-radius: 50%; 5247 --input-with-btn-inner-radius: var(--btn-border-radius); 5248 5249 --input-bg-color: 255 255 255 / 1.0; 5250 --input-text-color: 34 34 34; 5251 --input-border-width: 2px; 5252 --input-border-radius: 1px; 5253 --textarea-border-radius: 1px; 5254 --input-bg-color-diff-3: #f7f7f7; 5255 --input-bg-color-diff-6: #f0f0f0; 5256 5257 --modal-border-radius: 0px; 5258 --modal-overlay-color: 0 0 0; 5259 --modal-overlay-opacity: 0.4; 5260 --drawer-border-radius: 0px; 5261 --overlay-border-radius: 0px;--custom-label-bg-color: 35 2 46; 5262 --custom-label-text-color: 255 255 255;--sale-label-bg-color: 247 23 53; 5263 --sale-label-text-color: 255 255 255;--sold-out-label-bg-color: 73 93 99; 5264 --sold-out-label-text-color: 255 255 255;--new-label-bg-color: 126 203 187; 5265 --new-label-text-color: 9 3 2;--preorder-label-bg-color: 103 170 249; 5266 --preorder-label-text-color: 255 255 255;--in-stock-label-bg-color: 0 145 116; 5267 --in-stock-label-text-color: 255 255 255; 5268 5269 --collection-label-color: 0 126 18; 5270 5271 --page-width: 1590px; 5272 --gutter-sm: 20px; 5273 --gutter-md: 32px; 5274 --gutter-lg: 64px; 5275 5276 --payment-terms-bg-color: #ffffff; 5277 5278 --coll-card-bg-color: #f7f7f7; 5279 --coll-card-border-color: rgba(0,0,0,0); 5280 5281 --card-highlight-bg-color: #F9F9F9; 5282 --card-highlight-text-color: 85 85 85; 5283 --card-highlight-border-color: #E1E1E1;--card-bg-color: #fafafa; 5284 --card-text-color: 0 0 0; 5285 --card-border-color: #f7f7f7; 5286 5287 --reading-width: 48em; 5288 } 5289 5290 @media (max-width: 769px) { 5291 :root { 5292 --reading-width: 36em; 5293 } 5294 }</style> 5295 5296 <link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/main.css?v=123728977702231552111785770819"> 5297
5297<script src="//myevergreen.com/cdn/shop/t/101/assets/main.js?v=76476094356780495751781124410" defer="defer"></script>
5297<link 5298 rel="preload" 5299 href="//myevergreen.com/cdn/fonts/lato/lato_n5.b2fec044fbe05725e71d90882e5f3b21dae2efbd.woff2" 5300 as="font" 5301 type="font/woff2" 5302 crossorigin 5303 fetchpriority="high" 5304 ><link 5305 rel="preload" 5306 href="//myevergreen.com/cdn/fonts/merriweather/merriweather_n4.349a72bc63b970a8b7f00dc33f5bda2ec52f79cc.woff2" 5307 as="font" 5308 type="font/woff2" 5309 crossorigin 5310 fetchpriority="high" 5311 >
5311<script>window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.start');</script>
5311<meta name="google-site-verification" content="aULSH9HaPaz5EnQZB3beQl2gqhOIgkswwolgizyOJfM"> 5312<meta id="shopify-digital-wallet" name="shopify-digital-wallet" content="/59637006390/digital_wallets/dialog"> 5313<meta id="in-context-paypal-metadata" data-shop-id="59637006390" data-venmo-supported="true" data-environment="production" data-locale="en_US" data-paypal-v4="true" data-currency="USD"> 5314<link rel="ucp" href="/.well-known/ucp" version="2026-08-25"><link rel="buy" href="/cart/42920115601462:1?ucp/version=2026-08-25&context/payment/0/handler=dev.shopify.shop_pay" payment="dev.shopify.shop_pay com.google.pay dev.shopify.card"><link rel="alternate" type="application/json+oembed" href="https://myevergreen.com/products/01245.oembed">
5315<script async="async" src="/checkouts/internal/preloads.js?locale=en-US&default_configuration_id=18645046"></script>
5315 5316<link rel="preconnect" href="https://shop.app" crossorigin="anonymous">
5317<script async="async" src="https://shop.app/checkouts/internal/preloads.js?locale=en-US&default_configuration_id=18645046&shop_id=59637006390" crossorigin="anonymous"></script>
vendor: 1 bytes, line 5317
5317
5318<script id="apple-pay-shop-capabilities" type="application/json">{"shopId":59637006390,"countryCode":"US","currencyCode":"USD","merchantCapabilities":["supports3DS"],"merchantId":"gid:\/\/shopify\/Shop\/59637006390","merchantName":"Evergreen","requiredBillingContactFields":["postalAddress","email"],"requiredShippingContactFields":["postalAddress","email"],"shippingType":"shipping","supportedNetworks":["visa","masterCard","amex","discover","elo","jcb"],"total":{"type":"pending","label":"Evergreen","amount":"1.00"},"shopifyPaymentsEnabled":true,"supportsSubscriptions":true}</script>
vendor: 1 bytes, line 5318
5318
5319<script id="shopify-features" type="application/json">{"accessToken":"f7dcda31aaa116f4db7bc4bc0121106c","betas":["rich-media-storefront-analytics"],"domain":"myevergreen.com","predictiveSearch":true,"shopId":59637006390,"locale":"en"}</script>
vendor: 1 bytes, line 5319
5319
5320<script>var Shopify = Shopify || {}; 5321Shopify.shop = "9695f5-c4.myshopify.com"; 5322Shopify.locale = "en"; 5323Shopify.currency = {"active":"USD","rate":"1.0"}; 5324Shopify.country = "US"; 5325Shopify.theme = {"name":"eg-d2c-theme\/Hawksearch","id":153311182902,"schema_name":"Enterprise","schema_version":"1.6.2","theme_store_id":null,"role":"main"}; 5326Shopify.theme.handle = "null"; 5327Shopify.theme.style = {"id":null,"handle":null}; 5328Shopify.cdnHost = "myevergreen.com/cdn"; 5329Shopify.routes = Shopify.routes || {}; 5330Shopify.routes.root = "/"; 5331Shopify.shopJsCdnBaseUrl = "https://cdn.shopify.com/shopifycloud/shop-js"; 5332Shopify.SignInWithShop = Shopify.SignInWithShop || {}; 5333Shopify.SignInWithShop.User = Shopify.SignInWithShop.User || {}; 5334Shopify.SignInWithShop.User.recognized = false;</script>
vendor: 1 bytes, line 5334
5334
5335<script type="module">!function(o){(o.Shopify=o.Shopify||{}).modules=!0}(window);</script>
vendor: 1 bytes, line 5335
5335
5336<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 5336
5336
5337<script> 5338 window.ShopifyPay = window.ShopifyPay || {}; 5339 window.ShopifyPay.apiHost = "shop.app\/pay"; 5340 window.ShopifyPay.redirectState = null; 5341</script>
vendor: 1 bytes, line 5341
5341
5342<script> 5343 window.Shopify = window.Shopify || {}; 5344 window.Shopify.SignInWithShop = window.Shopify.SignInWithShop || {}; 5345 window.Shopify.SignInWithShop.assetMetrics = { sampleRate: 0.25 }; 5346 window.Shopify.SignInWithShop.eligible = true; 5347</script>
vendor: 1 bytes, line 5347
5347
5348<script id="shop-js-analytics" type="application/json">{"pageType":"product"}</script>
vendor: 1 bytes, line 5348
5348
5349<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 5349
5349
5350<script type="module"> 5351 await import("https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.init-shop-cart-sync.en.esm.js"); 5352 5353 window.Shopify.SignInWithShop?.initShopCartSync?.({"fedCMEnabled":true,"windoidEnabled":true}); 5354 5355</script>
vendor: 1 bytes, line 5355
5355
5356<script defer="defer" async type="module" src="https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.payment-terms.en.esm.js"></script>
vendor: 1 bytes, line 5356
5356
5357<script type="module"> 5358 await import("https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.payment-terms.en.esm.js"); 5359 5360 5361</script>
vendor: 1 bytes, line 5361
5361
5362<script> 5363 window.Shopify = window.Shopify || {}; 5364 if (!window.Shopify.featureAssets) window.Shopify.featureAssets = {}; 5365 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"]}; 5366</script>
vendor: 1 bytes, line 5366
5366
5367<script>(function() { 5368 var isLoaded = false; 5369 function asyncLoad() { 5370 if (isLoaded) return; 5371 isLoaded = true; 5372 var urls = ["https:\/\/rapid-cdn.yottaa.com\/rapid\/lib\/D--wAYVy-jyskg.js?shop=9695f5-c4.myshopify.com","\/\/cdn.shopify.com\/proxy\/3664d3949198e5a925c1abbdc96a08f90c8e933c44768a704f2e83f49f7d0c79\/cdn.bogos.io\/script_tag\/secomapp.scripttag.js?shop=9695f5-c4.myshopify.com\u0026sp-cache-control=cHVibGljLCBtYXgtYWdlPTkwMA","https:\/\/api-na1.hubapi.com\/scriptloader\/v1\/45696013.js?shop=9695f5-c4.myshopify.com","\/\/cdn.shopify.com\/proxy\/d316c9419534a81fd30d283fb6a1a9a081be9735d2248d3adbdf171627a24824\/edge.curalate.com\/sites\/myevergreen-ka27ik\/site\/latest\/site.min.js?shop=9695f5-c4.myshopify.com\u0026sp-cache-control=cHVibGljLCBtYXgtYWdlPTkwMA","\/\/cdn.shopify.com\/proxy\/2fe04a4424b262ed42da2d828b8c9cef46cae054851a2984566519639210db8b\/apps.bazaarvoice.com\/deployments\/myevergreen\/main_site\/production\/en_US\/bv.js?shop=9695f5-c4.myshopify.com\u0026sp-cache-control=cHVibGljLCBtYXgtYWdlPTkwMA","https:\/\/shopify-extension.getredo.com\/main.js?widget_id=nlayw7zu9wtj91j\u0026shop=9695f5-c4.myshopify.com"]; 5373 for (var i = 0; i < urls.length; i++) { 5374 var s = document.createElement('script'); 5375 s.type = 'text/javascript'; 5376 s.async = true; 5377 s.src = urls[i]; 5378 var x = document.getElementsByTagName('script')[0]; 5379 x.parentNode.insertBefore(s, x); 5380 } 5381 }; 5382 if(window.attachEvent) { 5383 window.attachEvent('onload', asyncLoad); 5384 } else { 5385 window.addEventListener('load', asyncLoad, false); 5386 } 5387})();</script>
vendor: 1 bytes, line 5387
5387
5388<script id="__st">var __st={"a":59637006390,"offset":-14400,"reqid":"47b8d99a-f2fc-4f0c-8979-273a6bd40ca1-1790697223","pageurl":"myevergreen.com\/products\/01245","u":"0439ea5b9ca1","p":"product","rtyp":"product","rid":7616317653046};</script>
vendor: 1 bytes, line 5388
5388
5389<script>window.ShopifyPaypalV4VisibilityTracking = true;</script>
vendor: 1 bytes, line 5389
5389
5390<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'])})(!0,!0)}();</script>
vendor: 1 bytes, line 5390
5390
5391<script integrity="sha256-JjoPp5ZfB1sSAs5SQaol1x1GgvveM+BgmRzyDexInEQ=" data-source-attribution="shopify.loadfeatures" defer="defer" src="//myevergreen.com/cdn/shopifycloud/storefront/assets/storefront/load_feature-1bd60354.js" crossorigin="anonymous"></script>
vendor: 1 bytes, line 5391
5391
5392<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 = "//myevergreen.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>
5392<script crossorigin="anonymous" defer="defer" src="//myevergreen.com/cdn/shopifycloud/storefront/assets/shopify_pay/storefront-616277c7.js?v=20250812"></script>
vendor: 1 bytes, line 5392
5392
5393<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 5393
5393
5394<script> 5395 window.Shopify = window.Shopify || {}; 5396 window.Shopify.MCP = window.Shopify.MCP || {}; 5397 window.Shopify.MCP.enabled = true; 5398 window.Shopify.MCP.shop = "9695f5-c4.myshopify.com"; 5399 window.Shopify.MCP.mcpEndpoint = "https:\/\/myevergreen.com\/api\/mcp"; 5400 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"]}}]; 5401</script>
vendor: 1 bytes, line 5401
5401
5402<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("\/\/myevergreen.com\/cdn\/shopifycloud\/storefront\/assets\/storefront\/webmcp-c6b62ece.js","sha256-ke4DDuBjdvea3vxLWxHc9E9nq8zihuG4IfYEGbb77ys=");})(); 5403</script>
vendor: 1 bytes, line 5403
5403
5404<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://myevergreen.com/cdn/shopifycloud/portable-wallets/latest/portable-wallets.en.js",t.type="module",document.head.appendChild(t)}}; 5405</script>
vendor: 1 bytes, line 5405
5405
5406<script data-source-attribution="shopify.dynamic_checkout.buyer_consent"> 5407 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); 5408</script>
vendor: 1 bytes, line 5408
5408
5409<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})}})); 5410</script>
vendor: 1 bytes, line 5410
5410
5411<script id='scb4127' type='text/javascript' async='' src='https://myevergreen.com/cdn/shopifycloud/privacy-banner/storefront-banner.js'></script>
5411<script integrity="sha256-/LA1C2Bx6899fYCos0FS9qLj2opaGFm7AXrTUvBEb4s=" data-source-attribution="shopify.remote_product_tracking" data-shopify-remote-tracking="{"publisher_shop_id":59637006390,"theme_id":153311182902,"theme_published":true,"theme_store_id":0,"placement":"collection","event_data":{"source_product_id":7616317653046,"handle":"01245","page_type":"product"},"recommendations_tracking_enabled":true}" defer="defer" src="//myevergreen.com/cdn/shopifycloud/storefront/assets/storefront/remote_product_tracking-91d95044.js" crossorigin="anonymous"></script>
5411 5412<link id="shopify-accelerated-checkout-styles" rel="stylesheet" media="screen" href="https://myevergreen.com/cdn/shopifycloud/portable-wallets/latest/accelerated-checkout-backwards-compat.css" crossorigin="anonymous"> 5413<style id="shopify-accelerated-checkout-cart"> 5414 #shopify-buyer-consent { 5415 margin-top: 1em; 5416 display: inline-block; 5417 width: 100%; 5418} 5419 5420#shopify-buyer-consent.hidden { 5421 display: none; 5422} 5423 5424#shopify-subscription-policy-button { 5425 background: none; 5426 border: none; 5427 padding: 0; 5428 text-decoration: underline; 5429 font-size: inherit; 5430 cursor: pointer; 5431} 5432 5433#shopify-subscription-policy-button::before { 5434 box-shadow: none; 5435} 5436 5437 </style>
5438<script id="sections-script" data-sections="header,footer" defer="defer" src="//myevergreen.com/cdn/shop/t/101/compiled_assets/scripts.js?v=132263383497981015851781124469"></script>
vendor: 1 bytes, line 5438
5438
5439<script id="shopify-cfh-end">window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.end');</script>
5439 5440 5441 5442
5442<script> 5443 document.documentElement.className = document.documentElement.className.replace('no-js', 'js'); 5444 </script>
5444 5445 5446 <meta name="msvalidate.01" content="F192C841575CA39E4AEFDDD124E82AE0" /><!-- CC Custom Head Start --><!-- CC Custom Head End --><link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/powerreviews-override.css?v=24924460965620797161781124412"> 5447 5448 <meta name="robots" content="index,follow"> 5449 5450 <!-- BEGIN app block: shopify://apps/checkmate/blocks/checked_network/697a3444-1374-4f13-ba8c-ec03db25ebf0 --> 5451
5451<script 5452 src='/apps/cm/v1/load?source=embed' 5453 async 5454 ></script>
5454 5455 5456 5457 5458<!-- END app block --><!-- BEGIN app block: shopify://apps/microsoft-clarity/blocks/clarity_js/31c3d126-8116-4b4a-8ba1-baeda7c4aeea -->
5459<script type="text/javascript"> 5460 (function (c, l, a, r, i, t, y) { 5461 c[a] = c[a] || function () { (c[a].q = c[a].q || []).push(arguments); }; 5462 t = l.createElement(r); t.async = 1; t.src = "https://www.clarity.ms/tag/" + i + "?ref=shopify"; 5463 y = l.getElementsByTagName(r)[0]; y.parentNode.insertBefore(t, y); 5464 5465 c.Shopify.loadFeatures([{ name: "consent-tracking-api", version: "0.1" }], error => { 5466 if (error) { 5467 console.error("Error loading Shopify features:", error); 5468 return; 5469 } 5470 5471 c[a]('consentv2', { 5472 ad_Storage: c.Shopify.customerPrivacy.marketingAllowed() ? "granted" : "denied", 5473 analytics_Storage: c.Shopify.customerPrivacy.analyticsProcessingAllowed() ? "granted" : "denied", 5474 source: 101, 5475 }); 5476 }); 5477 5478 l.addEventListener("visitorConsentCollected", function (e) { 5479 c[a]('consentv2', { 5480 ad_Storage: e.detail.marketingAllowed ? "granted" : "denied", 5481 analytics_Storage: e.detail.analyticsAllowed ? "granted" : "denied", 5482 source: 101, 5483 }); 5484 }); 5485 })(window, document, "clarity", "script", "sra4j57sci"); 5486</script>
5486 5487 5488 5489 5490<!-- END app block --><!-- BEGIN app block: shopify://apps/nospy-protect-data/blocks/app-block/0ea824f6-5b8e-445c-b27f-1d4763c81aa3 -->
5490<script> 5491 5492 const noSpySettings = {"v":1,"activation_status":true,"protect_sales":true,"analytic_log":true,"access_token":"cU2UFDuoUdHcQu8pt9rU0f21GWbuPs6FoYxD7T5xCKpmraNSMCfeQQJMwVCi0Oijfkkjh6Ihm7ipkNQ0zykJZom3WN2qNVh4eRQJ2wOmBsSrKU3gf1HYxswDQRdb0bQ4GbumRVd1HWtjMO3oR","token_session_days":1,"settings":{"image_drag":true,"right_click":true,"text_selection":true,"copy_paste":true,"keys_shortcuts":true,"spy_extensions":1,"spy_extensions_block_mode":1,"spy_extensions_redirect_url":null,"inspect_elements":true,"web_page_print":true,"inspect_elements_message":"WARNING - This website is legally protected. Our content is copyrighted and our trademark is registered. ð« Any copy is prohibited and may lead to legal action.","block_spam_bots":false,"proxy_vpn_block":1,"proxy_vpn_redirect_url":null,"tor_block":1,"redirect":0},"excludes":[],"allowed_bots":{"bing_bot":true,"apple_bot":true,"ahrefs_bot":true,"google_bot":true,"semrush_bot":true,"facebook_bot":true,"linkedin_bot":true,"pinterest_bot":true,"lighthouse_bot":true}}; 5493 5494 5495 5496 const noSpyRedirects = {"v":1,"rules":[]}; 5497 5498 5499 5500 const noSpyInternalPages = []; 5501 5502 5503 let my_shop = Shopify.shop; 5504 const noSpyBaseUrl = "https://visitors.nospyapp.com/api"; 5505 const noSpyLegacyUrl = "https://app.nospyapp.com/api"; 5506 5507 // Destinations are stored as bare hosts, but some legacy rows carry a scheme. 5508 // Prepending unconditionally produced "https://https://example.com". 5509 const toExternalUrl = (value) => { 5510 const v = String(value ?? '').trim(); 5511 return /^https?:\/\//i.test(v) ? v : `https://${v}`; 5512 }; 5513 let isNoSpyLogCreated = false; 5514 5515 window.NoSpyStore = { 5516 ip: null, 5517 geolocation: null, 5518 sessionId: null, 5519 sessionStart: null, 5520 reached: null, 5521 }; 5522 // =========================================== 5523 // BROWSER/ALLOWED BOTS DETECTION 5524 // =========================================== 5525 5526 const userAgent = navigator?.userAgent || 'unknown-user-agent'; 5527 5528 const isLighthouseMode = /Lighthouse/i.test(userAgent); 5529 const isGoogleBot = /Googlebot|Google-InspectionTool|Storebot-Google|AdsBot-Google|Lighthouse|GoogleOther|Google-CloudVertexBot|Google-Extended|APIs-Google|Mediapartners-Google|Google-Safety|DuplexWeb-Google|googleweblight|FeedFetcher-Google|GoogleProducer|Google-Read-Aloud|Google-Site-Verification/i.test(userAgent); 5530 const isFacebookBot = /facebookexternalhit|facebookcatalog|meta-webindexer|meta-externalads|meta-externalagent|meta-externalfetcher|Facebot/i.test(userAgent); 5531 const isBingBot = /bingbot|adidxbot/i.test(userAgent); 5532 const isWhitelistBots = isLighthouseMode || isGoogleBot || isFacebookBot || isBingBot; 5533 5534 // Check Iframe 5535 function isLoadedInIframe() { 5536 try { 5537 return window.self !== window.top; 5538 } catch (e) { 5539 return true; 5540 } 5541 } 5542 5543 const createHit = (data) => { 5544 fetch(`${noSpyBaseUrl}/hit?shop=${Shopify.shop}`, { 5545 method: "POST", 5546 headers: { 5547 "Content-Type": "application/json", 5548 }, 5549 body: JSON.stringify(data), 5550 }); 5551 }; 5552 5553 const createBlockLog = (payload) => { 5554 const data = JSON.stringify(payload); 5555 if (navigator.sendBeacon) { 5556 navigator.sendBeacon(`${noSpyBaseUrl}/block/log`, data); 5557 } else { 5558 fetch(`${noSpyBaseUrl}/block/log`, { 5559 method: 'POST', 5560 body: data, 5561 headers: { 'Content-Type': 'application/json' } 5562 }); 5563 } 5564 } 5565 5566 class SessionService { 5567 constructor() { 5568 this.sessionKey = 'no_spy_session_id'; 5569 this.lastSeenKey = 'no_spy_last_seen_at'; 5570 this.timeout = 30 * 60 * 1000; 5571 } 5572 5573 getSessionId() { 5574 return sessionStorage.getItem(this.sessionKey); 5575 } 5576 5577 init() { 5578 const now = Date.now(); 5579 let sessionId = this.getSessionId(); 5580 let lastSeen = parseInt(localStorage.getItem(this.lastSeenKey) || "0"); 5581 5582 if (!sessionId || (now - lastSeen) > this.timeout) { 5583 sessionId = crypto.randomUUID(); 5584 sessionStorage.setItem(this.sessionKey, sessionId); 5585 } 5586 5587 NoSpyStore.sessionId = sessionId; 5588 NoSpyStore.sessionStart = now; 5589 this.updateLastSeen(); 5590 this.attachListeners(); 5591 } 5592 5593 updateLastSeen() { 5594 const now = Date.now(); 5595 const lastUpdated = parseInt(localStorage.getItem(this.lastSeenKey), 10) || 0; 5596 if (now - lastUpdated > 5000) { 5597 // Update local storage 5598 localStorage.setItem(this.lastSeenKey, now.toString()); 5599 } 5600 } 5601 5602 attachListeners() { 5603 const update = this.updateLastSeen.bind(this); 5604 document.addEventListener('visibilitychange', update); 5605 document.addEventListener('mousemove', update); 5606 document.addEventListener('keydown', update); 5607 } 5608 5609 sendBeacon(ip) { 5610 if (!ip) return; 5611 5612 const duration = Math.floor((Date.now() - NoSpyStore.sessionStart) / 1000); 5613 const payload = JSON.stringify({ 5614 duration, 5615 ip_address: ip, 5616 session_id: NoSpyStore.sessionId 5617 }); 5618 5619 if (navigator.sendBeacon) { 5620 navigator.sendBeacon(`${noSpyBaseUrl}/track-session`, payload); 5621 } else { 5622 fetch(`${noSpyBaseUrl}/track-session`, { 5623 method: 'POST', 5624 body: payload, 5625 headers: { 5626 'Content-Type': 'application/json' 5627 } 5628 }).then(); 5629 } 5630 } 5631 }; 5632 5633 class GeoService { 5634 constructor() { 5635 this.cacheKey = 'no-spy-geo-location'; 5636 this.reachedKey = 'no-spy-geo-reached'; 5637 } 5638 5639 loadFromCache() { 5640 const cached = localStorage.getItem(this.cacheKey); 5641 if (!cached) return null; 5642 5643 const { expireTime, value } = JSON.parse(cached); 5644 if (Date.now() > expireTime) return null; 5645 5646 return value; 5647 } 5648 5649 saveToCache(data, reached) { 5650 localStorage.setItem(this.cacheKey, JSON.stringify({ 5651 expireTime: Date.now() + 10800 * 1000, // 3 hours 5652 value: data 5653 })); 5654 localStorage.setItem(this.reachedKey, reached); 5655 NoSpyStore.geolocation = data; 5656 NoSpyStore.ip = data.ip; 5657 NoSpyStore.reached = reached; 5658 } 5659 5660 fetch() { 5661 const cached = this.loadFromCache(); 5662 if (cached) { 5663 NoSpyStore.geolocation = cached; 5664 NoSpyStore.ip = cached.ip; 5665 return cached; 5666 } 5667 5668 // const res = await fetch(`${noSpyBaseUrl}/geolocation`, { 5669 // method: "POST", 5670 // headers: { "Content-Type": "application/json" }, 5671 // body: JSON.stringify({ ip: this.requestIp, shop }), 5672 // }); 5673 5674 // const json = await res.json(); 5675 // if (json.status === 201) { 5676 // this.saveToCache(json.data, json.reached); 5677 // NoSpyStore.geolocation = json.data; 5678 // NoSpyStore.ip = json.data.ip; 5679 // NoSpyStore.reached = json.reached; 5680 // return this.loadFromCache(); 5681 // } 5682 return null; 5683 } 5684 }; 5685 5686 const IpUtils = { 5687 isIPv4(ip) { 5688 return /^(\d{1,3}\.){3}\d{1,3}$/.test(ip) && 5689 ip.split('.').every(n => parseInt(n) >= 0 && parseInt(n) <= 255); 5690 }, 5691 5692 isIPv6(ip) { 5693 return /^[0-9a-fA-F:]+$/.test(ip) && ip.includes(':'); 5694 }, 5695 5696 detectVersion(ip) { 5697 if (this.isIPv4(ip)) return 'ipv4'; 5698 if (this.isIPv6(ip)) return 'ipv6';
5699 return 'invalid'; 5700 }, 5701 5702 ipv4ToLong(ip) { 5703 const parts = ip.split('.').map(Number); 5704 return ((parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3]) >>> 0; 5705 }, 5706 5707 ipv6ToBigInt(ip) { 5708 // Expand :: shorthand 5709 let expanded = ip; 5710 if (expanded.includes('::')) { 5711 const halves = expanded.split('::'); 5712 const left = halves[0] ? halves[0].split(':') : []; 5713 const right = halves[1] ? halves[1].split(':') : []; 5714 const missing = 8 - left.length - right.length; 5715 const middle = Array(missing).fill('0000'); 5716 expanded = [...left, ...middle, ...right].join(':'); 5717 } 5718 const parts = expanded.split(':'); 5719 let result = BigInt(0); 5720 for (const part of parts) { 5721 result = (result << BigInt(16)) | BigInt(parseInt(part || '0', 16)); 5722 } 5723 return result; 5724 }, 5725 5726 isInCidrRange(ip, cidr) { 5727 if (!cidr.includes('/')) { 5728 return ip.trim() === cidr.trim(); 5729 } 5730 const [rangeIp, maskStr] = cidr.split('/'); 5731 const mask = parseInt(maskStr); 5732 const ipVersion = this.detectVersion(ip); 5733 const rangeVersion = this.detectVersion(rangeIp); 5734 if (ipVersion !== rangeVersion || ipVersion === 'invalid') return false; 5735 5736 if (ipVersion === 'ipv4') { 5737 const ipLong = this.ipv4ToLong(ip); 5738 const rangeLong = this.ipv4ToLong(rangeIp); 5739 const maskLong = mask === 0 ? 0 : (~0 << (32 - mask)) >>> 0; 5740 return (ipLong & maskLong) === (rangeLong & maskLong); 5741 } else { 5742 const ipBig = this.ipv6ToBigInt(ip); 5743 const rangeBig = this.ipv6ToBigInt(rangeIp); 5744 const shift = BigInt(128 - mask); 5745 return (ipBig >> shift) === (rangeBig >> shift); 5746 } 5747 }, 5748 5749 isInRange(ip, startIp, endIp) { 5750 const ipVersion = this.detectVersion(ip); 5751 const startVersion = this.detectVersion(startIp); 5752 const endVersion = this.detectVersion(endIp); 5753 if (ipVersion !== startVersion || ipVersion !== endVersion || ipVersion === 'invalid') return false; 5754 5755 if (ipVersion === 'ipv4') { 5756 const ipLong = this.ipv4ToLong(ip); 5757 return ipLong >= this.ipv4ToLong(startIp) && ipLong <= this.ipv4ToLong(endIp); 5758 } else { 5759 const ipBig = this.ipv6ToBigInt(ip); 5760 return ipBig >= this.ipv6ToBigInt(startIp) && ipBig <= this.ipv6ToBigInt(endIp); 5761 } 5762 } 5763 }; 5764 5765 function applyBlockingPage() { 5766 const bt = noSpySettings?.blocking_template; 5767 const landingEffect = bt?.landing_effect !== false; 5768 const html = bt?.html; 5769 const pageUrl = bt?.page_url; 5770 if (html && landingEffect) { 5771 try { 5772 if (window.stop) window.stop(); 5773 document.head.innerHTML = '<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Access Restricted</title>'; 5774 document.body.innerHTML = html; 5775 } catch(e) { 5776 document.body.innerHTML = html; 5777 } 5778 } else if (pageUrl) { 5779 location.href = pageUrl; 5780 } else { 5781 const fallbackHtml = '<main style="min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px;text-align:center;font-family:Arial,sans-serif;"><div><h1 style="margin:0 0 12px;font-size:32px;">Access Restricted</h1><p style="margin:0;font-size:16px;">This store is not available from your location.</p></div></main>'; 5782 try { 5783 if (window.stop) window.stop(); 5784 document.head.innerHTML = '<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Access Restricted</title>'; 5785 document.body.innerHTML = fallbackHtml; 5786 } catch(e) { 5787 document.body.innerHTML = fallbackHtml; 5788 } 5789 } 5790 } 5791 5792 const RedirectMatcher = { 5793 evaluate(rules, geoData, pageHandle, referrer, ip, internetProvider) { 5794 if (!rules || !Array.isArray(rules) || rules.length === 0) return null; 5795 5796 const countryCode = geoData?.countryCode || ''; 5797 const regionName = geoData?.regionName || ''; 5798 const cityName = geoData?.cityName || ''; 5799 const ispName = internetProvider || geoData?.isp_name || ''; 5800 5801 const isRegionEmpty = !regionName || regionName === 'NULL'; 5802 const isCityEmpty = !cityName || cityName === 'NULL'; 5803 5804 // Empty value rule check 5805 if (isRegionEmpty || isCityEmpty) { 5806 for (const rule of rules) { 5807 if (rule.condition !== 'empty_value') continue; 5808 const payload = rule.payload; 5809 if (!payload || payload.value === 'ALL' || payload.value === countryCode) { 5810 return rule; 5811 } 5812 } 5813 } 5814 5815 let matchedRules = []; 5816 5817 for (const rule of rules) { 5818 const redirectUrl = this._getRedirectUrl(rule); 5819 5820 if (!this._shouldRedirect(rule, ip, countryCode, pageHandle, regionName, cityName, ispName, redirectUrl, referrer)) { 5821 continue; 5822 } 5823 5824 // Whitelist break 5825 if (rule.action === 'whitelist') { 5826 break; 5827 } 5828 5829 matchedRules.push(rule); 5830 } 5831 5832 if (matchedRules.length === 0) return null; 5833 5834 // Prioritize internal/blocking_page redirects 5835 const internal = matchedRules.find(r => r.redirect_type === 'internal' || r.redirect_type === 'blocking_page'); 5836 return internal || matchedRules[0]; 5837 }, 5838 5839 _getRedirectUrl(rule) { 5840 if (rule.redirect_type === 'blocking_page') { 5841 return noSpySettings?.blocking_template?.page_url || null; 5842 } 5843 let url = rule.redirect_url; 5844 if (rule.redirect_type === 'internal') { 5845 for (const prefix of ['/pages', '/collections', '/products']) { 5846 if (url && url.startsWith(prefix)) { 5847 url = url.replace(prefix, ''); 5848 break; 5849 } 5850 } 5851 } 5852 return url; 5853 }, 5854 5855 _shouldRedirect(rule, ip, countryCode, pageHandle, regionName, cityName, ispName, redirectUrl, referrer) { 5856 const condition = rule.condition; 5857 const payload = rule.payload; 5858 if (!payload) return false;
5859 5860 if (condition === 'ip' || condition === 'ip_range') { 5861 return this._matchIP(condition, ip, payload, redirectUrl, pageHandle); 5862 } 5863 if (condition === 'province') { 5864 return this._matchProvince(payload, countryCode, regionName, cityName, redirectUrl, pageHandle); 5865 } 5866 if (condition === 'country') { 5867 return this._matchCountry(payload, countryCode, redirectUrl, pageHandle); 5868 } 5869 if (condition === 'referrer_url') { 5870 return this._matchReferrer(payload, countryCode, redirectUrl, pageHandle, referrer); 5871 } 5872 if (condition === 'specific_pages' || condition === 'specific_collections') { 5873 return this._matchUrlPath(condition, payload, countryCode, redirectUrl, pageHandle); 5874 } 5875 if (condition === 'internet_provider') { 5876 return this._matchInternetProvider(payload, ispName, redirectUrl, pageHandle); 5877 } 5878 return false; 5879 }, 5880 5881 _norm(handle) { 5882 return handle && !handle.startsWith('/') ? '/' + handle : (handle || '/'); 5883 }, 5884 5885 _matchIP(condition, customerIp, payload, redirectUrl, pageHandle) { 5886 customerIp = (customerIp || '').trim(); 5887 pageHandle = this._norm(pageHandle); 5888 5889 if (condition === 'ip') { 5890 const payloadIp = (payload.ip || '').trim(); 5891 return customerIp === payloadIp && redirectUrl !== pageHandle; 5892 } 5893 5894 if (condition === 'ip_range') { 5895 const ipBlock = payload.ip_block; 5896 if (ipBlock) { 5897 return IpUtils.isInCidrRange(customerIp, ipBlock) && redirectUrl !== pageHandle; 5898 } 5899 const startIp = payload.ip_range_start; 5900 const endIp = payload.ip_range_end; 5901 if (startIp && endIp) { 5902 return IpUtils.isInRange(customerIp, startIp, endIp) && redirectUrl !== pageHandle; 5903 } 5904 } 5905 return false; 5906 }, 5907 5908 _matchCountry(payload, countryCode, redirectUrl, pageHandle) { 5909 const country = payload.country || payload; 5910 if (!country || !country.value) return false; 5911 pageHandle = this._norm(pageHandle); 5912 if (country.value === 'ALL') return redirectUrl !== pageHandle; 5913 return country.value === countryCode && redirectUrl !== pageHandle; 5914 }, 5915 5916 _matchProvince(payload, countryCode, regionName, cityName, redirectUrl, pageHandle) { 5917 const country = payload.country; 5918 if (!country || !country.value) return false; 5919 if (country.value !== countryCode) return false; 5920 5921 pageHandle = this._norm(pageHandle); 5922 if (redirectUrl === pageHandle) return false; 5923 5924 const province = payload.province; 5925 if (!province || !province.label) return false; 5926 if (!regionName) return false; 5927 5928 if (!this._matchLocationName(province.label, regionName)) return false; 5929 5930 const city = payload.city; 5931 if (city && city.label) { 5932 if (!cityName) return false; 5933 return this._matchLocationName(city.label, cityName); 5934 } 5935 return true; 5936 }, 5937 5938 _matchLocationName(storedName, visitorName) { 5939 const stored = (storedName || '').trim(); 5940 const visitor = (visitorName || '').trim(); 5941 if (stored.toLowerCase() === visitor.toLowerCase()) return true; 5942 5943 const suffixes = [' division', ' province', ' state', ' district', ' region', ' prefecture', ' oblast', ' territory']; 5944 let sLow = stored.toLowerCase(); 5945 let vLow = visitor.toLowerCase(); 5946 for (const suffix of suffixes) { 5947 if (sLow.endsWith(suffix)) sLow = sLow.slice(0, -suffix.length); 5948 if (vLow.endsWith(suffix)) vLow = vLow.slice(0, -suffix.length); 5949 } 5950 if (sLow === vLow) return true; 5951 5952 const sFirst = sLow.split(' ')[0]; 5953 const vFirst = vLow.split(' ')[0]; 5954 if (sFirst === vFirst && sFirst.length > 2) return true; 5955 5956 if (sLow.includes(vLow) || vLow.includes(sLow)) return true; 5957 5958 return false;
5959 }, 5960 5961 _matchReferrer(payload, countryCode, redirectUrl, pageHandle, referrer) { 5962 if (!payload.referrer) return false; 5963 const country = payload.country; 5964 if (!country || !country.value) return false; 5965 pageHandle = this._norm(pageHandle); 5966 5967 // Check if referrer matches 5968 if (referrer && referrer.includes(payload.referrer)) { 5969 if (country.value === 'ALL' && redirectUrl !== pageHandle) return true; 5970 return country.value === countryCode && redirectUrl !== pageHandle; 5971 } 5972 return false; 5973 }, 5974 5975 _matchUrlPath(condition, payload, countryCode, redirectUrl, pageHandle) { 5976 const country = payload.country; 5977 let keyValue; 5978 if (condition === 'specific_pages') { 5979 if (!payload.page) return false; 5980 keyValue = payload.page; 5981 } else { 5982 if (!payload.collection) return false; 5983 keyValue = payload.collection; 5984 } 5985 if (!country || !country.value) return false; 5986 5987 const handle = this._norm(keyValue.handle); 5988 pageHandle = this._norm(pageHandle); 5989 5990 if (country.value === 'ALL' && handle === pageHandle && redirectUrl !== pageHandle) return true; 5991 5992 return country.value === countryCode && handle === pageHandle && redirectUrl !== pageHandle; 5993 }, 5994 5995 _matchInternetProvider(payload, internetProvider, redirectUrl, pageHandle) { 5996 const payloadProvider = (payload.internet_provider || '').trim(); 5997 if (!payloadProvider || !internetProvider) return false; 5998 pageHandle = this._norm(pageHandle); 5999 return internetProvider.trim().toLowerCase() === payloadProvider.toLowerCase() && redirectUrl !== pageHandle; 6000 } 6001 }; 6002 6003 class RedirectFeature { 6004 constructor(ip, geoData, botVerification = null) { 6005 if (isLoadedInIframe()) return; 6006 6007 this.ip = ip; 6008 this.geoData = geoData; 6009 this.bot_verification = botVerification; 6010 this.sessionService = new SessionService(); 6011 6012 this.evaluateRedirects().catch(() => {}); 6013 } 6014 6015 async init() { 6016 // kept for compatibility â not used in new flow 6017 this.evaluateRedirects(); 6018 } 6019 6020 async evaluateRedirects() { 6021 const rules = noSpyRedirects ? (noSpyRedirects.rules || []) : []; 6022 isNoSpyLogCreated = true; 6023 if (rules.length === 0) return; 6024 6025 const isBot = this.bot_verification?.is_whitelisted_bot ?? false; 6026 if (isBot) return; 6027 6028 let pageHandle = location.pathname; 6029 if (pageHandle !== '/collections' && pageHandle !== '/collections/all' && pageHandle.startsWith('/collections/')) { 6030 pageHandle = pageHandle.replace('/collections/', ''); 6031 } else if (pageHandle.startsWith('/pages/')) { 6032 pageHandle = pageHandle.replace('/pages/', ''); 6033 } 6034 6035 const referrer = document.referrer || ''; 6036 const ispName = this.geoData?.isp_name || ''; 6037 6038 const matched = RedirectMatcher.evaluate(rules, this.geoData, pageHandle, referrer, this.ip, ispName); 6039 6040 isNoSpyLogCreated = true; 6041 6042 if (matched) { 6043 try { 6044 await fetch(`${noSpyBaseUrl}/block/log`, { 6045 method: 'POST', 6046 headers: { 'Content-Type': 'application/json' }, 6047 body: JSON.stringify({ 6048 shop: Shopify.shop, 6049 session_id: NoSpyStore.sessionId, 6050 status: false, 6051 action_type: 'redirect', 6052 ...this.geoData, 6053 }), 6054 }); 6055 } catch (e) { 6056 // Log failed, redirect anyway 6057 } 6058 this.handleRedirect(matched); 6059 } 6060 } 6061 6062 handleRedirect(rule) { 6063 if (rule.redirect_type === 'blocking_page') { 6064 applyBlockingPage(); 6065 return; 6066 } 6067 if (!rule.redirect_url) return; 6068 6069 if (rule.redirect_type === 'internal') { 6070 location.href = rule.redirect_url; 6071 } else { 6072 const url = toExternalUrl(rule.redirect_url); 6073 location.replace(url); 6074 } 6075 } 6076 }; 6077 6078 class LegacyRedirectFeature { 6079 constructor(ip, bot_verification = null) { 6080 if (isLoadedInIframe()) return; 6081 6082 this.ip = ip; 6083 this.bot_verification = bot_verification; 6084 6085 this.geoService = new GeoService(); 6086 this.sessionService = new SessionService(); 6087 6088 this.init(); 6089 } 6090
6091 async init() { 6092 this.geoService.fetch(); 6093 this.sessionService.init(); 6094 6095 this.fetchRedirect(); 6096 6097 // Run on unload 6098 window.addEventListener("beforeunload", () => { 6099 this.sessionService.sendBeacon(this.ip); 6100 }); 6101 // Run when page visibility changes (e.g., user closes tab or switches) 6102 document.addEventListener("visibilitychange", () => { 6103 console.log('NCG!'); 6104 if (document.visibilityState === 'hidden') { 6105 this.sessionService.sendBeacon(this.ip); 6106 } 6107 }); 6108 } 6109 6110 async fetchRedirect() { 6111 const handle = location.pathname.replace('/pages/', ''); 6112 const isBot = this.bot_verification?.is_whitelisted_bot ?? false; 6113 6114 const res = await fetch(`${noSpyLegacyUrl}/redirect-record`, { 6115 method: "POST", 6116 headers: { "Content-Type": "application/json" }, 6117 body: JSON.stringify({ 6118 shop: Shopify.shop, 6119 session_id: NoSpyStore.sessionId, 6120 handle, 6121 bot_verification: isBot, 6122 reached: NoSpyStore.reached, 6123 ...NoSpyStore.geolocation 6124 }), 6125 }); 6126 6127 const json = await res.json(); 6128 isNoSpyLogCreated = true; 6129 if (json?.data?.is_redirect && !isBot) { 6130 this.handleRedirect(json.data.rule); 6131 } 6132 } 6133 6134 handleRedirect(rule) { 6135 if (rule.redirect_type === 'blocking_page') { 6136 applyBlockingPage(); 6137 return; 6138 } 6139 if (!rule.redirect_url) return; 6140 6141 if (rule.redirect_type === 'internal') { 6142 location.href = rule.redirect_url; 6143 } else { 6144 const url = toExternalUrl(rule.redirect_url); 6145 location.replace(url); 6146 } 6147 } 6148 }; 6149 6150 class BlockSpamBotsFeature { 6151 constructor(options = {}) { 6152 this.threshold = options.threshold || 2.5; 6153 this.botScore = 0; 6154 this.mouseMoved = false; 6155 this.debug = options.debug || false; 6156 this.honeypotFieldName = "custom_field"; 6157 this.honeypotFieldClass = "nsp-custom-field"; 6158 this.botVerification = options.bot_verification; 6159 this.allowedBots = options.allowed_bots || {}; 6160 this.geoService = new GeoService(); 6161 this.sessionService = new SessionService(); 6162 this.run(options.is_block).then(); 6163 } 6164 6165 // Enhanced whitelist checking with multiple verification methods 6166 async isWhitelistedBot() { 6167 let checkFromFront = this.checkUserAgent(); 6168 let isWhitelistedBot = this.botVerification?.is_whitelisted_bot ?? false; 6169 if (checkFromFront || isWhitelistedBot) return true; 6170 return false; 6171 } 6172 6173 checkUserAgent() { 6174 const ua = navigator.userAgent.toLowerCase(); 6175 6176 const botPatterns = { 6177 'google_bot': ['googlebot', 'google-bot'], 6178 'facebook_bot': ['facebookexternalhit', 'facebookcatalog'], 6179 'bing_bot': ['bingbot', 'msnbot'], 6180 'apple_bot': ['applebot', 'apple-bot'], 6181 'ahref_bot': ['ahrefsbot', 'ahrefs-bot'], 6182 'lighthouse_bot': ['lighthouse', 'chrome-lighthouse'], 6183 'linkedin_bot': ['linkedinbot', 'linkedin-bot'], 6184 'pinterest_bot': ['pinterestbot', 'pinterest-bot'], 6185 'semrush_bot': ['semrushbot', 'semrush-bot'], 6186 'claude_bot': ['claudebot'], 6187 'meta_external_agent': ['meta-externalagent'], 6188 'amazon_bot': ['amazonbot'], 6189 'bytespider': ['bytespider'], 6190 'oai_search_bot': ['oai-searchbot'], 6191 'gpt_bot': ['gptbot'], 6192 'chatgpt_user': ['ChatGPT-User', 'openai.com/bot'], 6193 'perplexitybot': ['PerplexityBot'] 6194 }; 6195 6196 for (const [botName, isAllowed] of Object.entries(this.allowedBots)) { 6197 if (!isAllowed) continue; 6198 6199 const patterns = botPatterns[botName]; 6200 if (patterns) { 6201 for (const pattern of patterns) { 6202 if (ua.includes(pattern.toLowerCase())) { 6203 this.detectedBotType = botName; 6204 return true; 6205 } 6206 } 6207 } 6208 } 6209 6210 return false;
6211 } 6212 6213 log(...args) { 6214 if (this.debug) console.log(...args); 6215 } 6216 6217 isHeadless() { 6218 const headless = ( 6219 navigator.webdriver || 6220 !navigator.plugins.length || 6221 !navigator.languages || 6222 /HeadlessChrome/.test(navigator.userAgent) || 6223 /puppeteer/.test(navigator.userAgent) 6224 ); 6225 if (headless) this.botScore += 1; 6226 return headless; 6227 } 6228 6229 detectMouseMovement() { 6230 const handler = () => (this.mouseMoved = true); 6231 window.addEventListener("mousemove", handler); 6232 setTimeout(() => { 6233 if (!this.mouseMoved) { 6234 this.botScore += 1; 6235 this.log("Mouse movement: â"); 6236 } else { 6237 this.log("Mouse movement: â "); 6238 } 6239 window.removeEventListener("mousemove", handler); 6240 }, 3000); 6241 } 6242 6243 getCanvasFingerprint() { 6244 try { 6245 const canvas = document.createElement("canvas"); 6246 const ctx = canvas.getContext("2d"); 6247 ctx.textBaseline = "top"; 6248 ctx.font = "14px Arial"; 6249 ctx.fillStyle = "#f60"; 6250 ctx.fillRect(125, 1, 62, 20); 6251 ctx.fillStyle = "#069"; 6252 ctx.fillText("canvas-fingerprint", 2, 15); 6253 const fp = canvas.toDataURL(); 6254 this.log("Canvas fingerprint:", fp.slice(0, 30) + "..."); 6255 return fp; 6256 } catch { 6257 this.botScore += 0.5; 6258 return "blocked"; 6259 } 6260 } 6261 6262 async getAudioFingerprint() { 6263 try { 6264 const ctx = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, 44100, 44100); 6265 const osc = ctx.createOscillator(); 6266 const comp = ctx.createDynamicsCompressor(); 6267 osc.type = "triangle"; 6268 osc.frequency.value = 10000; 6269 osc.connect(comp); 6270 comp.connect(ctx.destination); 6271 osc.start(0); 6272 const buffer = await ctx.startRendering(); 6273 let hash = 0; 6274 for (let i = 0; i < buffer.length; i++) { 6275 hash += Math.abs(buffer.getChannelData(0)[i]); 6276 } 6277 this.log("Audio fingerprint hash:", hash.toFixed(2)); 6278 return hash.toFixed(2); 6279 } catch { 6280 this.botScore += 0.5; 6281 return "blocked"; 6282 } 6283 } 6284 6285 getWebGLFingerprint() { 6286 try { 6287 const canvas = document.createElement("canvas"); 6288 const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); 6289 const debugInfo = gl.getExtension("WEBGL_debug_renderer_info"); 6290 const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL); 6291 const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL); 6292 this.log("WebGL vendor/renderer:", vendor, renderer); 6293 return `${vendor}~${renderer}`; 6294 } catch { 6295 this.botScore += 0.5; 6296 return "blocked"; 6297 } 6298 } 6299 6300 detectTimingDrift() { 6301 const start = performance.now(); 6302 for (let i = 0; i < 1000000; i++) { 6303 Math.sqrt(i); 6304 } 6305 const duration = performance.now() - start; 6306 if (duration < 10) this.botScore += 0.5; 6307 this.log("Timing drift:", duration.toFixed(2)); 6308 return duration.toFixed(2); 6309 } 6310 6311 injectHoneypotIntoForms() { 6312 const style = document.createElement("style"); 6313 style.textContent = `.${this.honeypotFieldClass} { display: none !important; }`; 6314 document.head.appendChild(style); 6315 6316 document.querySelectorAll("form").forEach((form) => { 6317 // Check if already injected 6318 if (form.querySelector(`input[name="${this.honeypotFieldName}"]`)) return; 6319 6320 const input = document.createElement("input"); 6321 input.type = "text"; 6322 input.name = this.honeypotFieldName; 6323 input.className = this.honeypotFieldClass; 6324 input.tabIndex = -1; 6325 form.appendChild(input); 6326 6327 form.addEventListener("submit", (e) => { 6328 const honeypotValue = input.value; 6329 if (honeypotValue.trim() !== "") { 6330 e.preventDefault(); 6331 this.botScore += 2; 6332 this.log("â ï¸ Honeypot triggered! Value:", honeypotValue); 6333 this.blockBotActions().then(); 6334 } 6335 }); 6336 }); 6337 } 6338 6339 async blockBotActions(is_block = true) { 6340 this.log("ð¨ Bot Detected - Blocking interaction. Score:", this.botScore); 6341 alert("â ï¸ Suspicious activity detected. Submission blocked."); 6342 document.body.innerHTML = "<h1>Access Denied</h1>"; 6343 let actionType = is_block ? "block" : "threat"; 6344 createHit({ 6345 type: "spam_bot", 6346 name: "Spam Bot", 6347 pathname: window.location.pathname, 6348 action_type: actionType 6349 }); 6350 if (actionType === 'block' && isNoSpyLogCreated) { 6351 let geoData = NoSpyStore.geolocation; 6352 if (geoData === null) { 6353 geoData = this.geoService.fetch(); 6354 } 6355 let sessionId = NoSpyStore.sessionId; 6356 if (sessionId === null) { 6357 this.sessionService.init(); 6358 sessionId = this.sessionService.getSessionId(); 6359 } 6360 createBlockLog({ 6361 shop: Shopify.shop, 6362 session_id: sessionId, 6363 status: false, 6364 action_type: 'blocked', 6365 ...geoData, 6366 }); 6367 } 6368 throw new Error("Bot access denied"); 6369 } 6370 6371 async runDetection(is_block = true) { 6372 // let isHeadless = this.isHeadless(); 6373 // if (isHeadless) { 6374 // let actionType = is_block ? "block" : "threat"; 6375 // createHit({ 6376 // type: "spam_bot", 6377 // name: "Spam Bot", 6378 // pathname: window.location.pathname, 6379 // action_type: actionType 6380 // }); 6381 // } 6382 this.getCanvasFingerprint(); 6383 await this.getAudioFingerprint(); 6384 this.getWebGLFingerprint(); 6385 this.detectTimingDrift(); 6386 6387 if (this.botScore >= this.threshold) { 6388 this.blockBotActions(is_block).then(); 6389 } else { 6390 this.log("â Human verified. Score:", this.botScore); 6391 } 6392 return false;
6393 } 6394 6395 async run(is_block) { 6396 // Check if current user agent is whitelisted BEFORE running detection 6397 if (document.readyState === "complete") { 6398 if (await this.isWhitelistedBot()) { 6399 this.log("â Whitelisted bot - skipping detection"); 6400 return false; 6401 } 6402 this.detectMouseMovement(); 6403 this.injectHoneypotIntoForms(); 6404 this.runDetection(is_block).then(); 6405 } else { 6406 window.addEventListener("load", async () => { 6407 if (await this.isWhitelistedBot()) { 6408 this.log("â Whitelisted bot - skipping detection"); 6409 return false; 6410 } 6411 this.detectMouseMovement(); 6412 this.injectHoneypotIntoForms(); 6413 this.runDetection(is_block).then(); 6414 }); 6415 } 6416 } 6417 }; 6418 6419 class ProxyVpnTorBlockFeature { 6420 constructor(proxy_vpn_block = false, tor_block = false, proxy_vpn_redirect_url = null, blockingTemplateOptions = {}) { 6421 this.proxy_vpn_block = proxy_vpn_block; 6422 this.tor_block = tor_block; 6423 this.proxy_vpn_redirect_url = proxy_vpn_redirect_url; 6424 this.proxy_vpn_show_blocking_page = !!blockingTemplateOptions.proxy_vpn_show_blocking_page; 6425 this.tor_show_blocking_page = !!blockingTemplateOptions.tor_show_blocking_page; 6426 this.blocking_template_landing_effect = blockingTemplateOptions.blocking_template_landing_effect !== false; 6427 this.blocking_template_html = blockingTemplateOptions.blocking_template_html || null; 6428 this.blocking_template_page_url = blockingTemplateOptions.blocking_template_page_url || null; 6429 this.geoService = new GeoService(); 6430 this.sessionService = new SessionService(); 6431 if (this.proxy_vpn_block || this.tor_block) { 6432 this.run(); 6433 } 6434 } 6435 6436 // Returns the action to take, or null when the merchant configured no 6437 // destination â the caller must not record a block it cannot enforce. 6438 resolveBlockingAction(reasonShowBlockingPage) { 6439 if (reasonShowBlockingPage && this.blocking_template_html && this.blocking_template_landing_effect) { 6440 return {type: 'template'}; 6441 } 6442 if (reasonShowBlockingPage && !this.blocking_template_landing_effect && this.blocking_template_page_url) { 6443 return {type: 'page', url: this.blocking_template_page_url}; 6444 } 6445 if (this.proxy_vpn_redirect_url) { 6446 return {type: 'redirect', url: toExternalUrl(this.proxy_vpn_redirect_url)}; 6447 } 6448 return null; 6449 } 6450 6451 applyBlockingResponse(action) { 6452 if (!action) return; 6453 if (action.type === 'template') { 6454 try { 6455 if (window.stop) window.stop(); 6456 document.head.innerHTML = '<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Access Restricted</title>'; 6457 document.body.innerHTML = this.blocking_template_html; 6458 } catch (e) { 6459 document.body.innerHTML = this.blocking_template_html; 6460 } 6461 return; 6462 } 6463 window.location.href = action.url; 6464 } 6465 6466 isUsingProxy(geoLocation) { 6467 if (geoLocation) { 6468 return geoLocation.is_proxy ?? false; 6469 } 6470 return false; 6471 } 6472 6473 isUsingVPN(geoLocation) { 6474 if (geoLocation) { 6475 return geoLocation.is_vpn ?? false; 6476 } 6477 return false; 6478 } 6479 6480 isUsingTor(geoLocation) { 6481 if (geoLocation) { 6482 return geoLocation.is_tor ?? false; 6483 } 6484 return false; 6485 } 6486 6487 async storeBlockLog(geoData) { 6488 let sessionId = NoSpyStore.sessionId; 6489 if (sessionId === null) { 6490 this.sessionService.init(); 6491 sessionId = this.sessionService.getSessionId(); 6492 } 6493 createBlockLog({ 6494 shop: Shopify.shop, 6495 session_id: sessionId, 6496 status: false, 6497 action_type: 'blocked', 6498 ...geoData, 6499 }); 6500 return true; 6501 } 6502 6503 async getGeoLocation() { 6504 let geoData = NoSpyStore.geolocation; 6505 if (geoData === null) { 6506 geoData = await this.geoService.fetch(); 6507 } 6508 return geoData; 6509 } 6510 6511 run() { 6512 // Check until get the geo location from local storage use setInterval 6513 let interval = setInterval(async () => { 6514 if (isNoSpyLogCreated) { 6515 this.getGeoLocation().then((geoLocation) => { 6516 const proxyHit = (this.isUsingProxy(geoLocation) || this.isUsingVPN(geoLocation)) && this.proxy_vpn_block; 6517 const torHit = this.isUsingTor(geoLocation) && this.tor_block; 6518 if (proxyHit || torHit) { 6519 clearInterval(interval); 6520 const showBlockingPage = (proxyHit && this.proxy_vpn_show_blocking_page) || (torHit && this.tor_show_blocking_page); 6521 const action = this.resolveBlockingAction(showBlockingPage); 6522 if (!action) return; 6523 this.storeBlockLog(geoLocation).then(() => { 6524 this.applyBlockingResponse(action); 6525 }); 6526 } else { 6527 clearInterval(interval); 6528 } 6529 }); 6530 } 6531 }, 500); // 0.5 second interval 6532 } 6533 }; 6534 6535 const generateRandomString = (length) => { 6536 let result = ""; 6537 const characters = 6538 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 6539 const charactersLength = characters.length; 6540 for (let i = 0; i < length; i++) { 6541 result += characters.charAt(Math.floor(Math.random() * charactersLength)); 6542 } 6543 return result; 6544 }; 6545 6546 const handleOtherBug = () => { 6547 let isLastOperation = false;
6548 let intervalCount = 0; 6549 let interval = setInterval(function () { 6550 let getAllBodyChilds = document.body.children; 6551 Array.from(getAllBodyChilds).forEach((item) => { 6552 let smileUIFrame = item.querySelector("#smile-ui-container"); 6553 if (smileUIFrame && smileUIFrame.style.zIndex == "2147483647") { 6554 smileUIFrame.style.zIndex = "2147483646"; 6555 isLastOperation = true; 6556 } 6557 6558 let chat1 = item.querySelector("[class*='psmtc_']"); 6559 if (chat1 && chat1.style.zIndex == "2147483647") { 6560 chat1.style.zIndex = "2147483646"; 6561 } 6562 let chat2 = item.querySelector("[class*='psmw_']"); 6563 if (chat2 && chat2.style.zIndex == "2147483647") { 6564 chat2.style.zIndex = "2147483646"; 6565 } 6566 6567 let trustBadgeContainer = document.querySelector('*[id^="trustbadge-container"]'); 6568 if (trustBadgeContainer && trustBadgeContainer.style.zIndex == "2147483647") { 6569 trustBadgeContainer.style.zIndex = "2147483646"; 6570 } 6571 6572 if ( 6573 item.hasAttribute("id") && 6574 item.getAttribute("id") === "smile-ui-lite-container" 6575 ) { 6576 let getFrame = item.querySelector( 6577 "#smile-ui-lite-launcher-frame-container" 6578 ); 6579 if (getFrame) { 6580 getFrame.style.width = "146px"; 6581 } 6582 if (item.style.zIndex == "2147483647") { 6583 item.style.zIndex = "2147483646"; 6584 } 6585 } 6586 6587 if ( 6588 !item.hasAttribute("id") && 6589 item.nodeName === "DIV" && 6590 item.style.zIndex 6591 ) { 6592 if (item.style.zIndex == "2147483647") { 6593 item.style.zIndex = "2147483646"; 6594 console.log("zIndex found!"); 6595 } 6596 } 6597 6598 if ( 6599 item.hasAttribute("id") && 6600 item.getAttribute("id") === "reve-chat-container-div" 6601 ) { 6602 if (item.style.zIndex == "2147483647") { 6603 item.style.zIndex = "2147483646"; 6604 } 6605 } 6606 }); 6607 if (intervalCount >= 30 && isLastOperation) { 6608 clearInterval(interval); 6609 } 6610 intervalCount++; 6611 }, 1000); 6612 }; 6613 6614 const handleCssData = () => { 6615 let intervalCount = 0; 6616 let cssId = generateRandomString(15); 6617 const cssExceptions = ':not(#pandectes-banner):not(.pd-cookie-banner-window)'; 6618 let css = 6619 'div[style*="2147483647"]' + cssExceptions + ' {display: none !important;}.extension-container {display: none !important;}#shopify-raise-container {display: none !important;}.ppspy-container {display: none !important;}#shopify_app_wrapper {display: none !important;}html.shinecommerce-modal-open #shinecommerce-extension-div {display: none !important;}html.shinecommerce-modal-open, html.shinecommerce-modal-open body {overflow: auto !important;} .ixspy-tools {display: none !important;} #simplytrends-main-extension-root {display: none !important;} #my-extension-root {display: none !important;} plasmo-csui {display: none !important;} #shop-analysis-shadow-host {display: none !important;} #kins-kins-popup {display: none !important;} #ah-app {display: none !important;}'; 6620 let head = document.head || document.getElementsByTagName("head")[0]; 6621 let styles = document.createElement("style"); 6622 head.appendChild(styles); 6623 styles.type = "text/css"; 6624 styles.id = cssId; 6625 if (styles.styleSheet) { 6626 styles.styleSheet.cssText = css; 6627 } else { 6628 styles.appendChild(document.createTextNode(css)); 6629 } 6630 const myCssInterval = setInterval(myCssTimer, 10); 6631 function myCssTimer() { 6632 let getStlye = document.getElementById(cssId); 6633 if (getStlye === null) { 6634 head.appendChild(styles); 6635 } 6636 if (intervalCount === 1000) { 6637 clearInterval(myCssInterval); 6638 } 6639 intervalCount += 1; 6640 } 6641 }; 6642 6643 const handleTextSelection = (id, is_text, is_image) => { 6644 var css = document.createElement("style"); 6645 var head = document.head; 6646 head.appendChild(css); 6647 6648 css.type = 'text/css'; 6649 css.id = id; 6650 6651 css.innerText = ''; 6652 6653 if (is_text) { 6654 css.innerText += ` 6655 * { 6656 -webkit-user-select: none !important; 6657 -moz-user-select: none !important;
6658 -ms-user-select: none !important; 6659 user-select: none !important; 6660 } 6661 body { 6662 -webkit-user-select: none !important; 6663 -webkit-touch-callout: none !important; 6664 -moz-user-select: none !important; 6665 -ms-user-select: none !important; 6666 user-select: none !important; 6667 } 6668 .no_spy_allowed_element, .no_spy_allowed_element * { 6669 -webkit-user-select: text !important; 6670 -webkit-touch-callout: text !important; 6671 -moz-user-select: text !important; 6672 -ms-user-select: text !important; 6673 user-select: text !important; 6674 } 6675 .no_spy_allowed_element::selection, .no_spy_allowed_element *::selection { 6676 background: #CECECD; 6677 }`; 6678 } 6679 if (is_image) { 6680 css.innerText += ` 6681 img { 6682 -webkit-user-drag: none !important; 6683 -khtml-user-drag: none !important; 6684 -moz-user-drag: none !important; 6685 -o-user-drag: none !important; 6686 user-drag: none !important; 6687 pointer-events: none !important; 6688 }`; 6689 } 6690 6691 var elements = document.querySelectorAll("*"); 6692 6693 for (var i = 0; i < elements.length; i++) { 6694 if (elements[i].classList.contains('no_spy_allowed_element')) { 6695 continue; 6696 } 6697 if (elements[i].style.userSelect == 'auto') { 6698 elements[i].style.userSelect = 'none'; 6699 } 6700 if (elements[i].style.userSelect == 'text') { 6701 elements[i].style.userSelect = 'none'; 6702 } 6703 } 6704 } 6705 6706 const handleRightClick = () => { 6707 function init() { 6708 window.addEventListener('contextmenu', function handleEvent(event) { 6709 event.stopPropagation(); 6710 event.stopImmediatePropagation(); 6711 var handler = new EventHandler(event); 6712 window.removeEventListener(event.type, handleEvent, true); 6713 var EventsCallBback = new EventsCall(function() {}); 6714 handler.fire(); 6715 window.addEventListener(event.type, handleEvent, true); 6716 if (!handler.isCanceled && (!EventsCallBback.isCalled)) { 6717 event.preventDefault(); 6718 } 6719 }, true); 6720 } 6721 setInterval(init, 1000); 6722 6723 function EventsCall(callback) { 6724 this.events = ['DOMAttrModified', 'DOMNodeInserted', 'DOMNodeRemoved', 'DOMCharacterDataModified', 'DOMSubtreeModified']; 6725 this.bind(); 6726 } 6727 6728 EventsCall.prototype.bind = function() { 6729 this.events.forEach(function(event) { 6730 document.addEventListener(event, this, true); 6731 }.bind(this)); 6732 }; 6733 6734 EventsCall.prototype.handleEvent = function() { 6735 this.isCalled = false; 6736 }; 6737 6738 EventsCall.prototype.unbind = function() { 6739 this.events.forEach(function(event) {}.bind(this)); 6740 }; 6741 6742 function EventHandler(event) { 6743 this.event = event; 6744 this.contextmenuEvent = this.createEvent(this.event.type); 6745 } 6746 6747 EventHandler.prototype.createEvent = function(type) { 6748 var target = this.event.target; 6749 var event = target.ownerDocument.createEvent('MouseEvents'); 6750 event.initMouseEvent( 6751 type, this.event.bubbles, this.event.cancelable, 6752 target.ownerDocument.defaultView, this.event.detail, 6753 this.event.screenX, this.event.screenY, this.event.clientX, this.event.clientY, 6754 this.event.ctrlKey, this.event.altKey, this.event.shiftKey, this.event.metaKey, 6755 this.event.button, this.event.relatedTarget 6756 ); 6757 return event; 6758 }; 6759 6760 EventHandler.prototype.fire = function() { 6761 var target = this.event.target; 6762 var contextmenuHandler = function(event) { 6763 event.preventDefault(); 6764 }.bind(this); 6765 target.dispatchEvent(this.contextmenuEvent); 6766 this.contextmenuEvent.defaultPrevented; 6767 this.isCanceled = false;
6768 }; 6769 }; 6770 6771 const createAndPreviewMode = (expiresAt) => { 6772 // Create style 6773 const style = document.createElement('style'); 6774 style.textContent = ` 6775 .preview-bar { 6776 position: fixed; 6777 bottom: 0; 6778 left: 0; 6779 width: 100%; 6780 background-color: #1e293b; 6781 color: white; 6782 display: flex; 6783 justify-content: space-between; 6784 align-items: center; 6785 padding: 10px 20px; 6786 font-family: sans-serif; 6787 font-size: 14px; 6788 z-index: 2147483647; 6789 box-shadow: 0 2px 4px rgba(0,0,0,0.2); 6790 min-height: 55px; 6791 } 6792 .session-time { 6793 font-weight: bold; 6794 } 6795 iframe#PBarNextFrame { 6796 display: none !important; 6797 } 6798 `; 6799 document.head.appendChild(style); 6800 6801 // Calculate remaining time from expiresAt 6802 const now = new Date().getTime(); 6803 const remainingTime = expiresAt - now; 6804 6805 const days = Math.floor(remainingTime / (1000 * 60 * 60 * 24)); 6806 const hours = Math.floor((remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); 6807 const minutes = Math.floor((remainingTime % (1000 * 60 * 60)) / (1000 * 60)); 6808 const seconds = Math.floor((remainingTime % (1000 * 60)) / 1000); 6809 6810 const formatted = `${String(days)}d ${String(hours).padStart(2, '0')}h ${String(minutes).padStart(2, '0')}m ${String(seconds).padStart(2, '0')}s`; 6811 6812 // Create preview bar HTML 6813 const bar = document.createElement('div'); 6814 bar.className = 'preview-bar'; 6815 bar.innerHTML = ` 6816 <div class="session-time" id="sessionTimer">â³ ${formatted} left</div> 6817 <div>ð NoSpy Unlocked Preview</div> 6818 `; 6819 document.body.prepend(bar); 6820 6821 // Timer logic 6822 let remainingTotalSeconds = Math.floor(remainingTime / 1000); 6823 6824 function formatTime(seconds) { 6825 const d = Math.floor(seconds / 86400); // 86400 = 24*60*60 6826 const h = Math.floor((seconds % 86400) / 3600).toString().padStart(2, '0'); 6827 const m = Math.floor((seconds % 3600) / 60).toString().padStart(2, '0'); 6828 const s = (seconds % 60).toString().padStart(2, '0'); 6829 return `${d}
6829d ${h}h ${m}m ${s}s`; 6830 } 6831 6832 function updateTimer() { 6833 if (remainingTotalSeconds > 0) { 6834 remainingTotalSeconds--; 6835 document.getElementById('sessionTimer').textContent = `â³ ${formatTime(remainingTotalSeconds)} left`; 6836 } else { 6837 document.getElementById('sessionTimer').textContent = `â³ Session expired`; 6838 // reload the page and remove the preview bar 6839 setTimeout(() => document.querySelector('.preview-bar').remove(), 1000); 6840 setTimeout(() => window.location.href = '/', 3000); 6841 clearInterval(timerInterval); 6842 } 6843 } 6844 6845 const timerInterval = setInterval(updateTimer, 1000); 6846 } 6847 6848 const getNoSpyAccessToken = () => { 6849 const now = Date.now(); 6850 // get no spy access token from URL params 6851 const urlParams = new URLSearchParams(window.location.search); 6852 let getNoSpyAccessTokenFromUrl = urlParams.get('nospy_access_token'); 6853 6854 let noSpyAccessTokenFromLocalStorage = JSON.parse(localStorage.getItem('nospy_access_token')); 6855 6856 if (getNoSpyAccessTokenFromUrl != null) { 6857 return getNoSpyAccessTokenFromUrl; 6858 } else if (noSpyAccessTokenFromLocalStorage !== null) { 6859 // check if no spy access token is expired 6860 let expiresAtLocal = parseInt(noSpyAccessTokenFromLocalStorage.expiresAt, 10); // e.g., 1718801120000 6861 if (now > expiresAtLocal) { 6862 localStorage.removeItem('nospy_access_token'); 6863 return null; 6864 } 6865 return noSpyAccessTokenFromLocalStorage.token; 6866 } 6867 return null; 6868 }; 6869 6870 const storeNoSpyAccessToken = (token, expireDays = 1) => { 6871 const now = Date.now(); 6872 const hours = expireDays * 24; 6873 const expiresAt = now + hours * 60 * 60 * 1000; 6874 let noSpyAccessTokenFromLocalStorage = JSON.parse(localStorage.getItem('nospy_access_token')); 6875 if (noSpyAccessTokenFromLocalStorage === null) { 6876 localStorage.setItem('nospy_access_token', JSON.stringify({ 6877 token: token, 6878 expiresAt: expiresAt 6879 })); 6880 } else { 6881 return noSpyAccessTokenFromLocalStorage.expiresAt; 6882 } 6883 return expiresAt; 6884 } 6885 6886 const getPrivacyDataLegacy = async () => { 6887 if (noSpyInternalPages.length > 0) { 6888 const currentPath = window.location.pathname; 6889 const normalizedPath = currentPath.startsWith('/') ? currentPath : '/' + currentPath; 6890 const isInternalTarget = noSpyInternalPages.some(p => { 6891 const np = p.startsWith('/') ? p : '/' + p; 6892 return np === normalizedPath; 6893 }); 6894 if (isInternalTarget) return; 6895 } 6896 6897 let activation_status = false; 6898 let is_exclude = false; 6899 let redirect = 1; 6900 let copy_paste = 1; 6901 let image_drag = 1; 6902 let right_click = 1; 6903 let keys_shortcuts = 1; 6904 let text_selection = 1; 6905 let web_page_print = 1; 6906 let spy_extensions = 1; 6907 let spy_extensions_block_mode = 1; 6908 let spy_extensions_redirect_url = null; 6909 let inspect_elements = 1; 6910 let inspect_elements_message = 1; 6911 let block_spam_bots = 1; 6912 let proxy_vpn_block = 1; 6913 let proxy_vpn_redirect_url = null; 6914 let tor_block = 1; 6915 6916 let no_spy_access_token = getNoSpyAccessToken(); 6917 let geoLocation = new GeoService(); 6918 let geoLocationData = geoLocation.fetch(); 6919 6920 let url = `${noSpyLegacyUrl}/getSettings?shop=${Shopify.shop}${no_spy_access_token != null ? `&access_token=${no_spy_access_token}` : ''}`; 6921 if (geoLocationData) { 6922 url += `&asn=${geoLocationData.asn}`; 6923 } else { 6924 url += `&asn=0`; 6925 } 6926 let data = await fetch(url); 6927 let response = await data.json(); 6928 if (response.status) { 6929 if (response.preview === true) { 6930 let expiresAt = 0; 6931 if (no_spy_access_token !== null && response.data.session_duration) { 6932 expiresAt = storeNoSpyAccessToken(no_spy_access_token, response.data.session_duration); 6933 } 6934 createAndPreviewMode(expiresAt); 6935 return; 6936 } 6937 if (response.data[0].activation_status == 1) { 6938 activation_status = true; 6939 redirect = response.data[1].redirect; 6940 copy_paste = response.data[1].copy_paste; 6941 image_drag = response.data[1].image_drag; 6942 right_click = response.data[1].right_click; 6943 keys_shortcuts = response.data[1].keys_shortcuts; 6944 text_selection = response.data[1].text_selection; 6945 web_page_print = response.data[1].web_page_print; 6946 spy_extensions = response.data[1].spy_extensions; 6947 spy_extensions_block_mode = response.data[1].spy_extensions_block_mode; 6948 spy_extensions_redirect_url = response.data[1].spy_extensions_redirect_url; 6949 inspect_elements = response.data[1].inspect_elements; 6950 inspect_elements_message = response.data[1].inspect_elements_message; 6951 block_spam_bots = response.data[1].block_spam_bots; 6952 proxy_vpn_block = response.data[1].proxy_vpn_block; 6953 proxy_vpn_redirect_url = response.data[1].proxy_vpn_redirect_url; 6954 tor_block = response.data[1].tor_block; 6955 } 6956 // Check for exclude list 6957 if (response.data[2]) { 6958 const { collections, pages } = response.data[2]; 6959 let pathname = window.location.pathname.split('/'); 6960 if (pathname.length > 2) { 6961 if (pages) { 6962 if (pages.includes(pathname[2])) { 6963 is_exclude = true; 6964 } else if (pathname[1] === 'products' && pages.includes('/products/{handle}')) { 6965 is_exclude = true; 6966 } else if (pathname[1] === 'account') { 6967 if (pages.includes(window.location.pathname)) { 6968 is_exclude = true; 6969 } else if (pathname[2] === 'orders' && pages.includes('/account/orders/{handle}')) { 6970 is_exclude = true; 6971 } else if (pathname[2] === 'login' && pages.includes('/account/login')) { 6972 is_exclude = true; 6973 } else if (pathname[2] === 'register' && pages.includes('/account/register')) { 6974 is_exclude = true; 6975 } 6976 } else if (pages.includes(window.location.pathname)) { 6977 is_exclude = true; 6978 } 6979 } 6980 if (collections) { 6981 if (pathname[1] === 'collections' && collections.includes(pathname[2])) { 6982 is_exclude = true; 6983 } 6984 } 6985 } else { 6986 // check '/' is existed inside pages array or not 6987 if (pages && pages.includes(window.location.pathname)) { 6988 is_exclude = true; 6989 } 6990 } 6991 } 6992 } 6993 6994 // If geo location data is not null, then set the geo location data to the NoSpyStore 6995 if (response.geo_location && response.geo_location !== null) { 6996 geoLocation.saveToCache(response.geo_location, response.reached); 6997 } 6998 // If current user agent is not whitelisted and activation status is true, then run the detection 6999 if (!isWhitelistBots && activation_status) { 7000 const bot_verification = response.bot_verification; 7001 if (bot_verification && bot_verification.is_whitelisted_bot == true) { 7002 return false;
7003 } 7004 7005 if (redirect == 0) { 7006 new LegacyRedirectFeature(response.ip, bot_verification); 7007 } 7008 7009 if (proxy_vpn_block == 0 || tor_block == 0) { 7010 new ProxyVpnTorBlockFeature(proxy_vpn_block == 0, tor_block == 0, proxy_vpn_redirect_url, { 7011 proxy_vpn_show_blocking_page: !!response.data[1].proxy_vpn_show_blocking_page, 7012 tor_show_blocking_page: !!response.data[1].tor_show_blocking_page, 7013 blocking_template_landing_effect: response.blocking_template?.landing_effect !== false, 7014 blocking_template_html: response.blocking_template?.html || null, 7015 blocking_template_page_url: response.blocking_template?.page_url || null, 7016 }); 7017 } 7018 7019 if (block_spam_bots == 0) { 7020 new BlockSpamBotsFeature({ 7021 ip: response.ip, 7022 threshold: 2.5, 7023 debug: false, 7024 is_block: true, 7025 bot_verification: {...bot_verification, allowed_bots: response.allowed_bots}, 7026 allowed_bots: response.allowed_bots || {}, 7027 }); 7028 } 7029 7030 if (is_exclude) { 7031 return false; 7032 } 7033 7034 applyProtections({copy_paste, image_drag, right_click, keys_shortcuts, text_selection, web_page_print, spy_extensions, spy_extensions_block_mode, spy_extensions_redirect_url, inspect_elements, inspect_elements_message, inspect_elements_show_blocking_page: !!response.data[1].inspect_elements_show_blocking_page, blocking_template_html: response.blocking_template?.html || null, blocking_template_landing_effect: response.blocking_template?.landing_effect !== false, blocking_template_page_url: response.blocking_template?.page_url || null}); 7035 } else { 7036 return false; 7037 } 7038 }; 7039 7040 const applyProtections = (opts) => { 7041 const {copy_paste, image_drag, right_click, keys_shortcuts, text_selection, web_page_print, spy_extensions, spy_extensions_block_mode, spy_extensions_redirect_url, inspect_elements, inspect_elements_message, inspect_elements_show_blocking_page, blocking_template_html, blocking_template_landing_effect, blocking_template_page_url} = opts; 7042 7043 let devToolsBlocked = false; 7044 const handleDevToolsDetected = () => { 7045 if (devToolsBlocked) return; 7046 devToolsBlocked = true; 7047 if (inspect_elements_show_blocking_page && blocking_template_html && blocking_template_landing_effect) { 7048 try { 7049 if (window.stop) window.stop(); 7050 document.head.innerHTML = '<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Access Restricted</title>'; 7051 document.body.innerHTML = blocking_template_html; 7052 } catch (e) { 7053 document.body.innerHTML = blocking_template_html; 7054 } 7055 } else if (inspect_elements_show_blocking_page && !blocking_template_landing_effect && blocking_template_page_url) { 7056 window.location.href = blocking_template_page_url; 7057 } 7058 // No blocking page configured: take no action. Never navigate the 7059 // visitor to a destination the merchant did not choose. 7060 }; 7061 7062 const block = (type, bool, event) => { 7063 // createHit({'type': type, 'pathname': window.location.pathname}); 7064 let allowed_events = ['text_selection', 'copy_paste']; 7065 7066 if (allowed_events.includes(type)) { 7067 let target = event.target; 7068 let parent = target.parentNode; 7069 let mother_Parent = parent.parentNode; 7070 let last_mother_Parent = mother_Parent.parentNode; 7071 let allowed_element = "no_spy_allowed_element"; 7072 7073 if (target && target.classList && target.classList.contains(allowed_element)) { 7074 return true; 7075 } 7076 7077 if (parent && parent.classList && parent.classList.contains(allowed_element)) { 7078 return true; 7079 } 7080 7081 if (mother_Parent && mother_Parent.classList && mother_Parent.classList.contains(allowed_element)) { 7082 return true; 7083 } 7084 7085 if (last_mother_Parent && last_mother_Parent.classList && last_mother_Parent.classList.contains(allowed_element)) { 7086 return true; 7087 } 7088 } 7089 const allowed = Boolean(bool); 7090 7091 if (!allowed) { 7092 event.preventDefault(); 7093 event.stopPropagation(); 7094 } 7095 7096 return allowed; 7097 }; 7098 7099 document.onselectstart = function (event) { 7100 return block("text_selection", text_selection, event); 7101 }; 7102 7103 document.onpaste = function (event) { 7104 return block("copy_paste", copy_paste, event); 7105 }; 7106 7107 document.oncopy = function (event) { 7108 return block("copy_paste", copy_paste, event); 7109 }; 7110 7111 document.oncut = function (event) { 7112 return block("copy_paste", copy_paste, event); 7113 }; 7114 7115 document.ondragstart = function (event) { 7116 return block("image_drag", image_drag, event); 7117 }; 7118 7119 document.ondrag = function (event) { 7120 return block("image_drag", image_drag, event); 7121 }; 7122 7123 document.ondrop = function (event) { 7124 return block("image_drag", image_drag, event); 7125 }; 7126 7127 document.oncontextmenu = function (event) { 7128 return block("right_click", right_click, event); 7129 }; 7130 7131 if (web_page_print == 0) { 7132 // Disable Print Command from Keyboard 7133 // let isPOkay = { cmd: false, p: false }; 7134 // let keyPrints = ['Meta', 'Control', 'P', 'p']; 7135 // const undoPCommand = () => { 7136 // isPOkay.cmd = false;
7137 // isPOkay.p = false; 7138 // }; 7139 // document.addEventListener("keydown", (event) => { 7140 // let find = keyPrints.find((k) => k === event.key); 7141 // if (find) { 7142 // if (find === 'Meta' || find === 'Control') { 7143 // isPOkay.cmd = true; 7144 // } 7145 // if (find === 'P' || find === 'p') { 7146 // isPOkay.p = true; 7147 // } 7148 // } else { 7149 // undoPCommand(); 7150 // } 7151 // if (isPOkay.cmd === true && isPOkay.p === true) { 7152 // event.preventDefault(); 7153 // return false; 7154 // } 7155 // }); 7156 // Empty Webpage 7157 let getBodyVar = generateRandomString(32); 7158 window[getBodyVar] = null; 7159 window.addEventListener('beforeprint', function() { 7160 window[getBodyVar] = document.querySelector('body').innerHTML; 7161 document.querySelector('body').innerHTML = "<p><pretecting</p>"; 7162 }); 7163 7164 window.addEventListener('afterprint', function() { 7165 document.querySelector('body').innerHTML = window[getBodyVar]; 7166 window[getBodyVar] = null; 7167 }); 7168 // Print disable for extension 7169 function initDisablePrint() { 7170 let extension_1 = document.querySelector('iframe#pf-core'); 7171 if (extension_1 !== null) { 7172 let pf_div = document.querySelector('#pf-mask'); 7173 if (pf_div) pf_div.remove(); 7174 extension_1.remove(); 7175 let get_body = document.querySelector('body'); 7176 if (get_body) get_body.setAttribute('style', 'overflow: auto !important') 7177 } 7178 } 7179 setInterval(initDisablePrint, 100); 7180 } 7181 7182 if (right_click == 0) { 7183 handleRightClick(); 7184 } 7185 7186 document.onkeydown = function (event) { 7187 if (event.keyCode == 123) { 7188 return block("keys_shortcuts", keys_shortcuts, event); 7189 } 7190 if (event.ctrlKey && event.keyCode == "U".charCodeAt(0)) { 7191 return block("keys_shortcuts", keys_shortcuts, event); 7192 } 7193 7194 if (event.ctrlKey && event.shiftKey && event.keyCode == "I".charCodeAt(0)) { 7195 return block("inspect_elements", inspect_elements, event); 7196 } 7197 if (event.ctrlKey && event.shiftKey && event.keyCode == "J".charCodeAt(0)) { 7198 return block("inspect_elements", inspect_elements, event); 7199 } 7200 7201 if (event.ctrlKey && event.shiftKey && event.keyCode == "C".charCodeAt(0)) { 7202 return block("inspect_elements", inspect_elements, event); 7203 } 7204 }; 7205 7206 let is_image_drag = false; 7207 if (image_drag == 0) { 7208 is_image_drag = true; 7209 } 7210 7211 if (text_selection == 0) { 7212 let textSelectionId = generateRandomString(15); 7213 setInterval(textSelectionTimer, 1000); 7214 function textSelectionTimer() { 7215 let getStlye = document.getElementById(textSelectionId); 7216 if (getStlye !== null) { 7217 getStlye.remove(); 7218 } 7219 textSelectionId = generateRandomString(15); 7220 handleTextSelection(textSelectionId, true, is_image_drag); 7221 } 7222 } 7223 7224 // List of extensions to be blocked 7225 const handleExtensions = (is_block) => { 7226 let list_extensions = [ 7227 {name: "Shopify raise", selector: "#shopify-raise-container", hit: true}, 7228 {name: "Extension", selector: ".extension-container", hit: false}, 7229 {name: "PPSpy", selector: ".ppspy-container", hit: true}, 7230 {name: "Shopify Hunter", selector: "#shopify_app_wrapper", hit: true}, 7231 {name: "Shine Commerce", selector: "#shinecommerce-extension-div", hit: true}, 7232 {name: "Shopify Analyzer", selector: ".ixspy-tools", hit: true}, 7233 {name: "Simply Trends", selector: "#simplytrends-main-extension-root", hit: true}, 7234 {name: "My Extension", selector: "#my-extension-root", hit: false}, 7235 {name: "Minea", selector: "plasmo-csui", hit: true}, 7236 {name: "Koala", selector: "#kins-kins-popup", hit: true}, 7237 {name: "AliHunter", selector: "#ah-app", hit: true}, 7238 ]; 7239 // Handle all script handlers 7240 let otherExtensionsCount = 0; 7241 let allExtensionsInterval = setInterval(function () { 7242 list_extensions.forEach(function (ext) { 7243 // let actionType = is_block ? "block" : "threat"; 7244 let actionType = is_block ? ((spy_extensions_block_mode == 0 && spy_extensions_redirect_url) ? "redirect" : "block") : "threat"; 7245 let containerDom = document.querySelector(ext.selector); 7246 if (containerDom) { 7247 if (is_block) containerDom.remove(); 7248 if (ext.hit) { 7249 createHit({ 7250 type: "spy_extensions", 7251 name: ext.name, 7252 pathname: window.location.pathname, 7253 action_type: actionType 7254 }); 7255 ext.hit = false;
7256 } 7257 if (actionType == "redirect") { 7258 window.location.href = toExternalUrl(spy_extensions_redirect_url); 7259 } 7260 } 7261 }); 7262 otherExtensionsCount++; 7263 if (otherExtensionsCount > 20) { 7264 clearInterval(allExtensionsInterval); 7265 } 7266 }, 250); 7267 7268 let ppspyCreateHit = false; 7269 let extensionsInterval = setInterval(function () { 7270 // let actionType = is_block ? "block" : "threat"; 7271 let actionType = is_block ? ((spy_extensions_block_mode == 0 && spy_extensions_redirect_url) ? "redirect" : "block") : "threat"; 7272 let ppspyContainer = document.querySelector(".ppspy-exp-view-root"); 7273 if (ppspyContainer) { 7274 if (is_block) ppspyContainer.style.display = "none"; 7275 if (!ppspyCreateHit) { 7276 createHit({ 7277 type: "spy_extensions", 7278 name: "PPSpy", 7279 pathname: window.location.pathname, 7280 action_type: actionType 7281 }); 7282 ppspyCreateHit = true; 7283 } 7284 if (actionType == "redirect") { 7285 window.location.href = toExternalUrl(spy_extensions_redirect_url); 7286 } 7287 clearInterval(extensionsInterval); 7288 } 7289 }, 10); 7290 }; 7291 7292 if (spy_extensions == 0) { 7293 // Handle CSS Part 7294 handleCssData(); 7295 // Handle other issue bug 7296 handleOtherBug(); 7297 7298 handleExtensions(true); 7299 7300 // FIRST SCRIPT 7301 var startTime = new Date().getTime(); 7302 var interval = setInterval(function () { 7303 if (new Date().getTime() - startTime > 10000) 7304 return clearInterval(interval), void 0; 7305 7306 var e = document.querySelectorAll("div"); 7307 7308 for (i = 0; i < e.length; i++) { 7309 var zIndex = document.querySelectorAll("div")[i].style.Zindex; 7310 if (zIndex === "2147483647") { 7311 createHit({ 7312 type: "spy_extensions", 7313 name: "", 7314 pathname: window.location.pathname, 7315 }); 7316 document 7317 .querySelectorAll("div") 7318 [i].parentNode.parentNode.parentNode.remove(); 7319 } 7320 } 7321 }, 699); 7322 7323 // SECOND SCRIPT 7324 var facebook = [ 7325 { 7326 id: "kefmekfmfacbdefimlancoccpocmgmpb", 7327 image: "icons/extension-icon-x16.png", 7328 }, 7329 { 7330 id: "lppbajkahdbbadheilijoeegnfndhlab", 7331 image: "icons/extension-icon-x16.png", 7332 }, 7333 { 7334 id: "hjbfbllnfhppnhjdhhbmjabikmkfekgf", 7335 image: "icons/extension-icon-x16.png", 7336 }, 7337 { 7338 id: "hdpfnbgfohonaplgnaahcefglgclmdpo", 7339 image: "icons/extension-icon-x16.png", 7340 }, 7341 { 7342 id: "amolhiihcpdbkjimhlffamgieibhfapi", 7343 image: "icons/extension-icon-x16.png", 7344 }, 7345 ]; 7346 const querySelectorAll = (node, selector) => { 7347 const nodes = [...node.querySelectorAll(selector)], 7348 nodeIterator = document.createNodeIterator(node, Node.ELEMENT_NODE); 7349 let currentNode; 7350 while ((currentNode = nodeIterator.nextNode())) { 7351 if (currentNode.shadowRoot) { 7352 nodes.push(...querySelectorAll(currentNode.shadowRoot, selector)); 7353 } 7354 } 7355 return nodes; 7356 }; 7357 const checkfacebook = (id, src, callback) => { 7358 let e = new Image(); 7359 e.src = "chrome-extension://" + id + "/" + src; 7360 (e.onload = () => callback(1)), (e.onerror = () => callback(0)); 7361 }; 7362 window.addEventListener("load", function () { 7363 [...document.getElementsByClassName("extension-container")].forEac
7363h( 7364 (e) => (e.style.display = "none") 7365 ); 7366 }); 7367 var blockCallback = function (items) { 7368 chrome.app.installState(function (e) { 7369 if (e === "not_installed") { 7370 return false; 7371 } 7372 }); 7373 }; 7374 window.addEventListener("load", function () { 7375 var tags = querySelectorAll(document, "iframe"); 7376 var ext = tags.filter((item) => { 7377 return ![ 7378 "intercom-frame", 7379 "admin-bar-iframe", 7380 "preview-bar-iframe", 7381 "^$", 7382 "__JSBridgeIframe_SetResult_1.0__", 7383 "__JSBridgeIframe__", 7384 "__JSBridgeIframe_SetResult__", 7385 "__JSBridgeIframe_1.0__", 7386 "looxReviewsFram", 7387 "looxReviewsFrame", 7388 "^paypal-offers--iframe-(.*)-(.*)-(.*)-(.*)-(.*)$", 7389 "^(.*)paypalLight(.*)$", 7390 "^fb(.*)$", 7391 "^snap(.*)$", 7392 "^tiktok(.*)$", 7393 "^bytedance(.*)$", 7394 ].find((value) => new RegExp(value).test(item.id)); 7395 }); 7396 if (ext.length > 0) { 7397 blockCallback(ext); 7398 } else { 7399 facebook.forEach((element) => {
7400 checkfacebook(element.id, element.image, (ok) => { 7401 if (ok) { 7402 blockCallback(element); 7403 } 7404 }); 7405 }); 7406 } 7407 }); 7408 } else { 7409 handleExtensions(false); 7410 } 7411 7412 if (inspect_elements == 0) { 7413 const devtools = { 7414 isOpen: false, 7415 orientation: undefined, 7416 }; 7417 7418 /* 7419 const threshold = 160; 7420 7421 const emitEvent = (isOpen, orientation) => { 7422 globalThis.dispatchEvent( 7423 new globalThis.CustomEvent("devtoolschange", { 7424 detail: { 7425 isOpen, 7426 orientation, 7427 }, 7428 }) 7429 ); 7430 7431 if (isOpen) { 7432 // createHit({'type': 'inspect_elements', 'pathname': window.location.pathname}) 7433 } 7434 }; 7435 7436 const main = ({ emitEvents = true } = {}) => { 7437 const widthThreshold = 7438 globalThis.outerWidth - globalThis.innerWidth > threshold; 7439 const heightThreshold = 7440 globalThis.outerHeight - globalThis.innerHeight > threshold; 7441 const orientation = widthThreshold ? "vertical" : "horizontal"; 7442 7443 if ( 7444 !(heightThreshold && widthThreshold) && 7445 ((globalThis.Firebug && 7446 globalThis.Firebug.chrome && 7447 globalThis.Firebug.chrome.isInitialized) || 7448 widthThreshold || 7449 heightThreshold) 7450 ) { 7451 if ( 7452 (!devtools.isOpen || devtools.orientation !== orientation) && 7453 emitEvents 7454 ) { 7455 emitEvent(true, orientation); 7456 } 7457 7458 devtools.isOpen = true; 7459 devtools.orientation = orientation; 7460 } else { 7461 if (devtools.isOpen && emitEvents) { 7462 emitEvent(false, undefined); 7463 } 7464 7465 devtools.isOpen = false; 7466 devtools.orientation = undefined; 7467 } 7468 }; 7469 7470 main({ emitEvents: false }); 7471 setInterval(main, 500); 7472 */ 7473 7474 window.addEventListener("devtoolschange", (event) => { 7475 if ( 7476 /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( 7477 navigator.userAgent 7478 ) 7479 ) { 7480 } else { 7481 if (event.detail.isOpen) { 7482 // createHit({'type': 'inspect_elements', 'pathname': window.location.pathname}) 7483 console.log(`%c ${inspect_elements_message}`, "font-size:32px;"); 7484 handleDevToolsDetected(); 7485 } 7486 // else { 7487 // window.localStorage.removeItem("is_inspect_open"); 7488 // } 7489 } 7490 }); 7491 7492 // Check Iframe 7493 function isLoadedInIframeLocal() { 7494 try { 7495 return window.self !== window.top; 7496 } catch (e) { 7497 return true; 7498 } 7499 } 7500 7501 7502 // Second way for devtools check 7503 const devtools3 = { 7504 isOpen: false, 7505 }; 7506 7507 // Check for keyboard shortcuts commonly used in developer tools 7508 function checkShortcuts() { 7509 if ( 7510 (window.outerWidth - window.innerWidth) > 160 || 7511 window.outerHeight - window.innerHeight > 160 7512 ) { 7513 if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { 7514 devtools3.isOpen = false;
7515 } else { 7516 if (window.innerWidth > 768) { 7517 devtools3.isOpen = true; 7518 } 7519 } 7520 } 7521 } 7522 7523 // Check for console.log output 7524 function checkForConsole() { 7525 if (window.console && window.console.firebug) { 7526 devtools3.isOpen = true; 7527 } 7528 } 7529 7530 // Check for changes in the user agent string 7531 function checkUserAgent() { 7532 if (navigator.userAgent.includes('Chrome')) { 7533 devtools.isOpen = true; 7534 } 7535 } 7536 7537 // Check for other indicators of developer tools (customize as needed) 7538 function checkOtherIndicators() { 7539 if ( 7540 window.location.href.indexOf('debugger') > -1 || 7541 window.location.href.indexOf('inspect') > -1 7542 ) { 7543 devtools3.isOpen = true; 7544 } 7545 } 7546 7547 // Combine checks 7548 function checkForDevTools() { 7549 checkShortcuts(); 7550 checkForConsole(); 7551 checkUserAgent(); 7552 checkOtherIndicators(); 7553 } 7554 7555 // Interval to check for developer tools 7556 if (!isLoadedInIframeLocal()) { 7557 setInterval(() => { 7558 checkForDevTools(); 7559 if (devtools3.isOpen) { 7560 handleDevToolsDetected(); 7561 } 7562 }, 1000); 7563 } 7564 7565 let isOkay = { cmd: false, option: false, i: false }; 7566 const undoCommand = () => { 7567 isOkay.cmd = false; 7568 isOkay.option = false; 7569 isOkay.i = false; 7570 }; 7571 let keyLists = [91, 18, 73]; 7572 document.addEventListener("keydown", (event) => { 7573 let find = keyLists.find((k) => k === event.keyCode); 7574 if (find) { 7575 if (find === 91) { 7576 isOkay.cmd = true; 7577 } 7578 if (find === 18) { 7579 isOkay.option = true; 7580 } 7581 if (find === 73) { 7582 isOkay.i = true; 7583 setTimeout(() => undoCommand(), 500); 7584 } 7585 } else { 7586 undoCommand(); 7587 } 7588 if (isOkay.cmd === true && isOkay.option === true && isOkay.i === true) { 7589 event.preventDefault(); 7590 return false; 7591 } 7592 }); 7593 let is_prev_open_console = window.localStorage.getItem("is_inspect_open"); 7594 if (is_prev_open_console !== null) { 7595 const obj = JSON.parse(is_prev_open_console); 7596 let currentTime = new Date().getTime(); 7597 if (obj.timestamp > currentTime) { 7598 handleDevToolsDetected(); 7599 } 7600 } 7601 } 7602 }; 7603 7604 const getPrivacyData = async () => { 7605 // When on the blocking template page, show the template as an overlay and stop 7606 const blockingPageUrl = noSpySettings?.blocking_template?.page_url; 7607 const _shopifyRoot = (window.Shopify && window.Shopify.routes && window.Shopify.routes.root) || '/'; 7608 const _localePrefix = _shopifyRoot === '/' ? '' : _shopifyRoot.replace(/\/$/, ''); 7609 if (blockingPageUrl && (window.location.pathname === blockingPageUrl || window.location.pathname === _localePrefix + blockingPageUrl)) { 7610 const html = noSpySettings.blocking_template?.html; 7611 if (html) { 7612 const applyOverlay = () => { 7613 try { 7614 if (window.stop) window.stop(); 7615 document.head.innerHTML = '<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Access Restricted</title>'; 7616 document.body.innerHTML = html; 7617 } catch (e) { 7618 document.body.innerHTML = html; 7619 } 7620 }; 7621 if (document.body) { 7622 applyOverlay(); 7623 } else { 7624 document.addEventListener('DOMContentLoaded', applyOverlay); 7625 } 7626 } 7627 return; 7628 } 7629 7630 // Check internal redirect pages 7631 if (noSpyInternalPages.length > 0) { 7632 const currentPath = window.location.pathname; 7633 const normalizedPath = currentPath.startsWith('/') ? currentPath : '/' + currentPath; 7634 const isInternalTarget = noSpyInternalPages.some(p => { 7635 const np = p.startsWith('/') ? p : '/' + p; 7636 return np === normalizedPath; 7637 }); 7638 if (isInternalTarget) return; 7639 } 7640 7641 // No settings metafield â app not migrated yet, use legacy flow 7642 if (!noSpySettings) { 7643 return getPrivacyDataLegacy(); 7644 } 7645 7646 // Check activation status 7647 if (!noSpySettings.activation_status) return; 7648 7649 const settings = noSpySettings.settings || {}; 7650 7651 // Access token / preview mode check (client-side) 7652 let noSpyAccessToken = getNoSpyAccessToken(); 7653 if (noSpyAccessToken && noSpySettings.access_token && noSpyAccessToken === noSpySettings.access_token) { 7654 const tokenSessionDays = noSpySettings.token_session_days || 1; 7655 const expiresAt = storeNoSpyAccessToken(noSpyAccessToken, tokenSessionDays); 7656 createAndPreviewMode(expiresAt); 7657 return; 7658 } 7659 7660 // Check excludes from metafield 7661 let is_exclude = false;
7662 const excludes = noSpySettings.excludes || {}; 7663 const exPages = excludes.pages || []; 7664 const exCollections = excludes.collections || []; 7665 7666 if (exPages.length > 0 || exCollections.length > 0) { 7667 let pathname = window.location.pathname.split('/'); 7668 if (pathname.length > 2) { 7669 if (exPages.length > 0) { 7670 if (exPages.includes(pathname[2])) { 7671 is_exclude = true; 7672 } else if (pathname[1] === 'products' && exPages.includes('/products/{handle}')) { 7673 is_exclude = true; 7674 } else if (pathname[1] === 'account') { 7675 if (exPages.includes(window.location.pathname)) { 7676 is_exclude = true; 7677 } else if (pathname[2] === 'orders' && exPages.includes('/account/orders/{handle}')) { 7678 is_exclude = true; 7679 } else if (pathname[2] === 'login' && exPages.includes('/account/login')) { 7680 is_exclude = true; 7681 } else if (pathname[2] === 'register' && exPages.includes('/account/register')) { 7682 is_exclude = true; 7683 } 7684 } else if (exPages.includes(window.location.pathname)) { 7685 is_exclude = true; 7686 } 7687 } 7688 if (exCollections.length > 0) { 7689 if (pathname[1] === 'collections' && exCollections.includes(pathname[2])) { 7690 is_exclude = true; 7691 } 7692 } 7693 } else { 7694 if (exPages.includes(window.location.pathname)) { 7695 is_exclude = true; 7696 } 7697 } 7698 } 7699 7700 // Read settings values 7701 let redirect = settings.redirect ?? 1; 7702 let copy_paste = settings.copy_paste ?? 1; 7703 let image_drag = settings.image_drag ?? 1; 7704 let right_click = settings.right_click ?? 1; 7705 let keys_shortcuts = settings.keys_shortcuts ?? 1; 7706 let text_selection = settings.text_selection ?? 1; 7707 let web_page_print = settings.web_page_print ?? 1; 7708 let spy_extensions = settings.spy_extensions ?? 1; 7709 let spy_extensions_block_mode = settings.spy_extensions_block_mode ?? 1; 7710 let spy_extensions_redirect_url = settings.spy_extensions_redirect_url ?? null; 7711 // These flags are INVERTED: 0/false means the feature is ON, which is why 7712 // every check below reads `== 0`. The admin toggle matches (SettingsToggle 7713 // renders `!enabled ? on : off`), so a stored `true` displays as "Off". 7714 // The default of 1 here therefore means "off" for a shop with no settings. 7715 let inspect_elements = settings.inspect_elements ?? 1; 7716 let inspect_elements_message = settings.inspect_elements_message ?? ''; 7717 let block_spam_bots = settings.block_spam_bots ?? 1; 7718 let proxy_vpn_block = settings.proxy_vpn_block ?? 1; 7719 let proxy_vpn_redirect_url = settings.proxy_vpn_redirect_url ?? null; 7720 let tor_block = settings.tor_block ?? 1; 7721 7722 // Single API call: verify-visitor (geo-location + bot verification) 7723 let geoService = new GeoService(); 7724 let cachedGeo = geoService.fetch(); // returns null if expired or missing 7725 7726 let ip = null; 7727 let geoLocationData = cachedGeo; // use cache immediately for redirect matching 7728 let botVerification = null; 7729 let reached = cachedGeo ? (localStorage.getItem('no-spy-geo-reached') === 'true') : false; 7730 7731 // Always call verify-visitor for bot verification + IP resolution. 7732 // Pass cached ASN so server skips the geo lookup when we already have geo. 7733 const sessionService = new SessionService(); 7734 sessionService.init(); 7735 try { 7736 const verifyRes = await fetch(`${noSpyBaseUrl}/verify-visitor`, { 7737 method: 'POST', 7738 headers: { 'Content-Type': 'application/json' }, 7739 body: JSON.stringify({ 7740 shop: Shopify.shop, 7741 session_id: NoSpyStore.sessionId || crypto.randomUUID(), 7742 handle: window.location.pathname, 7743 asn: cachedGeo?.asn || 0, 7744 reached: reached ? 'true' : 'false', 7745 geo: cachedGeo || null, 7746 }), 7747 }); 7748 const verifyJson = await verifyRes.json(); 7749 ip = verifyJson.ip; 7750 botVerification = verifyJson.bot_verification; 7751 7752 if (verifyJson.geo_location) { 7753 // Fresh geo from server (cache was empty) â cache it and use it 7754 geoLocationData = verifyJson.geo_location; 7755 geoService.saveToCache(geoLocationData, verifyJson.reached); 7756 reached = verifyJson.reached; 7757 } 7758
7759 // Attach session beacon unconditionally so duration is tracked regardless of which 7760 // features are enabled. Must happen before any potential redirect below. 7761 if (ip) { 7762 let beaconSent = false; 7763 const sendOnce = () => { 7764 if (beaconSent) return; 7765 beaconSent = true; 7766 sessionService.sendBeacon(ip); 7767 }; 7768 window.addEventListener('beforeunload', sendOnce); 7769 document.addEventListener('visibilitychange', () => { 7770 if (document.visibilityState === 'hidden') sendOnce(); 7771 }); 7772 } 7773 7774 // Server pre-matched a redirect rule â act on it immediately (log already has correct status) 7775 if (redirect == 0 && verifyJson.redirect_matched && verifyJson.redirect_rule) { 7776 const rule = verifyJson.redirect_rule; 7777 if (rule.redirect_type === 'blocking_page') { 7778 applyBlockingPage(); 7779 return; 7780 } 7781 if (rule.redirect_url) { 7782 if (rule.redirect_type === 'internal') { 7783 location.href = rule.redirect_url; 7784 } else { 7785 location.replace(toExternalUrl(rule.redirect_url)); 7786 } 7787 return; 7788 } 7789 } 7790 } catch (e) { 7791 // verify-visitor failed â continue with cached geo if available, skip bot check 7792 } 7793 7794 if (!isWhitelistBots) { 7795 // Check server-side bot verification 7796 if (botVerification && botVerification.is_whitelisted_bot === true) { 7797 return false; 7798 } 7799 7800 // Client-side redirect evaluation (fallback when server didn't match) 7801 if (redirect == 0) { 7802 new RedirectFeature(ip, geoLocationData, botVerification); 7803 } 7804 7805 if (proxy_vpn_block == 0 || tor_block == 0) { 7806 const blockingTemplate = noSpySettings.blocking_template || null; 7807 new ProxyVpnTorBlockFeature(proxy_vpn_block == 0, tor_block == 0, proxy_vpn_redirect_url, { 7808 proxy_vpn_show_blocking_page: !!settings.proxy_vpn_show_blocking_page, 7809 tor_show_blocking_page: !!settings.tor_show_blocking_page, 7810 blocking_template_landing_effect: blockingTemplate ? blockingTemplate.landing_effect !== false : true, 7811 blocking_template_html: blockingTemplate?.html || null, 7812 blocking_template_page_url: blockingTemplate?.page_url || null, 7813 }); 7814 } 7815 7816 if (block_spam_bots == 0) { 7817 const allowedBots = noSpySettings.allowed_bots || {}; 7818 new BlockSpamBotsFeature({ 7819 ip: ip, 7820 threshold: 2.5, 7821 debug: false, 7822 is_block: true, 7823 bot_verification: botVerification || { is_whitelisted_bot: false }, 7824 allowed_bots: allowedBots, 7825 }); 7826 } 7827 7828 if (is_exclude) { 7829 return false; 7830 } 7831 7832 const blockingTemplate = noSpySettings.blocking_template || null; 7833 applyProtections({copy_paste, image_drag, right_click, keys_shortcuts, text_selection, web_page_print, spy_extensions, spy_extensions_block_mode, spy_extensions_redirect_url, inspect_elements, inspect_elements_message, inspect_elements_show_blocking_page: !!settings.inspect_elements_show_blocking_page, blocking_template_html: blockingTemplate?.html || null, blocking_template_landing_effect: blockingTemplate ? blockingTemplate.landing_effect !== false : true, blocking_template_page_url: blockingTemplate?.page_url || null}); 7834 } else { 7835 return false; 7836 } 7837 }; 7838 7839 // Theme editor (Shopify.designMode === true): never redirect, block, or log â the merchant 7840 // must be able to design the page without NoSpy navigating away or hiding content. 7841 if (window.Shopify && window.Shopify.designMode) { 7842 // no-op in the theme editor 7843 } else if (noSpySettings) { 7844 getPrivacyData(); 7845 } else { 7846 getPrivacyDataLegacy(); 7847 } 7848 7849 if(window.Shopify && window.Shopify.currency && window.Shopify.currency.rate) { 7850 window.localStorage.setItem('nospyExchangeRate', window.Shopify.currency.rate); 7851 } 7852</script>
7852 7853 7854 7855<!-- END app block --><!-- BEGIN app block: shopify://apps/elevar-conversion-tracking/blocks/dataLayerEmbed/bc30ab68-b15c-4311-811f-8ef485877ad6 --> 7856 7857 7858
7859<script type="module" dynamic> 7860 const configUrl = "/a/elevar/static/configs/5c44356f4ac919ed345f27e5d4932ff7fb50d32d/config.js"; 7861 const config = (await import(configUrl)).default; 7862 const scriptUrl = config.script_src_app_theme_embed; 7863 7864 if (scriptUrl) { 7865 const { handler } = await import(scriptUrl); 7866 7867 await handler( 7868 config, 7869 { 7870 cartData: { 7871 marketId: "15313797174", 7872 localeCountryCode:"US", 7873 attributes:{}, 7874 cartTotal: "0.0", 7875 currencyCode:"USD", 7876 items: [] 7877} 7878, 7879 user: { 7880 cartTotal: "0.0", 7881 currencyCode:"USD", 7882 customer: {}, 7883} 7884, 7885 isOnCartPage:false, 7886 collectionView:null, 7887 searchResultsView:null, 7888 productView:{ 7889 attributes:{}, 7890 currencyCode:"USD",defaultVariant: {id:"01245",name:"Flag Organizer", 7891 brand:"Evergreen", 7892 category:"Flag Accessories", 7893 variant:"Default Title", 7894 price: "25.0", 7895 productId: "7616317653046", 7896 variantId: "42920115601462", 7897 compareAtPrice: "0.0",image:"\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307",url:"\/products\/01245?variant=42920115601462"},items: [{id:"01245",name:"Flag Organizer", 7898 brand:"Evergreen", 7899 category:"Flag Accessories", 7900 variant:"Default Title", 7901 price: "25.0", 7902 productId: "7616317653046", 7903 variantId: "42920115601462", 7904 compareAtPrice: "0.0",image:"\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307",url:"\/products\/01245?variant=42920115601462"},] 7905 }, 7906 } 7907 ); 7908 } 7909</script>
7909 7910 7911 7912<!-- END app block -->
7912<script src="https://cdn.shopify.com/extensions/01a0eda4-289d-74bc-9949-f47d35d3f409/forms-2601/assets/shopify-forms-loader.js" type="text/javascript" defer="defer"></script>
vendor: 1 bytes, line 7912
7912
7913<script src="https://cdn.shopify.com/extensions/01a0edd2-f8b6-7667-9d3a-2c5c6b99a671/2026-09-29-15-39-01-UTC--fb5d645/assets/smile-loader.js" type="text/javascript" defer="defer"></script>
7913 7914<link href="https://monorail-edge.shopifysvc.com" rel="dns-prefetch">
7915<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: 59637006390,url: window.location.href,navigation_start,duration: currentMs - navigation_start,session_token,page_type: "product"};window.navigator.sendBeacon("https://monorail-edge.shopifysvc.com/v1/produce", JSON.stringify({schema_id: "online_store_buyer_site_abandonment/1.1",payload: payload,metadata: {event_created_at_ms: currentMs,event_sent_at_ms: currentMs}}));}}window.addEventListener('pagehide', handle_abandonment_event);}}());</script>
vendor: 1 bytes, line 7915
7915
7916<script> 7917 window.__TREKKIE_SHIM_QUEUE = window.__TREKKIE_SHIM_QUEUE || []; 7918</script>
vendor: 1 bytes, line 7918
7918
7919<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}
7919).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: 59637006390,storefrontBaseUrl: "https://myevergreen.com",extensionsBaseUrl: "https://extensions.shopifycdn.com/cdn/shopifycloud/web-pixels-manager",monorailEndpoint: "https://myevergreen.com/.well-known/shopify/monorail/unstable/produce_batch",surface: "storefront-renderer",enabledBetaFlags: ["16072cab","8450a54b","7ee89bf1"],webPixelsConfigList: [{"id":"2777841718","configuration":"{\"myshopifyDomain\":\"9695f5-c4.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":"2774466614","configuration":"{\"accountID\":\"TXh7tT\",\"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":"2534866998","configuration":"{\"config\":\"{\\\"google_tag_ids\\\":[\\\"AW-872318733\\\",\\\"GT-PZSPSR9K\\\"],\\\"target_country\\\":\\\"US\\\",\\\"gtag_events\\\":[{\\\"type\\\":\\\"search\\\",\\\"action_label\\\":\\\"AW-872318733\\\/tXvHCLq1ktIZEI2O-p8D\\\"},{\\\"type\\\":\\\"begin_checkout\\\",\\\"action_label\\\":\\\"AW-872318733\\\/djY9CMC1ktIZEI2O-p8D\\\"},{\\\"type\\\":\\\"view_item\\\",\\\"action_label\\\":[\\\"AW-872318733\\\/xv43CO2yktIZEI2O-p8D\\\",\\\"MC-2MBD7KCJKQ\\\"]},{\\\"type\\\":\\\"purchase\\\",\\\"action_label\\\":[\\\"AW-872318733\\\/KhUFCO-xktIZEI2O-p8D\\\",\\\"MC-2MBD7KCJKQ\\\"]},{\\\"type\\\":\\\"page_view\\\",\\\"action_label\\\":[\\\"AW-872318733\\\/X2Z7COqyktIZEI2O-p8D\\\",\\\"MC-2MBD7KCJKQ\\\"]},{\\\"type\\\":\\\"add_payment_info\\\",\\\"action_label\\\":\\\"AW-872318733\\\/7fynCMO1ktIZEI2O-p8D\\\"},{\\\"type\\\":\\\"add_to_cart\\\",\\\"action_label\\\":\\\"AW-872318733\\\/KqEGCL21ktIZEI2O-p8D\\\"}],\\\"enable_monitoring_mode\\\":false}\"}","eventPayloadVersion":"v1","runtimeContext":"OPEN","scriptVersion":"a3321ca85cf5aaf6b57585fcd8d67b3a","type":"APP","apiClientId":1780363,"privacyPurposes":[],"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":"2468511798","configuration":"{\"pixelCode\":\"CS40VV3C77UEQSGTJVC0\"}","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":[]},"dataSharingState":"optimized"},{"id":"2170454070","configuration":"{\"accountID\":\"476837\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"6beb2e80c5918031073c477e306feacf","type":"APP","apiClientId":219313,"privacyPurposes":["ANALYTICS"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_email","read_customer_name","read_customer_personal_data"],"dataSharingControls":["share_all_events"]}
7919,"dataSharingState":"unrestricted"},{"id":"1721008182","configuration":"{\"campaignID\":\"44913\",\"externalExecutionURL\":\"https:\/\/engine.saasler.com\/api\/v1\/webhook_executions\/2b803911b737e755702ecae044db1b19\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"7a47b06116c806e4367c27d301f4f458","type":"APP","apiClientId":3546795,"privacyPurposes":[],"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":"1538850870","configuration":"{\"api_url\":\"https:\\\/\\\/hub.upsellit.com\",\"org_id\":\"45404869\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"a7bdcee38819ba412b3d84030e7721df","type":"APP","apiClientId":215082500097,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_personal_data"],"dataSharingControls":["share_all_events"]},"dataSharingState":"unrestricted"},{"id":"1368916022","configuration":"{\"locale\":\"en_US\",\"client\":\"myevergreen\",\"environment\":\"production\",\"deployment_zone\":\"main_site\",\"use_external_ids\":\"false\",\"storefront_api_key\":\"none\",\"product_metafield_key\":\"none\",\"product_metafield_namespace\":\"none\",\"multi_locale_enabled\":\"false\",\"locale_mapping\":\"{}\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"e9849bbfb1381d47503a57eebf3a7a78","type":"APP","apiClientId":1888040,"privacyPurposes":["ANALYTICS","MARKETING"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data"],"dataSharingControls":["share_all_events"]},"dataSharingState":"unrestricted"},{"id":"1208156214","configuration":"{\"accountID\":\"9695f5-c4\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"1d4c781273105676f6b02a329648437f","type":"APP","apiClientId":32196493313,"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":"unrestricted","enabledFlags":["9a3ed68a"]},{"id":"1152286774","configuration":"{\"projectId\":\"sra4j57sci\"}","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":"1138294838","configuration":"{\"config_url\": \"https:\/\/shopify-gtm-suite.getelevar.com\/configs\/5c44356f4ac919ed345f27e5d4932ff7fb50d32d\/config.js\"}","eventPayloadVersion":"v1","runtimeContext":"LAX","scriptVersion":"7ae63d00911d5ee26809bf1e3232d852","type":"APP","apiClientId":2509311,"privacyPurposes":[],"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":"711426102","configuration":"{\"accountId\":\"9695f5-c4.myshopify.com\",\"trackingOrigin\":\"https:\\\/\\\/shdid.me\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"7e4a2932f61f97828d974aeb88ceba49","type":"APP","apiClientId":94099111937,"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"},{"id":"496631862","configuration":"{\"ti\":\"151011924\",\"endpoint\"
7919:\"https:\/\/bat.bing.com\/action\/0\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"5ee93563fe31b11d2d65e2f09a5229dc","type":"APP","apiClientId":2997493,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_personal_data"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"37257270","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"3","type":"CUSTOM","privacyPurposes":[],"name":"Google Ads 872318733\/543bCLmnz","dataSharingAdjustments":{"protectedCustomerApprovalScopes":[],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"41222198","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":[],"name":"Yottaa","dataSharingAdjustments":{"protectedCustomerApprovalScopes":[],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"43319350","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"3","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING"],"name":"Upsellit Pixel","dataSharingAdjustments":{"protectedCustomerApprovalScopes":[],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"43515958","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"2","type":"CUSTOM","privacyPurposes":[],"name":"Microsoft Ads 5438550","dataSharingAdjustments":{"protectedCustomerApprovalScopes":[],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"112295990","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":[],"name":"Elevar - Checkout Tracking","dataSharingAdjustments":{"protectedCustomerApprovalScopes":[],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"140443702","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"1","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"name":"AddShoppers","dataSharingAdjustments":{"protectedCustomerApprovalScopes":[],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"id":"148242486","eventPayloadVersion":"1","runtimeContext":"LAX","scriptVersion":"3","type":"CUSTOM","privacyPurposes":[],"name":"Hawksearch","dataSharingAdjustments":{"protectedCustomerApprovalScopes":[],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"},{"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":"Evergreen","paymentSettings":{"currencyCode":"USD"},"myshopifyDomain":"9695f5-c4.myshopify.com","countryCode":"US","storefrontUrl":"https:\/\/myevergreen.com"},"customer":null,"cart":null,"checkout":null,"productVariants":[{"price":{"amount":25.0,"currencyCode":"USD"},"product":{"title":"Flag Organizer","vendor":"Evergreen","id":"7616317653046","untranslatedTitle":"Flag Organizer","url":"\/products\/01245","type":"Flag Accessories"},"id":"42920115601462","image":{"src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307"},"sku":"01245","title":"Default Title","untranslatedTitle":"Default Title"}],"products":[{"id":"7616317653046","handle":"01245","isCollective":false,"title":"Flag Organizer","type":"Flag Accessories","untranslatedTitle":"Flag Organizer","url":"\/products\/01245","vendor":"Evergreen","remoteShopId":null,"variants":[{"id":"42920115601462","image":{"src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307"},"price":{"amount":25.0,"currencyCode":"USD"},"sku":"01245","title":"Default Title","untranslatedTitle":"Default Title"}]}],"purchasingCompany":null},},"https://myevergreen.com/cdn","a5bf51cfwabd6c495p49b74ff1maa529d2b",{"modern":"","legacy":""},{"trekkieShim":true,"agentContext":true,"apiClientId":"580111","facebookCapiEnabled":"false","themeId":"153311182902","themePublished":"true","eventMetadataId":"2cb51445-8808-4c99-8b57-2c2193df48b0","pageType":"product","resourceId":"7616317653046","shopId":"59637006390","storefrontBaseUrl":"https:\/\/myevergreen.com","extensionBaseUrl":"https:\/\/extensions.shopifycdn.com\/cdn\/shopifycloud\/web-pixels-manager","surface":"storefront-renderer","enabledBetaFlags":"[\"16072cab\", \"8450a54b\", \"7ee89bf1\"]","isMerchantRequest":"false","hashVersion":"a5bf51cfwabd6c495p49b74ff1maa529d2b","publish":"custom","events":"[[\"page_viewed\",{}],[\"product_viewed\",{\"productVariant\":{\"price\":{\"amount\":25.0,\"currencyCode\":\"USD\"},\"product\":{\"title\":\"Flag Organizer\",\"vendor\":\"Evergreen\",\"id\":\"7616317653046\",\"untranslatedTitle\":\"Flag Organizer\",\"url\":\"\/products\/01245\",\"type\":\"Flag Accessories\"},\"id\":\"42920115601462\",\"image\":{\"src\":\"\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307\"},\"sku\":\"01245\",\"title\":\"Default Title\",\"untranslatedTitle\":\"Default Title\"}}]]"});})();</script>
7919<script> 7920 window.ShopifyAnalytics = window.ShopifyAnalytics || {}; 7921 window.ShopifyAnalytics.meta = window.ShopifyAnalytics.meta || {}; 7922 window.ShopifyAnalytics.meta.currency = 'USD'; 7923 var meta = {"product":{"id":7616317653046,"gid":"gid:\/\/shopify\/Product\/7616317653046","vendor":"Evergreen","type":"Flag Accessories","handle":"01245","variants":[{"id":42920115601462,"price":2500,"name":"Flag Organizer","public_title":null,"sku":"01245"}],"remote":false,"collective":false},"page":{"pageType":"product","resourceType":"product","resourceId":7616317653046,"requestId":"47b8d99a-f2fc-4f0c-8979-273a6bd40ca1-1790697223"}}; 7924 for (var attr in meta) { 7925 window.ShopifyAnalytics.meta[attr] = meta[attr]; 7926 } 7927</script>
vendor: 1 bytes, line 7927
7927
7928<script class="analytics"> 7929 (function () { 7930 var customDocumentWrite = function(content) { 7931 var jquery = null; 7932 7933 if (window.jQuery) { 7934 jquery = window.jQuery; 7935 } else if (window.Checkout && window.Checkout.$) { 7936 jquery = window.Checkout.$; 7937 } 7938 7939 if (jquery) { 7940 jquery('body').append(content); 7941 } 7942 }; 7943 7944 var hasLoggedConversion = function(token) { 7945 if (token) { 7946 return document.cookie.indexOf('loggedConversion=' + token) !== -1; 7947 } 7948 return false; 7949 } 7950 7951 var setCookieIfConversion = function(token) { 7952 if (token) { 7953 var twoMonthsFromNow = new Date(Date.now()); 7954 twoMonthsFromNow.setMonth(twoMonthsFromNow.getMonth() + 2); 7955 7956 document.cookie = 'loggedConversion=' + token + '; expires=' + twoMonthsFromNow; 7957 } 7958 } 7959 7960 var trekkie = window.ShopifyAnalytics.lib = window.trekkie = window.trekkie || []; 7961 window.ShopifyAnalytics.lib.trekkie = window.trekkie; 7962 if (trekkie.integrations) { 7963 return; 7964 } 7965 trekkie.methods = [ 7966 'identify', 7967 'page', 7968 'ready', 7969 'track', 7970 'trackForm', 7971 'trackLink' 7972 ]; 7973 trekkie.factory = function(method) { 7974 return function() { 7975 var args = Array.prototype.slice.call(arguments); 7976 args.unshift(method); 7977 trekkie.push(args); 7978 if (method == 'track' || method == 'page') { 7979 var pageUrl; 7980 try { 7981 pageUrl = window.location.href; 7982 } catch (e) {} 7983 var pageReferrer; 7984 try { 7985 pageReferrer = document.referrer; 7986 } catch (e) {} 7987 try { 7988 if (window.__TREKKIE_SHIM_QUEUE == null) { 7989 window.__TREKKIE_SHIM_QUEUE = []; 7990 } 7991 window.__TREKKIE_SHIM_QUEUE.push({ 7992 from: 'trekkie-stub', 7993 method: method, 7994 args: args.slice(1), 7995 pageContext: { 7996 url: pageUrl, 7997 referrer: pageReferrer 7998 } 7999 }); 8000 } catch (e) { 8001 // no-op 8002 } 8003 } 8004 return trekkie; 8005 }; 8006 }; 8007 for (var i = 0; i < trekkie.methods.length; i++) { 8008 var key = trekkie.methods[i]; 8009 trekkie[key] = trekkie.factory(key); 8010 } 8011 trekkie.load = function(config) { 8012 trekkie.config = config || {}; 8013 trekkie.config.initialDocumentCookie = document.cookie; 8014 var first = document.getElementsByTagName('script')[0]; 8015var script = document.createElement('script'); 8016script.type = 'text/javascript'; 8017script.onerror = function(e) { 8018 var scriptFallback = document.createElement('script'); 8019 scriptFallback.type = 'text/javascript'; 8020 scriptFallback.onerror = function(error) { 8021 var Monorail = { 8022 produce: function produce(monorailDomain, schemaId, payload) { 8023 var currentMs = new Date().getTime(); 8024 var event = { 8025 schema_id: schemaId, 8026 payload: payload, 8027 metadata: { 8028 event_created_at_ms: currentMs, 8029 event_sent_at_ms: currentMs 8030 } 8031 }; 8032 return Monorail.sendRequest("https://" + monorailDomain + "/v1/produce", JSON.stringify(event)); 8033 }, 8034 sendRequest: function sendRequest(endpointUrl, payload) { 8035 // Try the sendBeacon API 8036 if (window && window.navigator && typeof window.navigator.sendBeacon === 'function' && typeof window.Blob === 'function' && !Monorail.isIos12()) { 8037 var blobData = new window.Blob([payload], { 8038 type: 'text/plain' 8039 }); 8040 8041 if (window.navigator.sendBeacon(endpointUrl, blobData)) { 8042 return true; 8043 } // sendBeacon was not successful 8044 8045 } // XHR beacon 8046 8047 var xhr = new XMLHttpRequest(); 8048 8049 try { 8050 xhr.open('POST', endpointUrl); 8051 xhr.setRequestHeader('Content-Type', 'text/plain'); 8052 xhr.send(payload); 8053 } catch (e) { 8054 console.log(e); 8055 } 8056 8057 return false; 8058 }, 8059 isIos12: function isIos12() { 8060 return window.navigator.userAgent.lastIndexOf('iPhone; CPU iPhone OS 12_') !== -1 || window.navigator.userAgent.lastIndexOf('iPad; CPU OS 12_') !== -1; 8061 } 8062 }; 8063 Monorail.produce('monorail-edge.shopifysvc.com', 8064 'trekkie_storefront_load_errors/1.1', 8065 {shop_id: 59637006390, 8066 theme_id: 153311182902, 8067 app_name: "storefront", 8068 context_url: window.location.href, 8069 source_url: "//myevergreen.com/cdn/s/trekkie.storefront.f1ba865b3fecd812ad617f74ac079261075e9edb.min.js"}); 8070 8071 }; 8072 scriptFallback.async = true; 8073 scriptFallback.src = '//myevergreen.com/cdn/s/trekkie.storefront.f1ba865b3fecd812ad617f74ac079261075e9edb.min.js'; 8074 first.parentNode.insertBefore(scriptFallback, first); 8075}; 8076script.async = true; 8077script.src = '//myevergreen.com/cdn/s/trekkie.storefront.f1ba865b3fecd812ad617f74ac079261075e9edb.min.js'; 8078first.parentNode.insertBefore(script, first); 8079 8080 }; 8081 trekkie.load( 8082 {"Trekkie":{"appName":"storefront","development":false,"defaultAttributes":{"shopId":59637006390,"isMerchantRequest":null,"themeId":153311182902,"themeCityHash":"3036418959083613090","contentLanguage":"en","currency":"USD","eventMetadataId":"2cb51445-8808-4c99-8b57-2c2193df48b0"},"isServerSideCookieWritingEnabled":true,"monorailRegion":"shop_domain","enabledBetaFlags":["764d78cb","8450a54b","7ee89bf1"]},"Session Attribution":{},"S2S":{"facebookCapiEnabled":false,"source":"trekkie-storefront-renderer","apiClientId":580111}} 8083 ); 8084 8085 var loaded = false;
8086 trekkie.ready(function() { 8087 if (loaded) return; 8088 loaded = true; 8089 8090 window.ShopifyAnalytics.lib = window.trekkie; 8091 8092 var originalDocumentWrite = document.write; 8093 document.write = customDocumentWrite; 8094 try { window.ShopifyAnalytics.merchantGoogleAnalytics.call(this); } catch(error) {}; 8095 document.write = originalDocumentWrite; 8096 8097 var match = window.location.pathname.match(/checkouts\/(.+)\/(thank_you|post_purchase)/) 8098 var token = match? match[1]: undefined; 8099 if (!hasLoggedConversion(token)) { 8100 setCookieIfConversion(token); 8101 window.ShopifyAnalytics.lib.track("Viewed Product",{"currency":"USD","variantId":42920115601462,"productId":7616317653046,"productGid":"gid:\/\/shopify\/Product\/7616317653046","name":"Flag Organizer","price":"25.00","sku":"01245","brand":"Evergreen","variant":null,"category":"Flag Accessories","nonInteraction":true,"remote":false,"available":true},undefined,undefined,{"shopifyEmitted":true}); 8102 } 8103 }); 8104 8105 window.ShopifyAnalytics.lib.page(null,{"pageType":"product","resourceType":"product","resourceId":7616317653046,"requestId":"47b8d99a-f2fc-4f0c-8979-273a6bd40ca1-1790697223","shopifyEmitted":true}); 8106 8107 var eventsListenerScript = document.createElement('script'); 8108 eventsListenerScript.async = true; 8109 eventsListenerScript.src = "//myevergreen.com/cdn/shopifycloud/storefront/assets/shop_events_listener-4e26a9ce.js"; 8110 document.getElementsByTagName('head')[0].appendChild(eventsListenerScript); 8111})();</script>
vendor: 1 bytes, line 8111
8111
8112<script 8113 defer 8114 src="https://myevergreen.com/cdn/shopifycloud/perf-kit/shopify-perf-kit-3.9.4.min.js" 8115 data-application="storefront-renderer" 8116 data-shop-id="59637006390" 8117 data-render-region="gcp-us-central1" 8118 data-page-type="product" 8119 data-theme-instance-id="153311182902" 8120 data-theme-name="Enterprise" 8121 data-theme-version="1.6.2" 8122 data-monorail-region="shop_domain" 8123 data-resource-timing-sampling-rate="10" 8124 data-shs="true" 8125 data-shs-beacon="true" 8126 data-shs-export-with-fetch="true" 8127 data-shs-logs-sample-rate="1" 8128 data-shs-beacon-endpoint="https://myevergreen.com/api/collect" 8129></script>
8129 8130<meta name="shopify-y" content="db2399ac-a491-4e03-8135-1153f034a36a" data-expiration="1822254823000"><meta name="shopify-s" content="86f18f51-3837-45c8-aa7b-43d1029b56da" data-expiration="1790699023000"><meta name="new-cookie-storage-activated" content="t"> 8131</head> 8132 8133 <body 8134 8135 > 8136 8137 8138 <a class="skip-link btn btn--primary visually-hidden" href="#main-content" data-ce-role="skip">Skip to content</a><!-- BEGIN sections: header-group --> 8139<section id="shopify-section-sections--21510771834934__custom_brand_bar_qrbJck" class="shopify-section shopify-section-group-header-group"><style> 8140 .brand-bar { 8141 display: flex; 8142 justify-content: space-between; 8143 align-items: center; 8144 padding: 10px 20px; 8145 } 8146 8147 .brand-bar-left, .brand-bar-right { 8148 display: flex; 8149 align-items: center; 8150 } 8151 .divider { 8152 margin: 0; 8153 } 8154 8155 8156 @media (max-width: 768px) { 8157 .brand-bar { 8158 display: none; /* Hide on mobile devices */ 8159 } 8160 } 8161</style> 8162 8163 8164 8165 8166 8167<div class="brand-bar" style="background-color: #009174;"> 8168 <div class="brand-bar-left"> 8169 8170 8171 <a href="https://myevergreen.com/"> 8172 <img src="//myevergreen.com/cdn/shop/files/brand-bar-logos-myeg.svg?crop=center&height=24&v=1734548171&width=98" alt="Shop My Evergreen" height="24" width="98"> 8173 </a> 8174 8175 8176 <span class="divider" style="color: #ffffff;">|</span> 8177 8178 8179 <a href="https://plowhearth.com/"> 8180 <img src="//myevergreen.com/cdn/shop/files/brand-bar-logos-ph.svg?crop=center&height=24&v=1734548171&width=108" alt="Shop Plow and Hearth" height="24" width="108"> 8181 </a> 8182 8183 8184 <span class="divider" style="color: #ffffff;">|</span> 8185 8186 8187 <a href="https://teamsportsamerica.com/"> 8188 <img src="//myevergreen.com/cdn/shop/files/brand-bar-logos-tsa.svg?crop=center&height=24&v=1734548171&width=158" alt="Shop Team Sports America" height="24" width="158"> 8189 </a> 8190 8191 8192 <span class="divider" style="color: #ffffff;" aria-hidden="true">|</span> 8193 8194 8195 <a href="https://chimes.com/" target="_blank" aria-label="Visit chimes.com (opens in a new tab)"> 8196 <img src="//myevergreen.com/cdn/shop/files/woodstock-2.svg?crop=center&height=24&v=1769545495&width=158" alt="Shop Woodstock Chimes" height="24" width="160"> 8197 </a> 8198 8199 8200 </div> 8201 8202 <div class="brand-bar-right"> 8203 8204 </div> 8205</div> 8206 8207<style> #shopify-section-sections--21510771834934__custom_brand_bar_qrbJck img {margin-top: 3px; margin-bottom: 3px;} </style></section><div id="shopify-section-sections--21510771834934__announcement" class="shopify-section shopify-section-group-header-group cc-announcement"> 8208<link href="//myevergreen.com/cdn/shop/t/101/assets/announcement.css?v=182839355565175739031781124411" rel="stylesheet" type="text/css" media="all" /> 8209
8209<script src="//myevergreen.com/cdn/shop/t/101/assets/announcement.js?v=123267429028003703111781124412" defer="defer"></script>
8209<style data-shopify>.announcement { 8210 --announcement-text-color: 255 255 255; 8211 background-color: #da5256; 8212 }</style><announcement-bar class="announcement block text-body-large" data-slide-delay="7000"> 8213 <div class="container"> 8214 <div class="flex"> 8215 <div class="announcement__col--left announcement__col--align-center"><div class="announcement__text flex items-center m-0" > 8216 <div class="rte"><p>Free Shipping on $59+ with Code: FREESHIP59</p></div> 8217 </div></div> 8218 8219 </div> 8220 </div> 8221 </announcement-bar> 8222<style> #shopify-section-sections--21510771834934__announcement a {text-decoration: none; font-weight: normal;} @media screen and (max-width: 1024px) {#shopify-section-sections--21510771834934__announcement * {display: none; }} </style></div><div id="shopify-section-sections--21510771834934__header" class="shopify-section shopify-section-group-header-group cc-header"> 8223<style data-shopify>.header { 8224 --bg-color: 255 255 255 / 1.0; 8225 --text-color: 7 7 7; 8226 --nav-bg-color: 255 255 255; 8227 --nav-text-color: 7 7 7; 8228 --nav-child-bg-color: 255 255 255; 8229 --nav-child-text-color: 7 7 7; 8230 --header-accent-color: 119 119 119; 8231 --search-bg-color: #e6e6e6; 8232 8233 8234 }</style><store-header class="header bg-theme-bg text-theme-text has-motion search-is-collapsed"data-is-sticky="true"data-is-search-minimised="true"style="--header-transition-speed: 300ms"> 8235 <header class="header__grid header__grid--left-logo container flex flex-wrap items-center"> 8236 <div class="header__logo logo flex js-closes-menu"> 8237 <h1 class="visually-hidden">Evergreen â Sassafras Mats, Flags, Home and Garden Decor, and Gifts</h1><a class="logo__link inline-block" href="/"><span class="flex" style="max-width: 300px;"> 8238 <img src="//myevergreen.com/cdn/shop/files/evergreen-logo-full-color.svg?v=1718829572&width=300" 8239 style="object-position: 50.0% 50.0%" loading="eager" 8240 width="300" 8241 height="50" 8242 8243 alt="Shop myevergreen.com for seasonal decor and gifts perfect for any occasion."> 8244 </span></a></div> 8245 8246 8247 8248 8249 8250 8251
8252 <div class="header__search relative js-closes-menu"> 8253 <hawksearch-unifiedsearch-field></hawksearch-unifiedsearch-field> 8254 <hawksearch-visualsearch-field></hawksearch-visualsearch-field> 8255 </div> 8256 8257 8258 8259 8260 8261 8262<div class="header__icons flex justify-end mis-auto js-closes-menu"><a class="header__icon md:hidden js-show-search" href="/search" aria-controls="search-bar"> 8263 <svg width="21" height="23" viewBox="0 0 21 23" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M14.398 14.483 19 19.514l-1.186 1.014-4.59-5.017a8.317 8.317 0 0 1-4.888 1.578C3.732 17.089 0 13.369 0 8.779S3.732.472 8.336.472c4.603 0 8.335 3.72 8.335 8.307a8.265 8.265 0 0 1-2.273 5.704ZM8.336 15.53c3.74 0 6.772-3.022 6.772-6.75 0-3.729-3.031-6.75-6.772-6.75S1.563 5.051 1.563 8.78c0 3.728 3.032 6.75 6.773 6.75Z"/></svg> 8264 <span class="visually-hidden">Search</span> 8265 </a><a class="header__icon text-current" href="https://myevergreen.com/customer_authentication/redirect?locale=en®ion_country=US"> 8266 <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M12 2a5 5 0 1 1 0 10 5 5 0 0 1 0-10zm0 1.429a3.571 3.571 0 1 0 0 7.142 3.571 3.571 0 0 0 0-7.142zm0 10c2.558 0 5.114.471 7.664 1.411A3.571 3.571 0 0 1 22 18.19v3.096c0 .394-.32.714-.714.714H2.714A.714.714 0 0 1 2 21.286V18.19c0-1.495.933-2.833 2.336-3.35 2.55-.94 5.106-1.411 7.664-1.411zm0 1.428c-2.387 0-4.775.44-7.17 1.324a2.143 2.143 0 0 0-1.401 2.01v2.38H20.57v-2.38c0-.898-.56-1.7-1.401-2.01-2.395-.885-4.783-1.324-7.17-1.324z"/></svg> 8267 <span class="visually-hidden">Log in</span> 8268 </a><a class="header__icon relative text-current" id="cart-icon" href="/cart" data-no-instant><svg width="24" height="24" viewBox="0 0 24 24" class="icon icon--cart" aria-hidden="true" focusable="false" role="presentation"><path fill="currentColor" d="M17 18a2 2 0 0 1 2 2 2 2 0 0 1-2 2 2 2 0 0 1-2-2c0-1.11.89-2 2-2M1 2h3.27l.94 2H20a1 1 0 0 1 1 1c0 .17-.05.34-.12.5l-3.58 6.47c-.34.61-1 1.03-1.75 1.03H8.1l-.9 1.63-.03.12a.25.25 0 0 0 .25.25H19v2H7a2 2 0 0 1-2-2c0-.35.09-.68.24-.96l1.36-2.45L3 4H1V2m6 16a2 2 0 0 1 2 2 2 2 0 0 1-2 2 2 2 0 0 1-2-2c0-1.11.89-2 2-2m9-7 2.78-5H6.14l2.36 5H16Z"/></svg><span class="visually-hidden">Cart</span><div id="cart-icon-bubble"></div> 8269 </a> 8270 </div><main-menu class="main-menu" data-menu-sensitivity="200"> 8271 <details class="main-menu__disclosure has-motion" open> 8272 <summary class="main-menu__toggle md:hidden"> 8273 <span class="main-menu__toggle-icon" aria-hidden="true"></span> 8274 <span class="visually-hidden">Menu</span> 8275 </summary> 8276 <div class="main-menu__content has-motion justify-center"> 8277 <nav aria-label="Primary"> 8278 <ul class="main-nav justify-center"><li><details class="js-mega-nav" > 8279 <summary class="main-nav__item--toggle relative js-nav-hover js-toggle"> 8280 <a class="main-nav__item main-nav__item--primary main-nav__item-content" href="/collections/sassafras_switch_mats"> 8281 Sassafras Switch Mats<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8282 </a> 8283 </summary><div class="main-nav__child mega-nav mega-nav--columns has-motion"> 8284 <div class="container mega-nav--promos-bottom"> 8285 <ul class="child-nav md:flex md:nav-gap-x-16"> 8286 <li class="md:hidden"> 8287 <button type="button" class="main-nav__item main-nav__item--back relative js-back"> 8288 <div class="main-nav__item-content text-start"> 8289 <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="m6.797 11.625 8.03-8.03 1.06 1.06-6.97 6.97 6.97 6.97-1.06 1.06z"/></svg> Back</div> 8290 </button> 8291 </li> 8292 8293 <li class="md:hidden"> 8294 <a href="/collections/sassafras_switch_mats" class="main-nav__item child-nav__item large-text main-nav__item-header">Sassafras Switch Mats</a> 8295 </li><li class="flex-auto"><nav-menu class="js-mega-nav"> 8296 <details open> 8297 <summary class="child-nav__item--toggle main-nav__item--toggle relative js-no-toggle-md"> 8298 <div class="main-nav__item-content"><a class="child-nav__item main-nav__item main-nav__item-content" href="/collections/sassafras_switch_mats" data-no-instant>BY TYPE<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8299 </a> 8300 </div> 8301 </summary> 8302 8303 <div class="disclosure__panel has-motion"><ul class="main-nav__grandchild has-motion " role="list" style=""><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/sassafras_base_mats">Sassafras Base Mats</a> 8304 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/sassafras_inserts">Sassafras Inserts</a> 8305 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/sassafras_bundle">Sassafras Bundles</a> 8306 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/sassafras_xl">Sassafras XL</a> 8307 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/sports_sassafras">Sports Sassafras</a> 8308 </li></ul> 8309 </div> 8310 </details> 8311 </nav-menu></li><li class="flex-auto"><nav-menu class="js-mega-nav"> 8312 <details open> 8313 <summary class="child-nav__item--toggle main-nav__item--toggle relative js-no-toggle-md"> 8314 <div class="main-nav__item-content"><a class="child-nav__item main-nav__item main-nav__item-content" href="/collections/sassafras_switch_mats" data-no-instant>BY SEASON<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8315 </a> 8316 </div> 8317 </summary> 8318 8319 <div class="disclosure__panel has-motion"><ul class="main-nav__grandchild has-motion " role="list" style=""><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/spring_sassafras">Spring Sassafras</a> 8320 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/summer_sassafras">Summer Sassafras</a> 8321 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/fall_sassafras">Fall Sassafras</a> 8322 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/winter_sassafras">Winter Sassafras</a> 8323 </li></ul> 8324 </div> 8325 </details> 8326 </nav-menu></li><li class="flex-auto"><nav-menu class="js-mega-nav"> 8327 <details open> 8328 <summary class="child-nav__item--toggle main-nav__item--toggle relative js-no-toggle-md"> 8329 <div class="main-nav__item-content"><a class="child-nav__item main-nav__item main-nav__item-content" href="/collections/sassafras_switch_mats" data-no-instant>BY HOLIDAY<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8330 </a> 8331 </div> 8332 </summary> 8333 8334 <div class="disclosure__panel has-motion"><ul class="main-nav__grandchild has-motion " role="list" style=""><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/valentines_day_sassafras">Valentine's Day Sassafras</a> 8335 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/mardi_gras_sassafras">Mardi Gras Sassafras</a> 8336 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/st-_patricks_day_sassafras">St. Patrick's Day Sassafras</a> 8337 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/easter_sassafras">Easter Sassafras</a> 8338 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/independence_day_sassafras">Independence Day Sassafras</a> 8339 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/halloween_sassafras">Halloween Sassafras</a> 8340 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/thanksgiving_sassafras">Thanksgiving Sassafras</a> 8341 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/christmas_sassafras">Christmas Sassafras </a> 8342 </li></ul> 8343 </div> 8344 </details> 8345 </nav-menu></li></ul><div class="child-promos" data-promo-count="3"> 8346 <div class="main-nav__promos mt-12 md:nav-mt-4 sm:nav-gap-x-6 sm:grid sm:nav-grid-cols-3 lg:grid-cols-3" 8347 style="--promo-text-color:#ffffff;--promo-min-height:110px;--promo-overlay-color: rgba(0, 0, 0, 0.0);"><a href="/collections/garden_flags" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8348 <img srcset="//myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=400, //myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=800 2x" src="//myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=800" 8349 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8350 width="800" 8351 height="214" 8352 8353 alt=""> 8354 </div></a><a href="/collections/sassafras_inserts" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8355 <img srcset="//myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=400, //myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=800 2x" src="//myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=800" 8356 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8357 width="800" 8358 height="214" 8359 8360 alt=""> 8361 </div></a><a href="/collections/deal-of-the-week" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8362 <img srcset="//myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=400, //myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=800 2x" src="//myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=800" 8363 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8364 width="800" 8365 height="214" 8366 8367 alt=""> 8368 </div></a></div> 8369 </div></div></div> 8370 </details></li><li>
8370<details class="js-mega-nav" > 8371 <summary class="main-nav__item--toggle relative js-nav-hover js-toggle"> 8372 <a class="main-nav__item main-nav__item--primary main-nav__item-content" href="/collections/doormats"> 8373 Doormats<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8374 </a> 8375 </summary><div class="main-nav__child mega-nav mega-nav--columns mega-nav--no-grandchildren has-motion"> 8376 <div class="container mega-nav--promos-bottom"> 8377 <ul class="child-nav md:grid md:nav-gap-x-16 md:nav-gap-y-4 md:grid-cols-3 lg:grid-cols-4"> 8378 <li class="md:hidden"> 8379 <button type="button" class="main-nav__item main-nav__item--back relative js-back"> 8380 <div class="main-nav__item-content text-start"> 8381 <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="m6.797 11.625 8.03-8.03 1.06 1.06-6.97 6.97 6.97 6.97-1.06 1.06z"/></svg> Back</div> 8382 </button> 8383 </li> 8384 8385 <li class="md:hidden"> 8386 <a href="/collections/doormats" class="main-nav__item child-nav__item large-text main-nav__item-header">Doormats</a> 8387 </li><li><a class="main-nav__item child-nav__item" 8388 href="/collections/coir_mats">Coir Mats 8389 </a></li><li><a class="main-nav__item child-nav__item" 8390 href="/collections/monogrammed_mats">Monogrammed Mats 8391 </a></li><li><a class="main-nav__item child-nav__item" 8392 href="/collections/washable_mats">Washable Mats 8393 </a></li><li><a class="main-nav__item child-nav__item" 8394 href="/collections/layering_mats">Layering Mats 8395 </a></li><li><a class="main-nav__item child-nav__item" 8396 href="/collections/pvc-trapper-mats">PVC Trapper Mats 8397 </a></li><li><a class="main-nav__item child-nav__item" 8398 href="/collections/anti-fatigue-mats">Anti-Fatigue Mats 8399 </a></li></ul><div class="child-promos" data-promo-count="3"> 8400 <div class="main-nav__promos mt-12 md:nav-mt-4 sm:nav-gap-x-6 sm:grid sm:nav-grid-cols-3 lg:grid-cols-3" 8401 style="--promo-text-color:#ffffff;--promo-min-height:110px;--promo-overlay-color: rgba(0, 0, 0, 0.0);"><a href="/collections/garden_flags" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8402 <img srcset="//myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=400, //myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=800 2x" src="//myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=800" 8403 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8404 width="800" 8405 height="214" 8406 8407 alt=""> 8408 </div></a><a href="/collections/sassafras_inserts" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8409 <img srcset="//myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=400, //myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=800 2x" src="//myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=800" 8410 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8411 width="800" 8412 height="214" 8413 8414 alt=""> 8415 </div></a><a href="/collections/deal-of-the-week" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8416 <img srcset="//myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=400, //myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=800 2x" src="//myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=800" 8417 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8418 width="800" 8419 height="214" 8420 8421 alt=""> 8422 </div></a></div> 8423 </div></div></div> 8424 </details></li><li>
8424<details class="js-mega-nav" > 8425 <summary class="main-nav__item--toggle relative js-nav-hover js-toggle"> 8426 <a class="main-nav__item main-nav__item--primary main-nav__item-content" href="/collections/flags"> 8427 Flags<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8428 </a> 8429 </summary><div class="main-nav__child mega-nav mega-nav--columns has-motion"> 8430 <div class="container mega-nav--promos-bottom"> 8431 <ul class="child-nav md:grid md:nav-gap-x-16 md:nav-gap-y-4 md:grid-cols-3 lg:grid-cols-4"> 8432 <li class="md:hidden"> 8433 <button type="button" class="main-nav__item main-nav__item--back relative js-back"> 8434 <div class="main-nav__item-content text-start"> 8435 <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="m6.797 11.625 8.03-8.03 1.06 1.06-6.97 6.97 6.97 6.97-1.06 1.06z"/></svg> Back</div> 8436 </button> 8437 </li> 8438 8439 <li class="md:hidden"> 8440 <a href="/collections/flags" class="main-nav__item child-nav__item large-text main-nav__item-header">Flags</a> 8441 </li><li><nav-menu class="js-mega-nav"> 8442 <details open> 8443 <summary class="child-nav__item--toggle main-nav__item--toggle relative js-no-toggle-md"> 8444 <div class="main-nav__item-content"><a class="child-nav__item main-nav__item main-nav__item-content" href="/collections/flags_by_size_-_type" data-no-instant>BY SIZE & TYPE<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8445 </a> 8446 </div> 8447 </summary> 8448 8449 <div class="disclosure__panel has-motion"><ul class="main-nav__grandchild has-motion " role="list" style=""><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/garden_flags">Garden Flags</a> 8450 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/house_flags">House Flags</a> 8451 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/estate_flags">Estate Flags</a> 8452 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/everlasting_impressions">Everlasting Impressions</a> 8453 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/banners_-_bunting">Banners & Bunting</a> 8454 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/flag_bundles">Flag Bundles</a> 8455 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/sports_flags">Sports Flags</a> 8456 </li></ul> 8457 </div> 8458 </details> 8459 </nav-menu></li><li><nav-menu class="js-mega-nav"> 8460 <details open> 8461 <summary class="child-nav__item--toggle main-nav__item--toggle relative js-no-toggle-md"> 8462 <div class="main-nav__item-content"><a class="child-nav__item main-nav__item main-nav__item-content" href="/collections/flags_by_season" data-no-instant>BY SEASON<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8463 </a> 8464 </div> 8465 </summary> 8466 8467 <div class="disclosure__panel has-motion"><ul class="main-nav__grandchild has-motion " role="list" style=""><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/spring_flags">Spring Flags</a> 8468 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/summer_flags">Summer Flags</a> 8469 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/fall_flags">Fall Flags</a> 8470 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/winter_flags">Winter Flags</a> 8471 </li></ul> 8472 </div> 8473 </details> 8474 </nav-menu></li><li><nav-menu class="js-mega-nav"> 8475 <details open> 8476 <summary class="child-nav__item--toggle main-nav__item--toggle relative js-no-toggle-md"> 8477 <div class="main-nav__item-content"><a class="child-nav__item main-nav__item main-nav__item-content" href="/collections/flags" data-no-instant>BY HOLIDAY<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8478 </a> 8479 </div> 8480 </summary> 8481 8482 <div class="disclosure__panel has-motion"><ul class="main-nav__grandchild has-motion " role="list" style=""><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/valentines_day_flags">Valentine's Day Flags</a> 8483 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/mardi_gras_flags">Mardi Gras Flags</a> 8484 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/st-_patricks_day_flags">St. Patrick's Day Flags</a> 8485 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/easter_flags">Easter Flags</a> 8486 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/independence_day_flags">Independence Day Flags</a> 8487 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/halloween_flags">Halloween Flags</a> 8488 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/thanksgiving_flags">Thanksgiving Flags</a> 8489 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/christmas_flags">Christmas Flags</a> 8490 </li></ul> 8491 </div> 8492 </details> 8493 </nav-menu></li><li><nav-menu class="js-mega-nav"> 8494 <details open> 8495 <summary class="child-nav__item--toggle main-nav__item--toggle relative js-no-toggle-md"> 8496 <div class="main-nav__item-content"><a class="child-nav__item main-nav__item main-nav__item-content" href="/collections/accessories" data-no-instant>FLAG ACCESSORIES<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8497 </a> 8498 </div> 8499 </summary> 8500 8501 <div class="disclosure__panel has-motion"><ul class="main-nav__grandchild has-motion " role="list" style=""><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/flag_stands">Flag Stands</a> 8502 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/flag_poles">Flag Poles</a> 8503 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/flag_brackets">Flag Brackets</a> 8504 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/products/01245" aria-current="page">Flag Organizer</a> 8505 </li></ul> 8506 </div> 8507 </details> 8508 </nav-menu></li></ul><div class="child-promos" data-promo-count="3"> 8509 <div class="main-nav__promos mt-12 md:nav-mt-4 sm:nav-gap-x-6 sm:grid sm:nav-grid-cols-3 lg:grid-cols-3" 8510 style="--promo-text-color:#ffffff;--promo-min-height:110px;--promo-overlay-color: rgba(0, 0, 0, 0.0);"><a href="/collections/garden_flags" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8511 <img srcset="//myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=400, //myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=800 2x" src="//myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=800" 8512 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8513 width="800" 8514 height="214" 8515 8516 alt=""> 8517 </div></a><a href="/collections/sassafras_inserts" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8518 <img srcset="//myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=400, //myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=800 2x" src="//myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=800" 8519 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8520 width="800" 8521 height="214" 8522 8523 alt=""> 8524 </div></a><a href="/collections/deal-of-the-week" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8525 <img srcset="//myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=400, //myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=800 2x" src="//myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=800" 8526 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8527 width="800" 8528 height="214" 8529 8530 alt=""> 8531 </div></a></div> 8532 </div></div></div> 8533 </details></li><li>
8533<details class="js-mega-nav" > 8534 <summary class="main-nav__item--toggle relative js-nav-hover js-toggle"> 8535 <a class="main-nav__item main-nav__item--primary main-nav__item-content" href="/collections/outdoor_decor"> 8536 Outdoor Décor<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8537 </a> 8538 </summary><div class="main-nav__child mega-nav mega-nav--columns mega-nav--no-grandchildren has-motion"> 8539 <div class="container mega-nav--promos-bottom"> 8540 <ul class="child-nav md:grid md:nav-gap-x-16 md:nav-gap-y-4 md:grid-cols-3 lg:grid-cols-4"> 8541 <li class="md:hidden"> 8542 <button type="button" class="main-nav__item main-nav__item--back relative js-back"> 8543 <div class="main-nav__item-content text-start"> 8544 <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="m6.797 11.625 8.03-8.03 1.06 1.06-6.97 6.97 6.97 6.97-1.06 1.06z"/></svg> Back</div> 8545 </button> 8546 </li> 8547 8548 <li class="md:hidden"> 8549 <a href="/collections/outdoor_decor" class="main-nav__item child-nav__item large-text main-nav__item-header">Outdoor Décor</a> 8550 </li><li><a class="main-nav__item child-nav__item" 8551 href="/collections/door_decor">Door Décor 8552 </a></li><li><a class="main-nav__item child-nav__item" 8553 href="/collections/mailbox_covers">Mailbox Covers 8554 </a></li><li><a class="main-nav__item child-nav__item" 8555 href="/collections/pillow_covers">Pillow Covers 8556 </a></li><li><a class="main-nav__item child-nav__item" 8557 href="/pages/giddy-the-goose">Giddy The Porch Goose 8558 </a></li><li><a class="main-nav__item child-nav__item" 8559 href="/collections/balloon_spinners">Balloon Spinners 8560 </a></li><li><a class="main-nav__item child-nav__item" 8561 href="/collections/porch_leaners">Porch Leaners 8562 </a></li><li><a class="main-nav__item child-nav__item" 8563 href="/collections/windsocks">Windsocks 8564 </a></li><li><a class="main-nav__item child-nav__item" 8565 href="/collections/garden_stakes">Yard Signs & Garden Stakes 8566 </a></li><li><a class="main-nav__item child-nav__item" 8567 href="/collections/chimes_mobiles_-_bells">Chimes, Mobiles & Bells 8568 </a></li><li><a class="main-nav__item child-nav__item" 8569 href="/collections/door-garage-covers">Door & Garage Covers 8570 </a></li><li><a class="main-nav__item child-nav__item" 8571 href="/collections/porch_decor_and_more">Porch Décor and More 8572 </a></li></ul><div class="child-promos" data-promo-count="3"> 8573 <div class="main-nav__promos mt-12 md:nav-mt-4 sm:nav-gap-x-6 sm:grid sm:nav-grid-cols-3 lg:grid-cols-3" 8574 style="--promo-text-color:#ffffff;--promo-min-height:110px;--promo-overlay-color: rgba(0, 0, 0, 0.0);"><a href="/collections/garden_flags" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8575 <img srcset="//myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=400, //myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=800 2x" src="//myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=800" 8576 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8577 width="800" 8578 height="214" 8579 8580 alt=""> 8581 </div></a><a href="/collections/sassafras_inserts" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8582 <img srcset="//myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=400, //myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=800 2x" src="//myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=800" 8583 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8584 width="800" 8585 height="214" 8586 8587 alt=""> 8588 </div></a><a href="/collections/deal-of-the-week" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8589 <img srcset="//myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=400, //myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=800 2x" src="//myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=800" 8590 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8591 width="800" 8592 height="214" 8593 8594 alt=""> 8595 </div></a></div> 8596 </div></div></div> 8597 </details></li><li>
8597<details class="js-mega-nav" > 8598 <summary class="main-nav__item--toggle relative js-nav-hover js-toggle"> 8599 <a class="main-nav__item main-nav__item--primary main-nav__item-content" href="/collections/gifts"> 8600 Gifts<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8601 </a> 8602 </summary><div class="main-nav__child mega-nav mega-nav--columns has-motion"> 8603 <div class="container mega-nav--promos-bottom"> 8604 <ul class="child-nav md:flex md:nav-gap-x-16"> 8605 <li class="md:hidden"> 8606 <button type="button" class="main-nav__item main-nav__item--back relative js-back"> 8607 <div class="main-nav__item-content text-start"> 8608 <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="m6.797 11.625 8.03-8.03 1.06 1.06-6.97 6.97 6.97 6.97-1.06 1.06z"/></svg> Back</div> 8609 </button> 8610 </li> 8611 8612 <li class="md:hidden"> 8613 <a href="/collections/gifts" class="main-nav__item child-nav__item large-text main-nav__item-header">Gifts</a> 8614 </li><li class="flex-auto"><nav-menu class="js-mega-nav"> 8615 <details open> 8616 <summary class="child-nav__item--toggle main-nav__item--toggle relative js-no-toggle-md"> 8617 <div class="main-nav__item-content"><a class="child-nav__item main-nav__item main-nav__item-content" href="/collections/gifts" data-no-instant>BY TYPE<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8618 </a> 8619 </div> 8620 </summary> 8621 8622 <div class="disclosure__panel has-motion"><ul class="main-nav__grandchild has-motion " role="list" style=""><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/umbrellas">Umbrellas</a> 8623 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/totes">Totes</a> 8624 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/kites">Kites</a> 8625 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/gift_sets">Gift Sets</a> 8626 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/tabletop_goose">Tabletop Goose</a> 8627 </li></ul> 8628 </div> 8629 </details> 8630 </nav-menu></li><li class="flex-auto"><nav-menu class="js-mega-nav"> 8631 <details open> 8632 <summary class="child-nav__item--toggle main-nav__item--toggle relative js-no-toggle-md"> 8633 <div class="main-nav__item-content"><a class="child-nav__item main-nav__item main-nav__item-content" href="/collections/drinkware" data-no-instant>DRINKWARE<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8634 </a> 8635 </div> 8636 </summary> 8637 8638 <div class="disclosure__panel has-motion"><ul class="main-nav__grandchild has-motion " role="list" style=""><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/coffee_cups">Coffee Cups</a> 8639 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/travel_drinkware">Travel Drinkware</a> 8640 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/wine_glasses">Wine Glasses</a> 8641 </li></ul> 8642 </div> 8643 </details> 8644 </nav-menu></li><li class="flex-auto"><nav-menu class="js-mega-nav"> 8645 <details open> 8646 <summary class="child-nav__item--toggle main-nav__item--toggle relative js-no-toggle-md"> 8647 <div class="main-nav__item-content"><a class="child-nav__item main-nav__item main-nav__item-content" href="/collections/novelty-signs" data-no-instant>NOVELTY SIGNS<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8648 </a> 8649 </div> 8650 </summary> 8651 8652 <div class="disclosure__panel has-motion"><ul class="main-nav__grandchild has-motion " role="list" style=""><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/wood_box_signs">Wood Block Signs</a> 8653 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/wood_wall_signs">Wood Wall Signs</a> 8654 </li></ul> 8655 </div> 8656 </details> 8657 </nav-menu></li></ul><div class="child-promos" data-promo-count="3"> 8658 <div class="main-nav__promos mt-12 md:nav-mt-4 sm:nav-gap-x-6 sm:grid sm:nav-grid-cols-3 lg:grid-cols-3" 8659 style="--promo-text-color:#ffffff;--promo-min-height:110px;--promo-overlay-color: rgba(0, 0, 0, 0.0);"><a href="/collections/garden_flags" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8660 <img srcset="//myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=400, //myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=800 2x" src="//myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=800" 8661 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8662 width="800" 8663 height="214" 8664 8665 alt=""> 8666 </div></a><a href="/collections/sassafras_inserts" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8667 <img srcset="//myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=400, //myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=800 2x" src="//myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=800" 8668 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8669 width="800" 8670 height="214" 8671 8672 alt=""> 8673 </div></a><a href="/collections/deal-of-the-week" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8674 <img srcset="//myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=400, //myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=800 2x" src="//myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=800" 8675 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8676 width="800" 8677 height="214" 8678 8679 alt=""> 8680 </div></a></div> 8681 </div></div></div> 8682 </details></li><li>
8682<details class="js-mega-nav" > 8683 <summary class="main-nav__item--toggle relative js-nav-hover js-toggle"> 8684 <a class="main-nav__item main-nav__item--primary main-nav__item-content" href="/collections/shop_by_season"> 8685 Shop By Season<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8686 </a> 8687 </summary><div class="main-nav__child mega-nav mega-nav--columns has-motion"> 8688 <div class="container mega-nav--promos-bottom"> 8689 <ul class="child-nav md:flex md:nav-gap-x-16"> 8690 <li class="md:hidden"> 8691 <button type="button" class="main-nav__item main-nav__item--back relative js-back"> 8692 <div class="main-nav__item-content text-start"> 8693 <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="m6.797 11.625 8.03-8.03 1.06 1.06-6.97 6.97 6.97 6.97-1.06 1.06z"/></svg> Back</div> 8694 </button> 8695 </li> 8696 8697 <li class="md:hidden"> 8698 <a href="/collections/shop_by_season" class="main-nav__item child-nav__item large-text main-nav__item-header">Shop By Season</a> 8699 </li><li class="flex-auto"><nav-menu class="js-mega-nav"> 8700 <details open> 8701 <summary class="child-nav__item--toggle main-nav__item--toggle relative js-no-toggle-md"> 8702 <div class="main-nav__item-content"><a class="child-nav__item main-nav__item main-nav__item-content" href="/collections/by_holiday" data-no-instant>HOLIDAY DÃCOR<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8703 </a> 8704 </div> 8705 </summary> 8706 8707 <div class="disclosure__panel has-motion"><ul class="main-nav__grandchild has-motion " role="list" style=""><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/valentines_day">Valentines Day</a> 8708 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/mardi_gras">Mardi Gras</a> 8709 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/st-_patricks_day">St. Patrick's Day</a> 8710 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/easter">Easter</a> 8711 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/independence_day">Independence Day</a> 8712 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/halloween">Halloween</a> 8713 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/thanksgiving">Thanksgiving</a> 8714 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/christmas">Christmas</a> 8715 </li></ul> 8716 </div> 8717 </details> 8718 </nav-menu></li><li class="flex-auto"><nav-menu class="js-mega-nav"> 8719 <details open> 8720 <summary class="child-nav__item--toggle main-nav__item--toggle relative js-no-toggle-md"> 8721 <div class="main-nav__item-content"><a class="child-nav__item main-nav__item main-nav__item-content" href="/collections/shop_by_season" data-no-instant>SEASONAL DÃCOR<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8722 </a> 8723 </div> 8724 </summary> 8725 8726 <div class="disclosure__panel has-motion"><ul class="main-nav__grandchild has-motion " role="list" style=""><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/spring">Spring</a> 8727 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/summer">Summer</a> 8728 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/fall">Fall</a> 8729 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/winter">Winter</a> 8730 </li></ul> 8731 </div> 8732 </details> 8733 </nav-menu></li><li class="flex-auto"><nav-menu class="js-mega-nav"> 8734 <details open> 8735 <summary class="child-nav__item--toggle main-nav__item--toggle relative js-no-toggle-md"> 8736 <div class="main-nav__item-content"><a class="child-nav__item main-nav__item main-nav__item-content" href="/collections/shop_by_theme" data-no-instant>SHOP BY THEME<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8737 </a> 8738 </div> 8739 </summary> 8740 8741 <div class="disclosure__panel has-motion"><ul class="main-nav__grandchild has-motion " role="list" style=""><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/patriotic">Patriotic</a> 8742 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/coastal">Coastal Charm</a> 8743 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/inspirational">Inspirational</a> 8744 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/pet_central">Pet Central</a> 8745 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/fantasy">Fantasy</a> 8746 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/farm-country">Farm & Country</a> 8747 </li><li><a class="grandchild-nav__item main-nav__item relative" href="/collections/floral">Floral</a> 8748 </li></ul> 8749 </div> 8750 </details> 8751 </nav-menu></li></ul><div class="child-promos" data-promo-count="3"> 8752 <div class="main-nav__promos mt-12 md:nav-mt-4 sm:nav-gap-x-6 sm:grid sm:nav-grid-cols-3 lg:grid-cols-3" 8753 style="--promo-text-color:#ffffff;--promo-min-height:110px;--promo-overlay-color: rgba(0, 0, 0, 0.0);"><a href="/collections/garden_flags" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8754 <img srcset="//myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=400, //myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=800 2x" src="//myevergreen.com/cdn/shop/files/garden-flag-promo_1.png?v=1748460096&width=800" 8755 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8756 width="800" 8757 height="214" 8758 8759 alt=""> 8760 </div></a><a href="/collections/sassafras_inserts" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8761 <img srcset="//myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=400, //myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=800 2x" src="//myevergreen.com/cdn/shop/files/sassafras-promo_1.png?v=1748460096&width=800" 8762 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8763 width="800" 8764 height="214" 8765 8766 alt=""> 8767 </div></a><a href="/collections/deal-of-the-week" class="promo hover:grow-media overflow-hidden relative flex p-4 justify-center items-center text-center"><div class="media absolute top-0 left-0 w-full h-full"> 8768 <img srcset="//myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=400, //myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=800 2x" src="//myevergreen.com/cdn/shop/files/dotw-nav-banner_1.jpg?v=1749050204&width=800" 8769 class="img-fit" style="object-position: 50.0% 50.0%" loading="lazy" 8770 width="800" 8771 height="214" 8772 8773 alt=""> 8774 </div></a></div> 8775 </div></div></div> 8776 </details></li><li>
8776<details> 8777 <summary class="main-nav__item--toggle relative js-nav-hover js-toggle"> 8778 <a class="main-nav__item main-nav__item--primary main-nav__item-content" href="/collections/sale"> 8779 Sale<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8780 </a> 8781 </summary><div class="main-nav__child has-motion"> 8782 8783 <ul class="child-nav child-nav--dropdown"> 8784 <li class="md:hidden"> 8785 <button type="button" class="main-nav__item main-nav__item--back relative js-back"> 8786 <div class="main-nav__item-content text-start"> 8787 <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="m6.797 11.625 8.03-8.03 1.06 1.06-6.97 6.97 6.97 6.97-1.06 1.06z"/></svg> Back</div> 8788 </button> 8789 </li> 8790 8791 <li class="md:hidden"> 8792 <a href="/collections/sale" class="main-nav__item child-nav__item large-text main-nav__item-header">Sale</a> 8793 </li><li><a class="main-nav__item child-nav__item" 8794 href="/collections/almost-gone">Almost Gone 8795 </a></li><li><a class="main-nav__item child-nav__item" 8796 href="/collections/sale">Shop All Sale 8797 </a></li><li><a class="main-nav__item child-nav__item" 8798 href="/collections/deal-of-the-week">Deal Of The Week 8799 </a></li></ul></div> 8800 </details></li></ul> 8801 </nav></div> 8802 </details> 8803 </main-menu></header> 8804</store-header><link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/navigation-mega-columns.css?v=119816575673477993541781124413" media="print" onload="this.media='all'"><link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/promos.css?v=127548740392444850871781124414" media="print" onload="this.media='all'"> 8805 <link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/navigation-promos.css?v=43827163382767200201781124410" media="print" onload="this.media='all'"> 8806
8807<script type="application/ld+json"> 8808 { 8809 "@context": "http://schema.org", 8810 "@type": "Organization", 8811 "name": "Evergreen", 8812 "logo": "https:\/\/myevergreen.com\/cdn\/shop\/files\/evergreen-logo-full-color.svg?v=1718829572\u0026width=351", 8813 8814 "sameAs": [ 8815 8816"https:\/\/www.facebook.com\/shopmyevergreen\/","https:\/\/www.instagram.com\/shopmyevergreen\/","https:\/\/www.pinterest.com\/shopmyevergreen\/","https:\/\/www.linkedin.com\/company\/evergreen-enterprises" 8817 ], 8818 "url": "https:\/\/myevergreen.com" 8819 } 8820</script>
8820 8821 8822 8823<style> #shopify-section-sections--21510771834934__header {z-index: 100;} #shopify-section-sections--21510771834934__header .main-nav__item--toggle .icon {display: none;} @media (min-width: 769px) {#shopify-section-sections--21510771834934__header .main-nav__item--primary {margin: 0 1.4rem; }} </style></div><section id="shopify-section-sections--21510771834934__custom_liquid_T8QGjV" class="shopify-section shopify-section-group-header-group cc-custom-liquid"><div class="section relative section--full-width section--padded-xsmall border-bottom"><ul class="beard_items"> 8824 8825 <li><a href="/collections/new-arrivals" style="color: #222222;">New Arrivals</a></li> 8826 8827 <li><a href="/pages/giddy-the-goose" style="color: #222222;">Giddy The Porch Goose</a></li> 8828 8829 <li><a href="/pages/whimsy-maxxing" style="color: #222222;">Whimsical Favorites</a></li> 8830 8831 <li><a href="/collections/fall-and-halloween" style="color: #222222;">Halloween</a></li> 8832 8833 <li><a href="/collections/house_flags" style="color: #222222;">House Flags</a></li> 8834 8835 <li><a href="/collections/deal-of-the-week" style="color: #222222;">Deal Of The Week</a></li> 8836 8837 </ul></div> 8838 8839 8840<style> #shopify-section-sections--21510771834934__custom_liquid_T8QGjV {background-color: #f1f1ef;} #shopify-section-sections--21510771834934__custom_liquid_T8QGjV .beard_menu {padding: 10px 10%; margin-top: -8px; margin-bottom: -8px;} #shopify-section-sections--21510771834934__custom_liquid_T8QGjV .beard_items {list-style: none; padding: 0; display: flex; justify-content: space-evenly; max-width: 1260px; margin-top: 5px; margin-left: auto; margin-right: auto; font-weight: bold;} #shopify-section-sections--21510771834934__custom_liquid_T8QGjV a:hover {color: #107661;} @media screen and (max-width: 1024px) {#shopify-section-sections--21510771834934__custom_liquid_T8QGjV {display: none !important; }} </style></section> 8841<!-- END sections: header-group --><main id="main-content"><div class="container product-breadcrumbs">
8841<script type="application/ld+json"> 8842 { 8843 "@context": "https://schema.org", 8844 "@type": "BreadcrumbList", 8845 "itemListElement": [ 8846 { 8847 "@type": "ListItem", 8848 "position": 1, 8849 "name": "Home", 8850 "item": "https:\/\/myevergreen.com\/" 8851 },{ 8852 "@type": "ListItem", 8853 "position": 2, 8854 "name": "Flag Organizer", 8855 "item": "https:\/\/myevergreen.com\/products\/01245" 8856 }] 8857 } 8858 </script>
8858 8859<nav class="breadcrumbs flex justify-between w-full" aria-label="Breadcrumbs"> 8860 <ol class="breadcrumbs-list flex has-ltr-icon"> 8861 <li class="flex items-center"> 8862 <a class="breadcrumbs-list__link" href="/">Home</a> <svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="m9.693 4.5 7.5 7.5-7.5 7.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 8863 </li><li class="flex items-center"> 8864 <a class="breadcrumbs-list__link" href="/products/01245" aria-current="page">Flag Organizer</a> 8865 </li></ol></nav> 8866 8867 </div><div id="shopify-section-template--21510772129846__main" class="shopify-section cc-main-product product-main"> 8868<link href="//myevergreen.com/cdn/shop/t/101/assets/product.css?v=39469541301224235251781124412" rel="stylesheet" type="text/css" media="all" /> 8869<link href="//myevergreen.com/cdn/shop/t/101/assets/product-page.css?v=178784697000508416221781124410" rel="stylesheet" type="text/css" media="all" />
8870<script src="//myevergreen.com/cdn/shop/t/101/assets/product-message.js?v=109559992369320503431781124414" defer="defer"></script>
8870 8871 <link href="//myevergreen.com/cdn/shop/t/101/assets/product-message.css?v=64872734686806679821781124414" rel="stylesheet" type="text/css" media="all" /> 8872<link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/media-gallery.css?v=40714777479435031101781124410">
8872<script src="//myevergreen.com/cdn/shop/t/101/assets/product-form.js?v=131379636371976267351781124412" defer="defer"></script>
8872<style data-shopify>.media-gallery__main .media-xr-button { display: none; } 8873 .active .media-xr-button:not([data-shopify-xr-hidden]) { display: block; }</style><div class="container"> 8874 <div class="product js-product" data-section="template--21510772129846__main"> 8875 <div id="product-media" class="product-media product-media--slider"> 8876
8877<script src="//myevergreen.com/cdn/shop/t/101/assets/media-gallery.js?v=168794727851445643501781124411" defer="defer"></script>
8877<media-gallery 8878 class="media-gallery" 8879 role="region" 8880 8881 data-layout="slider" 8882 8883 data-zoom-trigger="hover" 8884 8885 8886 8887 8888 aria-label="Gallery Viewer" 8889 style="--gallery-bg-color:#fafafa;--gallery-border-color:#eeeeee;"> 8890 <div class="media-gallery__status visually-hidden" role="status"></div> 8891 8892 <div class="media-gallery__viewer relative"> 8893 <ul class="media-viewer flex" id="gallery-viewer" role="list" tabindex="0"><li class="media-viewer__item is-current-variant" data-media-id="30261426946102" data-media-type="image"><div class="media relative" style="padding-top: 100%;"><a href="//myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=1500" class="media--cover media--zoom media--zoom-not-loaded inline-flex overflow-hidden absolute top-0 left-0 w-full h-full js-zoom-link" target="_blank"><picture> 8894 <source srcset="//myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=690 690w, //myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=800 800w" 8895 media="(max-width: 600px)" 8896 width="800" 8897 height="800"><img srcset="//myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=640 640w, //myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=900 900w, //myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=1214 1214w" sizes="(min-width: 1718px) 800px, (min-width: 1280px) calc(50vw), (min-width: 1024px) calc(50vw), (min-width: 769px) calc(50vw - 64px), (min-width: 600px) calc(100vw - 64px), calc(100vw - 40px)" src="//myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=1214" 8898 class="product-image img-fit img-fit--contain w-full" loading="eager" 8899 width="1214" 8900 height="1214" 8901 8902 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_c9b37276-4780-4d3f-baf1-60c599eda033"></picture> 8903<img class="zoom-image zoom-image--contain top-0 absolute left-0 right-0 pointer-events-none js-zoom-image no-js-hidden" 8904 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_c9b37276-4780-4d3f-baf1-60c599eda033" 8905 src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201500%201500'%3E%3C/svg%3E" loading="lazy" 8906 data-src="//myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=1500" width="1500" height="1500" 8907 data-original-width="3000" data-original-height="3000"> 8908 </a></div> 8909</li><li class="media-viewer__item" data-media-id="30261426978870" data-media-type="image"><div class="media relative" style="padding-top: 100%;"><a href="//myevergreen.com/cdn/shop/files/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307&width=1500" class="media--cover media--zoom media--zoom-not-loaded inline-flex overflow-hidden absolute top-0 left-0 w-full h-full js-zoom-link" target="_blank"><picture> 8910 <source srcset="//myevergreen.com/cdn/shop/files/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307&width=690 690w, //myevergreen.com/cdn/shop/files/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307&width=800 800w" 8911 media="(max-width: 600px)" 8912 width="800" 8913 height="800"><img srcset="//myevergreen.com/cdn/shop/files/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307&width=640 640w, //myevergreen.com/cdn/shop/files/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307&width=900 900w, //myevergreen.com/cdn/shop/files/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307&width=1214 1214w" sizes="(min-width: 1718px) 800px, (min-width: 1280px) calc(50vw), (min-width: 1024px) calc(50vw), (min-width: 769px) calc(50vw - 64px), (min-width: 600px) calc(100vw - 64px), calc(100vw - 40px)" src="//myevergreen.com/cdn/shop/files/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307&width=1214" 8914 class="product-image img-fit img-fit--contain w-full" loading="lazy" 8915 width="1214" 8916 height="1214" 8917 8918 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_4bdb1383-1b62-4776-919e-642fbf3de913"></picture> 8919<img class="zoom-image zoom-image--contain top-0 absolute left-0 right-0 pointer-events-none js-zoom-image no-js-hidden" 8920 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_4bdb1383-1b62-4776-919e-642fbf3de913" 8921 src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201500%201500'%3E%3C/svg%3E" loading="lazy" 8922 data-src="//myevergreen.com/cdn/shop/files/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307&width=1500" width="1500" height="1500" 8923 data-original-width="3000" data-original-height="3000"> 8924 </a></div> 8925</li><li class="media-viewer__item" data-media-id="30261427011638" data-media-type="image"><div class="media relative" style="padding-top: 100%;"><a href="//myevergreen.com/cdn/shop/files/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307&width=1500" class="media--cover media--zoom media--zoom-not-loaded inline-flex overflow-hidden absolute top-0 left-0 w-full h-full js-zoom-link" target="_blank"><picture> 8926 <source srcset="//myevergreen.com/cdn/shop/files/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307&width=690 690w, //myevergreen.com/cdn/shop/files/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307&width=800 800w" 8927 media="(max-width: 600px)" 8928 width="800" 8929 height="800"><img srcset="//myevergreen.com/cdn/shop/files/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307&width=640 640w, //myevergreen.com/cdn/shop/files/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307&width=900 900w, //myevergreen.com/cdn/shop/files/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307&width=1214 1214w" sizes="(min-width: 1718px) 800px, (min-width: 1280px) calc(50vw), (min-width: 1024px) calc(50vw), (min-width: 769px) calc(50vw - 64px), (min-width: 600px) calc(100vw - 64px), calc(100vw - 40px)" src="//myevergreen.com/cdn/shop/files/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307&width=1214" 8930 class="product-image img-fit img-fit--contain w-full" loading="lazy" 8931 width="1214" 8932 height="1214" 8933 8934 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_9086bef2-c4ed-4a4d-a86f-74fa581e2583"></picture> 8935<img class="zoom-image zoom-image--contain top-0 absolute left-0 right-0 pointer-events-none js-zoom-image no-js-hidden" 8936 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_9086bef2-c4ed-4a4d-a86f-74fa581e2583" 8937 src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201500%201500'%3E%3C/svg%3E" loading="lazy" 8938 data-src="//myevergreen.com/cdn/shop/files/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307&width=1500" width="1500" height="1500" 8939 data-original-width="3000" data-original-height="3000"> 8940 </a></div> 8941</li><li class="media-viewer__item" data-media-id="30261427044406" data-media-type="image"><div class="media relative" style="padding-top: 100%;"><a href="//myevergreen.com/cdn/shop/files/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307&width=1500" class="media--cover media--zoom media--zoom-not-loaded inline-flex overflow-hidden absolute top-0 left-0 w-full h-full js-zoom-link" target="_blank"><picture> 8942 <source srcset="//myevergreen.com/cdn/shop/files/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307&width=690 690w, //myevergreen.com/cdn/shop/files/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307&width=800 800w" 8943 media="(max-width: 600px)" 8944 width="800" 8945 height="800"><img srcset="//myevergreen.com/cdn/shop/files/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307&width=640 640w, //myevergreen.com/cdn/shop/files/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307&width=900 900w, //myevergreen.com/cdn/shop/files/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307&width=1214 1214w" sizes="(min-width: 1718px) 800px, (min-width: 1280px) calc(50vw), (min-width: 1024px) calc(50vw), (min-width: 769px) calc(50vw - 64px), (min-width: 600px) calc(100vw - 64px), calc(100vw - 40px)" src="//myevergreen.com/cdn/shop/files/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307&width=1214" 8946 class="product-image img-fit img-fit--contain w-full" loading="lazy" 8947 width="1214" 8948 height="1214" 8949 8950 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_50c16b2e-148e-4117-a4f7-34cb131df641"></picture> 8951<img class="zoom-image zoom-image--contain top-0 absolute left-0 right-0 pointer-events-none js-zoom-image no-js-hidden" 8952 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_50c16b2e-148e-4117-a4f7-34cb131df641" 8953 src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201500%201500'%3E%3C/svg%3E" loading="lazy" 8954 data-src="//myevergreen.com/cdn/shop/files/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307&width=1500" width="1500" height="1500" 8955 data-original-width="3000" data-original-height="3000"> 8956 </a></div> 8957</li><li class="media-viewer__item" data-media-id="30261427077174" data-media-type="image"><div class="media relative" style="padding-top: 100%;"><a href="//myevergreen.com/cdn/shop/files/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307&width=1500" class="media--cover media--zoom media--zoom-not-loaded inline-flex overflow-hidden absolute top-0 left-0 w-full h-full js-zoom-link" target="_blank"><picture> 8958 <source srcset="//myevergreen.com/cdn/shop/files/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307&width=690 690w, //myevergreen.com/cdn/shop/files/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307&width=800 800w" 8959 media="(max-width: 600px)" 8960 width="800" 8961 height="800"><img srcset="//myevergreen.com/cdn/shop/files/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307&width=640 640w, //myevergreen.com/cdn/shop/files/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307&width=900 900w, //myevergreen.com/cdn/shop/files/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307&width=1214 1214w" sizes="(min-width: 1718px) 800px, (min-width: 1280px) calc(50vw), (min-width: 1024px) calc(50vw), (min-width: 769px) calc(50vw - 64px), (min-width: 600px) calc(100vw - 64px), calc(100vw - 40px)" src="//myevergreen.com/cdn/shop/files/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307&width=1214" 8962 class="product-image img-fit img-fit--contain w-full" loading="lazy" 8963 width="1214" 8964 height="1214" 8965 8966 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_78d85916-fa40-48bb-bb77-5a10608cfb8a"></picture> 8967<img class="zoom-image zoom-image--contain top-0 absolute left-0 right-0 pointer-events-none js-zoom-image no-js-hidden" 8968 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_78d85916-fa40-48bb-bb77-5a10608cfb8a" 8969 src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201500%201500'%3E%3C/svg%3E" loading="lazy" 8970 data-src="//myevergreen.com/cdn/shop/files/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307&width=1500" width="1500" height="1500" 8971 data-original-width="3000" data-original-height="3000"> 8972 </a></div> 8973</li><li class="media-viewer__item" data-media-id="32716987531318" data-media-type="image"><div class="media relative" style="padding-top: 100%;"><a href="//myevergreen.com/cdn/shop/files/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683&width=1500" class="media--cover media--zoom media--zoom-not-loaded inline-flex overflow-hidden absolute top-0 left-0 w-full h-full js-zoom-link" target="_blank"><picture> 8974 <source srcset="//myevergreen.com/cdn/shop/files/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683&width=690 690w, //myevergreen.com/cdn/shop/files/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683&width=800 800w" 8975 media="(max-width: 600px)" 8976 width="800" 8977 height="800"><img srcset="//myevergreen.com/cdn/shop/files/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683&width=640 640w, //myevergreen.com/cdn/shop/files/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683&width=900 900w, //myevergreen.com/cdn/shop/files/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683&width=1214 1214w" sizes="(min-width: 1718px) 800px, (min-width: 1280px) calc(50vw), (min-width: 1024px) calc(50vw), (min-width: 769px) calc(50vw - 64px), (min-width: 600px) calc(100vw - 64px), calc(100vw - 40px)" src="//myevergreen.com/cdn/shop/files/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683&width=1214" 8978 class="product-image img-fit img-fit--contain w-full" loading="lazy" 8979 width="1214" 8980 height="1214" 8981 8982 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_f2f9b15d-bbf0-46a4-bd85-94be47651f9c"></picture> 8983<img class="zoom-image zoom-image--contain top-0 absolute left-0 right-0 pointer-events-none js-zoom-image no-js-hidden" 8984 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_f2f9b15d-bbf0-46a4-bd85-94be47651f9c" 8985 src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201500%201500'%3E%3C/svg%3E" loading="lazy" 8986 data-src="//myevergreen.com/cdn/shop/files/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683&width=1500" width="1500" height="1500" 8987 data-original-width="3000" data-original-height="3000"> 8988 </a></div> 8989</li><li class="media-viewer__item" data-media-id="30261427142710" data-media-type="image"><div class="media relative" style="padding-top: 100%;"><a href="//myevergreen.com/cdn/shop/files/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307&width=1500" class="media--cover media--zoom media--zoom-not-loaded inline-flex overflow-hidden absolute top-0 left-0 w-full h-full js-zoom-link" target="_blank"><picture> 8990 <source srcset="//myevergreen.com/cdn/shop/files/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307&width=690 690w, //myevergreen.com/cdn/shop/files/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307&width=800 800w" 8991 media="(max-width: 600px)" 8992 width="800" 8993 height="800"><img srcset="//myevergreen.com/cdn/shop/files/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307&width=640 640w, //myevergreen.com/cdn/shop/files/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307&width=900 900w, //myevergreen.com/cdn/shop/files/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307&width=1214 1214w" sizes="(min-width: 1718px) 800px, (min-width: 1280px) calc(50vw), (min-width: 1024px) calc(50vw), (min-width: 769px) calc(50vw - 64px), (min-width: 600px) calc(100vw - 64px), calc(100vw - 40px)" src="//myevergreen.com/cdn/shop/files/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307&width=1214" 8994 class="product-image img-fit img-fit--contain w-full" loading="lazy" 8995 width="1214" 8996 height="1214" 8997 8998 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_761861be-abd6-472f-b120-15d110780fb7"></picture> 8999<img class="zoom-image zoom-image--contain top-0 absolute left-0 right-0 pointer-events-none js-zoom-image no-js-hidden" 9000 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_761861be-abd6-472f-b120-15d110780fb7" 9001 src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201500%201500'%3E%3C/svg%3E" loading="lazy" 9002 data-src="//myevergreen.com/cdn/shop/files/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307&width=1500" width="1500" height="1500" 9003 data-original-width="3000" da
9003ta-original-height="3000"> 9004 </a></div> 9005</li></ul><div class="media-ctrl media-ctrl--lg-down-static no-js-hidden"> 9006 9007 <button type="button" class="media-ctrl__btn tap-target vertical-center btn visible-lg" name="prev" aria-controls="gallery-viewer" disabled> 9008 <span class="visually-hidden">Previous</span> 9009 <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="m6.797 11.625 8.03-8.03 1.06 1.06-6.97 6.97 6.97 6.97-1.06 1.06z"/></svg> 9010 </button> 9011 9012 9013 <div class="media-ctrl__counter text-sm"> 9014 <span class="media-ctrl__current-item">1</span> 9015 <span aria-hidden="true"> / </span> 9016 <span class="visually-hidden">of</span> 9017 <span class="media-ctrl__total-items">7</span> 9018 </div> 9019 9020 9021 <button type="button" class="media-ctrl__btn tap-target vertical-center btn visible-lg" name="next" aria-controls="gallery-viewer"> 9022 <span class="visually-hidden">Next</span> 9023 <svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="m9.693 4.5 7.5 7.5-7.5 7.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 9024 </button> 9025 9026 </div><div class="loading-spinner loading-spinner--out" role="status"> 9027 <span class="sr-only">Loading...</span> 9028 </div></div><div class="media-gallery__thumbs hidden md:block no-js-hidden"> 9029 <ul class="media-thumbs relative flex" role="list"><li class="media-thumbs__item" data-media-id="30261426946102"> 9030 <button class="media-thumbs__btn media relative w-full is-active" aria-current="true" aria-controls="gallery-viewer" style="padding-top: 100%;"> 9031 <span class="visually-hidden">Load image 1 in gallery view</span><img srcset="//myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=80, //myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=160 2x" src="//myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=160" 9032 class="img-fit img-fit--contain w-full" loading="eager" 9033 width="160" 9034 height="160" 9035 9036 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_c9b37276-4780-4d3f-baf1-60c599eda033"> 9037 </button> 9038 </li><li class="media-thumbs__item" data-media-id="30261426978870"> 9039 <button class="media-thumbs__btn media relative w-full" aria-controls="gallery-viewer" style="padding-top: 100%;"> 9040 <span class="visually-hidden">Load image 2 in gallery view</span><img srcset="//myevergreen.com/cdn/shop/files/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307&width=80, //myevergreen.com/cdn/shop/files/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307&width=160 2x" src="//myevergreen.com/cdn/shop/files/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307&width=160" 9041 class="img-fit img-fit--contain w-full" loading="eager" 9042 width="160" 9043 height="160" 9044 9045 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_4bdb1383-1b62-4776-919e-642fbf3de913"> 9046 </button> 9047 </li><li class="media-thumbs__item" data-media-id="30261427011638"> 9048 <button class="media-thumbs__btn media relative w-full" aria-controls="gallery-viewer" style="padding-top: 100%;"> 9049 <span class="visually-hidden">Load image 3 in gallery view</span><img srcset="//myevergreen.com/cdn/shop/files/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307&width=80, //myevergreen.com/cdn/shop/files/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307&width=160 2x" src="//myevergreen.com/cdn/shop/files/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307&width=160" 9050 class="img-fit img-fit--contain w-full" loading="eager" 9051 width="160" 9052 height="160" 9053 9054 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_9086bef2-c4ed-4a4d-a86f-74fa581e2583"> 9055 </button> 9056 </li><li class="media-thumbs__item" data-media-id="30261427044406"> 9057 <button class="media-thumbs__btn media relative w-full" aria-controls="gallery-viewer" style="padding-top: 100%;">
9058 <span class="visually-hidden">Load image 4 in gallery view</span><img srcset="//myevergreen.com/cdn/shop/files/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307&width=80, //myevergreen.com/cdn/shop/files/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307&width=160 2x" src="//myevergreen.com/cdn/shop/files/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307&width=160" 9059 class="img-fit img-fit--contain w-full" loading="eager" 9060 width="160" 9061 height="160" 9062 9063 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_50c16b2e-148e-4117-a4f7-34cb131df641"> 9064 </button> 9065 </li><li class="media-thumbs__item" data-media-id="30261427077174"> 9066 <button class="media-thumbs__btn media relative w-full" aria-controls="gallery-viewer" style="padding-top: 100%;"> 9067 <span class="visually-hidden">Load image 5 in gallery view</span><img srcset="//myevergreen.com/cdn/shop/files/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307&width=80, //myevergreen.com/cdn/shop/files/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307&width=160 2x" src="//myevergreen.com/cdn/shop/files/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307&width=160" 9068 class="img-fit img-fit--contain w-full" loading="eager" 9069 width="160" 9070 height="160" 9071 9072 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_78d85916-fa40-48bb-bb77-5a10608cfb8a"> 9073 </button> 9074 </li><li class="media-thumbs__item" data-media-id="32716987531318"> 9075 <button class="media-thumbs__btn media relative w-full" aria-controls="gallery-viewer" style="padding-top: 100%;"> 9076 <span class="visually-hidden">Load image 6 in gallery view</span><img srcset="//myevergreen.com/cdn/shop/files/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683&width=80, //myevergreen.com/cdn/shop/files/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683&width=160 2x" src="//myevergreen.com/cdn/shop/files/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683&width=160" 9077 class="img-fit img-fit--contain w-full" loading="eager" 9078 width="160" 9079 height="160" 9080 9081 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_f2f9b15d-bbf0-46a4-bd85-94be47651f9c"> 9082 </button> 9083 </li><li class="media-thumbs__item" data-media-id="30261427142710"> 9084 <button class="media-thumbs__btn media relative w-full" aria-controls="gallery-viewer" style="padding-top: 100%;"> 9085 <span class="visually-hidden">Load image 7 in gallery view</span><img srcset="//myevergreen.com/cdn/shop/files/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307&width=80, //myevergreen.com/cdn/shop/files/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307&width=160 2x" src="//myevergreen.com/cdn/shop/files/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307&width=160" 9086 class="img-fit img-fit--contain w-full" loading="eager" 9087 width="160" 9088 height="160" 9089 9090 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_761861be-abd6-472f-b120-15d110780fb7"> 9091 </button> 9092 </li></ul> 9093 </div></media-gallery> 9094 9095</div> 9096 9097 <div 9098 class="product-info product-info--sticky" 9099 9100 data-sticky-height-elems="#product-media,.cc-main-product + .cc-product-details .container" 9101 9102 >
9102<script src="//myevergreen.com/cdn/shop/t/101/assets/sticky-scroll-direction.js?v=32758325870558658521781124410" defer="defer"></script>
9102 9103 <sticky-scroll-direction data-min-sticky-size="md"> 9104 <div><a class="product-options--anchor" id="product-info" rel="nofollow"></a><div class="product-info__block product-info__block--sm product-info__title" > 9105 <h1 class="product-title h5"> 9106 Flag Organizer 9107 9108 9109 </h1> 9110 </div><div class="product-info__block" > 9111 <div id="shopify-block-AL3FickFENmMvaTVxe__bazaarvoice_reviews_photos_rating_summary_block_jnXWRC" class="shopify-block shopify-app-block"> 9112 9113 9114 9115 9116 9117 9118 <div data-bv-show="rating_summary" data-bv-seo="true" data-bv-product-id="7616317653046"> </div> 9119 9120 9121 9122 9123 9124</div> 9125 </div><div 9126 class="product-info__block product-info__block--sm product-vendor-sku text-sm" 9127 9128 ><span 9129 class="product-sku" 9130 9131 ><span>SKU:</span> 9132 <span class="product-sku__value">01245</span> 9133 </span></div><div class="product-info__block product-info__block--sm product-price" > 9134 <div class="product-info__price"> 9135 <div class="price"> 9136 <div class="price__default"> 9137 <strong class="price__current">$25.00 9138</strong> 9139 <s class="price__was"></s> 9140 </div> 9141 9142 <div class="unit-price relative" hidden><span class="visually-hidden">Unit price</span><span class="unit-price__price"> 9143</span><span class="unit-price__separator"> / </span><span class="unit-price__unit"></span></div> 9144 9145 <div class="price__no-variant" hidden> 9146 <strong class="price__current">Unavailable</strong> 9147 </div> 9148</div> 9149 9150 </div><form method="post" action="/cart/add" id="instalments-form-template--21510772129846__main" accept-charset="UTF-8" class="js-instalments-form text-sm mt-2" enctype="multipart/form-data"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="â" /><input type="hidden" name="id" value="42920115601462"> 9151 <shopify-payment-terms variant-id="42920115601462" shopify-meta="{"type":"product","currency_code":"USD","country_code":"US","variants":[{"id":42920115601462,"price_per_term":"$12.50","full_price":"$25.00","eligible":false,"available":true,"number_of_payment_terms":2}],"min_price":"$35.00","max_price":"$30,000.00","financing_plans":[{"min_price":"$35.00","max_price":"$49.99","terms":[{"apr":0,"loan_type":"split_pay","installments_count":2}],"min_price_amount":35.0,"max_price_amount":49.99},{"min_price":"$50.00","max_price":"$149.99","terms":[{"apr":0,"loan_type":"split_pay","installments_count":3},{"apr":0,"loan_type":"split_pay","installments_count":4}],"min_price_amount":50.0,"max_price_amount":149.99},{"min_price":"$150.00","max_price":"$999.99","terms":[{"apr":0,"loan_type":"split_pay","installments_count":3},{"apr":0,"loan_type":"split_pay","installments_count":4},{"apr":15,"loan_type":"interest","installments_count":3},{"apr":15,"loan_type":"interest","installments_count":6},{"apr":15,"loan_type":"interest","installments_count":12}],"min_price_amount":150.0,"max_price_amount":999.99},{"min_price":"$1,000.00","max_price":"$30,000.00","terms":[{"apr":15,"loan_type":"interest","installments_count":3},{"apr":15,"loan_type":"interest","installments_count":6},{"apr":15,"loan_type":"interest","installments_count":12}],"min_price_amount":1000.0,"max_price_amount":30000.0}],"installments_buyer_prequalification_enabled":false,"seller_id":3098466}"></shopify-payment-terms> 9152<input type="hidden" name="product-id" value="7616317653046" /><input type="hidden" name="section-id" value="template--21510772129846__main" /></form></div><div class="product-info__block" > 9153 <p><img src="//myevergreen.com/cdn/shop/files/paypal-p.svg?v=1719865388&width=15" alt="" srcset="//myevergreen.com/cdn/shop/files/paypal-p.svg?v=1719865388&width=15 15w" width="15" height="20"> <img src="//myevergreen.com/cdn/shop/files/paypal-pay-in-4.svg?v=1719865194&width=60" alt="" srcset="//myevergreen.com/cdn/shop/files/paypal-pay-in-4.svg?v=1719865194&width=60 60w" width="60" height="19"> Pay in 4 interest-free payments on purchases of $30-$1,500.</p> 9154 </div><div class="product-info__block product-backorder"> 9155 <style> 9156.backorder-notice { 9157 border: 2px solid #009174; 9158 background-color: #fdf6f5; 9159 padding: 16px 20px; 9160 margin: 16px 0; 9161 text-align: center; 9162} 9163 9164.backorder-notice strong { 9165 color: #DA5256; 9166 font-size: 15px; 9167 display: block; 9168 margin-bottom: 6px; 9169} 9170 9171.backorder-notice p { 9172 color: #333; 9173 font-size: 14px; 9174 margin: 0; 9175 line-height: 1.5; 9176} 9177.backorder-notice strong.backorder-subheading { 9178 color: #333; 9179 font-size: 15px; 9180 display: block; 9181 margin-bottom: 6px; 9182} 9183cart-drawer .backorder-notice, 9184.cart-drawer .backorder-notice, 9185.cart .backorder-notice { 9186 display: inline-block; 9187 border: 1px solid #ddd; 9188 background-color: #f9f9f9; 9189 padding: 8px 12px; 9190 margin: 8px 0; 9191 font-size: 13px; 9192 text-align: left; 9193} 9194</style><div class="backorder-notice" hidden><strong class="eta_date_text"> 9195 Pre-order Now! 9196 </strong> 9197 <strong class="backorder-subheading"> 9198 Estimated to Ship by 9199 </strong> 9200 <p class="m-0"> 9201 Reserve yours today and we'll ship it as soon as it's available. 9202 </p></div> 9203 9204 9205 </div><hr 9206 class="mt-8 mb-8" 9207 9208 ><div class="product-info__block" > 9209 <product-form><form method="post" action="/cart/add" id="product-form-template--21510772129846__main" accept-charset="UTF-8" class="js-product-form js-product-form-main" enctype="multipart/form-data"><input type="hidden" name="form_type" value="product" /><input type="hidden" name="utf8" value="â" /><div 9210 class="alert mb-8 bg-error-bg text-error-text js-form-error text-start" 9211 role="alert" 9212 hidden 9213 ></div> 9214 9215 <input type="hidden" name="id" value="42920115601462" disabled> 9216 <div class="product-info__add-to-cart flex"> 9217<quantity-input class="inline-block"> 9218 <label class="label visually-hidden" for="quantity-template--21510772129846__main">Qty</label> 9219 <div class="qty-input qty-input--combined inline-flex items-center w-full"> 9220 <button type="button" class="qty-input__btn btn btn--minus no-js-hidden" name="minus">
9221 <span class="visually-hidden">-</span> 9222 </button> 9223 <input type="number" 9224 class="qty-input__input input" 9225 id="quantity-template--21510772129846__main" 9226 name="quantity" 9227 min="1" 9228 value="1" 9229 > 9230 <button type="button" class="qty-input__btn btn btn--plus no-js-hidden" name="plus"> 9231 <span class="visually-hidden">+</span> 9232 </button> 9233 </div> 9234</quantity-input> 9235 9236<div class="product-info__add-button"><button 9237 type="submit" 9238 data-add-to-cart-text="Add to cart" 9239 class="btn btn--primary w-full" 9240 name="add" 9241 9242 >Add to cart</button> 9243 </div> 9244 </div><input type="hidden" name="product-id" value="7616317653046" /><input type="hidden" name="section-id" value="template--21510772129846__main" /></form></product-form></div> 9245<div class="product-info__block" > 9246 <style> 9247 #pmb-message_banner_FXWLXi .product-message-banner { 9248 display: block; 9249 background-color: #009174; 9250 color: #ffffff; 9251 padding: 16px; 9252 border-radius: 6px; 9253 text-decoration: none; 9254 transition: opacity 0.15s ease; 9255 } 9256 #pmb-message_banner_FXWLXi a.product-message-banner:hover { opacity: 0.9; } 9257 #pmb-message_banner_FXWLXi .product-message-banner__inner { 9258 display: flex; 9259 flex-direction: column; 9260 align-items: center; 9261 justify-content: center; 9262 gap: 0.5rem; 9263 text-align: center; 9264 } 9265 #pmb-message_banner_FXWLXi .product-message-banner__heading { 9266 margin: 0; 9267 font-weight: 700; 9268 color: inherit; 9269 line-height: 1.3; 9270 } 9271 #pmb-message_banner_FXWLXi .product-message-banner__text, 9272 #pmb-message_banner_FXWLXi .product-message-banner__text p { 9273 margin: 0; 9274 color: inherit; 9275 } 9276 #pmb-message_banner_FXWLXi .product-message-banner__text a { color: inherit; text-decoration: underline; } 9277 #pmb-message_banner_FXWLXi .product-message-banner__button { 9278 display: inline-block; 9279 padding: 0.5rem 1rem; 9280 border: 1px solid currentColor; 9281 border-radius: 4px; 9282 font-weight: 600; 9283 text-decoration: none; 9284 color: inherit; 9285 background: transparent; 9286 } 9287 </style> 9288 <div id="pmb-message_banner_FXWLXi"><a 9289 class="product-message-banner" 9290 href="/collections/garden_flags" 9291 target="_blank" rel="noopener" 9292 ><div class="product-message-banner__inner"><p class="product-message-banner__heading">Buy 3 or More Garden Flags, Save 20%</p></div></a></div> 9293 </div> 9294<hr 9295 class="mt-8 mb-8" 9296 9297 ><div 9298 class="product-info__block product-info__block--sm rte product-description" 9299 9300 > 9301 Keep all of your flags organized in one easy location! This two-sided flag organizer can hold up to 33 of your favorite house or garden flags, so you'll easily be able to decorate your home appropriately for the season! 9302 </div><div class="product-info__block" > 9303 9304 9305 9306<ul style="padding: 0 28px;"> 9307 9308 9309 9310 <li style="list-style-type: disc;">Double-sided flag organizer has 33 pockets.</li> 9311 9312 9313 9314 9315 <li style="list-style-type: disc;">Designed to fit in a closet.</li> 9316 9317 9318 9319 9320 <li style="list-style-type: disc;">Swivel hanger hook.</li> 9321 9322 9323 9324 9325 <li style="list-style-type: disc;">Stores flags, finials, brackets and more!</li> 9326 9327 9328 9329 9330 <li style="list-style-type: disc;">Measures 18.5 x 48.25 inches.</li> 9331 9332 9333</ul> 9334 9335 9336 </div><details-disclosure > 9337 <details 9338 class="disclosure disclosure--row" 9339 9340 > 9341 <summary> 9342 <div class="flex justify-between items-center"> 9343 <h2 class="disclosure__title product-info__disclosure font-body font-bold text-body flex flex-auto items-center mb-0"><svg class="icon icon--ruler" width="22" height="22" viewBox="0 0 16 16" aria-hidden="true" focusable="false" role="presentation">
9343<path fill="currentColor" d="M14.93 4.11L12.1 1.28a1 1 0 00-1.41 0L6.8 5.17.78 11.18a1 1 0 000 1.42l2.82 2.82a1 1 0 001.42 0l9.9-9.9a1 1 0 000-1.4zm-10.6 10.6L1.48 11.9l1.41-1.41 1.06 1.06a.5.5 0 00.71-.71L3.61 9.77l1.42-1.42 1.05 1.06a.5.5 0 00.71-.7L5.73 7.65l1.42-1.42L8.2 7.3c.2.2.5.2.7 0s.2-.5 0-.7L7.85 5.53 9.27 4.1l1.06 1.06a.5.5 0 00.71-.7L9.98 3.4 11.39 2l2.83 2.83-9.9 9.9z"/></svg> 9344Details & Dimensions</h2> 9345 <span class="disclosure__toggle"><svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 9346</span> 9347 </div> 9348 </summary> 9349 <div class="disclosure__panel has-motion"> 9350 <div class="disclosure__content rte"> 9351 <p>Size: 18.5"W x 48.25"H x 0.1"D</p> 9352 9353 </div> 9354 </div> 9355 </details> 9356 </details-disclosure><details-disclosure > 9357 <details 9358 class="disclosure disclosure--row" 9359 9360 > 9361 <summary> 9362 <div class="flex justify-between items-center"> 9363 <h2 class="disclosure__title product-info__disclosure font-body font-bold text-body flex flex-auto items-center mb-0"><svg class="icon icon--truck" width="22" height="22" viewBox="0 0 16 16" aria-hidden="true" focusable="false" role="presentation"><path fill="currentColor" d="M15.64 6.92L9.5 5.12V4a.5.5 0 00-.5-.5H1a.5.5 0 00-.5.5v8.5c0 .28.22.5.5.5h1.27a2.1 2.1 0 004.06 0h3.94a2.1 2.1 0 004.06 0h1.17a.5.5 0 00.5-.5V7.4a.5.5 0 00-.36-.48zM4.3 13.6a1.1 1.1 0 110-2.2 1.1 1.1 0 010 2.2zM6.33 12a2.1 2.1 0 00-4.06 0H1.5V4.5h7V12H6.33zm5.97 1.6a1.1 1.1 0 110-2.2 1.1 1.1 0 010 2.2zM15 12h-.67a2.1 2.1 0 00-4.06 0H9.5V6.17l5.5 1.6V12z"/></svg> 9364Shipping & Return Info</h2> 9365 <span class="disclosure__toggle"><svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 9366</span> 9367 </div> 9368 </summary> 9369 <div class="disclosure__panel has-motion"> 9370 <div class="disclosure__content rte"> 9371 <p><span class="metafield-single_line_text_field">No Ship Restriction</span></p> 9372 9373 </div> 9374 </div> 9375 </details> 9376 </details-disclosure><div class="product-info__block" ><link href="//myevergreen.com/cdn/shop/t/101/assets/product.css?v=39469541301224235251781124412" rel="stylesheet" type="text/css" media="all" /> 9377<link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/quick-add.css?v=35249579494178169851781124411" media="print" onload="this.media='all'"> 9378
9378<script src="//myevergreen.com/cdn/shop/t/101/assets/quick-add.js?v=36670813702257243391781124411" defer="defer"></script>
9378 9379
9379<script src="//myevergreen.com/cdn/shop/t/101/assets/variant-picker.js?v=88930995069167509411781124410" defer="defer"></script>
9379 9380
9380<script src="//myevergreen.com/cdn/shop/t/101/assets/product-form.js?v=131379636371976267351781124412" defer="defer"></script>
9380 9381
9381<script src="//myevergreen.com/cdn/shop/t/101/assets/custom-select.js?v=165097283151564761351781124413" defer="defer"></script>
9381<product-recommendations class="block" data-url="/recommendations/products?section_id=template--21510772129846__main&product_id=7616317653046&limit=4&intent=complementary" data-product-id="7616317653046"></product-recommendations></div><div class="product-info__block" > 9382 <div class="social-share flex items-center"> 9383 <p class="social-share__heading mb-0 font-bold">Share:</p> 9384 <ul class="social inline-flex flex-wrap"><li> 9385 <a class="social__link flex items-center justify-center" href="//twitter.com/intent/tweet?text=Flag%20Organizer&url=https://myevergreen.com/products/01245" target="_blank" rel="noopener" title="Tweet on X"> 9386 <svg fill="currentColor" width="40" height="40" viewBox="1 1 22 22" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg> 9387 </a> 9388 </li><li> 9389 <a class="social__link flex items-center justify-center" href="//www.facebook.com/sharer.php?u=https://myevergreen.com/products/01245" target="_blank" rel="noopener" title="Share on Facebook"> 9390 <svg width="24" height="24" viewBox="0 0 14222 14222" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M14222 7112c0 3549.352-2600.418 6491.344-6000 7024.72V9168h1657l315-2056H8222V5778c0-562 275-1111 1159-1111h897V2917s-814-139-1592-139c-1624 0-2686 984-2686 2767v1567H4194v2056h1806v4968.72C2600.418 13603.344 0 10661.352 0 7112 0 3184.703 3183.703 1 7111 1s7111 3183.703 7111 7111Zm-8222 7025c362 57 733 86 1111 86-377.945 0-749.003-29.485-1111-86.28Zm2222 0v-.28a7107.458 7107.458 0 0 1-167.717 24.267A7407.158 7407.158 0 0 0 8222 14137Zm-167.717 23.987C7745.664 14201.89 7430.797 14223 7111 14223c319.843 0 634.675-21.479 943.283-62.013Z"/></svg> 9391 </a> 9392 </li><li> 9393 <a class="social__link flex items-center justify-center" href="//pinterest.com/pin/create/button/?url=https://myevergreen.com/products/01245&media=//myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=1000&description=Flag%20Organizer" target="_blank" rel="noopener" title="Pin on Pinterest"> 9394 <svg width="24" height="24" viewBox="0 0 48 48" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M24.001 0C10.748 0 0 10.745 0 24.001c0 9.825 5.91 18.27 14.369 21.981-.068-1.674-.012-3.689.415-5.512.462-1.948 3.087-13.076 3.087-13.076s-.765-1.533-.765-3.799c0-3.556 2.064-6.212 4.629-6.212 2.182 0 3.237 1.64 3.237 3.604 0 2.193-1.4 5.476-2.12 8.515-.6 2.549 1.276 4.623 3.788 4.623 4.547 0 7.61-5.84 7.61-12.76 0-5.258-3.543-9.195-9.986-9.195-7.279 0-11.815 5.427-11.815 11.49 0 2.094.616 3.567 1.581 4.708.446.527.505.736.344 1.34-.113.438-.378 1.505-.488 1.925-.16.607-.652.827-1.2.601-3.355-1.369-4.916-5.04-4.916-9.17 0-6.816 5.75-14.995 17.152-14.995 9.164 0 15.195 6.636 15.195 13.75 0 9.416-5.233 16.45-12.952 16.45-2.588 0-5.026-1.4-5.862-2.99 0 0-1.394 5.53-1.688 6.596-.508 1.85-1.504 3.7-2.415 5.14 2.159.638 4.44.985 6.801.985C37.255 48 48 37.255 48 24.001 48 10.745 37.255 0 24.001 0"/></svg> 9395 </a> 9396 </li> 9397</ul> 9398 9399 </div> 9400 </div></div> 9401 </sticky-scroll-direction></div> 9402 </div> 9403</div><link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/sticky-atc-panel.css?v=127345280256637206701781124414" media="print" onload="this.media='all'"> 9404
9404<script src="//myevergreen.com/cdn/shop/t/101/assets/sticky-atc-panel.js?v=181954691680187795721781124410" defer="defer"></script>
9404 9405 9406 <sticky-atc-panel class="sticky-atc-panel sticky-atc-panel--out fixed bottom-0 end invisible"> 9407 <div class="card card--row card--related card--sticky-atc relative flex items-center"><div class="card__media"><img srcset="//myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=56, //myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=112 2x" src="//myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=112" 9408 loading="lazy" 9409 width="112" 9410 height="112" 9411 9412 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_c9b37276-4780-4d3f-baf1-60c599eda033"> 9413 </div><div class="card__info"> 9414 <p class="sticky-atc-panel__heading h6 regular-text text-current"> 9415 Flag Organizer 9416 </p><div class="price"> 9417 <div class="price__default"> 9418 <strong class="price__current">$25.00 9419</strong> 9420 <s class="price__was"></s> 9421 </div> 9422 9423 <div class="unit-price relative" hidden><span class="visually-hidden">Unit price</span><span class="unit-price__price"> 9424</span><span class="unit-price__separator"> / </span><span class="unit-price__unit"></span></div> 9425 9426 <div class="price__no-variant" hidden> 9427 <strong class="price__current">Unavailable</strong> 9428 </div> 9429</div> 9430</div> 9431 9432 <div class="card__buttons"><a href="#product-info" rel="nofollow" class="btn btn--secondary btn--sm">View details</a></div> 9433 </div> 9434 </sticky-atc-panel> 9435 9436 9437
9438<script type="application/ld+json"> 9439{ 9440 "@context": "https://schema.org/", 9441 "@type": "Product", 9442 "@id": "https://myevergreen.com/products/01245", 9443 "category": "Flag Accessories", 9444 "description": "Keep all of your flags organized in one easy location! This two-sided flag organizer can hold up to 33 of your favorite house or garden flags, so you'll easily be able to decorate your home appropriately for the season!", 9445 "gtin": "746851700033", 9446 "image": "https:\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307\u0026width=1920", 9447 "name": "Flag Organizer", 9448 "sku": "01245", 9449 "url": "https:\/\/myevergreen.com\/products\/01245", 9450 "brand": { 9451 "@type": "Brand", 9452 "name": "Evergreen" 9453 }, 9454 "offers": { 9455 "@id": "https:\/\/myevergreen.com\/products\/01245?variant=42920115601462#offer", 9456 "@type": "Offer", 9457 "availability": "https://schema.org/InStock", 9458 "price": "25.00", 9459 "priceCurrency": "USD", 9460 "url": "https:\/\/myevergreen.com\/products\/01245?variant=42920115601462" 9461 } 9462} 9463</script>
9463 9464 9465 9466<style> #shopify-section-template--21510772129846__main .flash-promo {text-align: center; background-color: #76d7a7; padding: 10px; width: 100%; margin: 0; font-size: 16px; font-weight: bold;} #shopify-section-template--21510772129846__main .bogos-container {background-color: #76d7a7; padding-block: 12px;} #shopify-section-template--21510772129846__main .bogos-container:hover {opacity: 0.8;} #shopify-section-template--21510772129846__main .bogos-bundle-cta {color: black; display: flex; justify-content: space-between; padding-inline: 15px;} </style></div><div id="shopify-section-template--21510772129846__details" class="shopify-section cc-product-details product-details section"><div class="container reading-width"><div class="product-details__block" > 9467 9468 9469 9470 <div style="text-align:center;"> 9471 <img 9472 src="//myevergreen.com/cdn/shop/files/buy-now-pay-later-color_600x.png?v=1764365223" 9473 alt="" 9474 loading="lazy" 9475 style="display:inline-block;" 9476 > 9477 </div> 9478 9479 </div></div> 9480</div><div id="shopify-section-template--21510772129846__hawksearch-recommendations" class="shopify-section">
9481<script src="//myevergreen.com/cdn/shop/t/101/assets/quick-add.js?v=36670813702257243391781124411" defer="defer"></script>
9481 9482
9482<script src="//myevergreen.com/cdn/shop/t/101/assets/variant-picker.js?v=88930995069167509411781124410" defer="defer"></script>
9482 9483
9483<script src="//myevergreen.com/cdn/shop/t/101/assets/product-form.js?v=131379636371976267351781124412" defer="defer"></script>
9483 9484
9484<script src="//myevergreen.com/cdn/shop/t/101/assets/custom-select.js?v=165097283151564761351781124413" defer="defer"></script>
9484<style> 9485 .hawksearch-recommendations { 9486 width: 100%; 9487 max-width: calc(var(--page-width, 1320px) + var(--gutter) * 2); 9488 margin: 40px auto; 9489 padding: 0 var(--gutter); 9490 } 9491 .hawksearch-recommendations__empty { 9492 padding: 20px; 9493 text-align: center; 9494 color: #999; 9495 font-style: italic; 9496 } 9497</style> 9498 9499<div class="container hawksearch-recommendations"><div class="text-center"> 9500 <h2 class="h4 section__heading">You May Also Like</h2> 9501 </div> 9502 9503 <hawksearch-recommendations 9504 widget-id="dfd81367-95db-45ac-819e-42b0bafdd03b" item-id="01245" 9505 style="--recs-desktop-width: 25.0%; --recs-tablet-width: 33.333333333333336%;" 9506 ></hawksearch-recommendations> 9507 9508 9509</div> 9510 9511 9512</div><section id="shopify-section-template--21510772129846__recommendations" class="shopify-section cc-product-recommendations cc-product-card-grid"><link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/product.css?v=39469541301224235251781124412" media="print" onload="this.media='all'"><link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/quick-add.css?v=35249579494178169851781124411" media="print" onload="this.media='all'"> 9513
9513<script src="//myevergreen.com/cdn/shop/t/101/assets/quick-add.js?v=36670813702257243391781124411" defer="defer"></script>
9513 9514
9514<script src="//myevergreen.com/cdn/shop/t/101/assets/variant-picker.js?v=88930995069167509411781124410" defer="defer"></script>
9514 9515
9515<script src="//myevergreen.com/cdn/shop/t/101/assets/product-form.js?v=131379636371976267351781124412" defer="defer"></script>
9515 9516
9516<script src="//myevergreen.com/cdn/shop/t/101/assets/custom-select.js?v=165097283151564761351781124413" defer="defer"></script>
9516<product-recommendations class="section" data-url="/recommendations/products?section_id=template--21510772129846__recommendations&product_id=7616317653046&limit=8&intent=related" data-product-id="7616317653046"></product-recommendations> 9517 9518 9519</section><section id="shopify-section-template--21510772129846__recently_viewed_PhTAVe" class="shopify-section cc-recently-viewed cc-product-card-grid"><link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/product.css?v=39469541301224235251781124412" media="print" onload="this.media='all'"><link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/quick-add.css?v=35249579494178169851781124411" media="print" onload="this.media='all'"> 9520
9520<script src="//myevergreen.com/cdn/shop/t/101/assets/quick-add.js?v=36670813702257243391781124411" defer="defer"></script>
9520 9521
9521<script src="//myevergreen.com/cdn/shop/t/101/assets/variant-picker.js?v=88930995069167509411781124410" defer="defer"></script>
9521 9522
9522<script src="//myevergreen.com/cdn/shop/t/101/assets/product-form.js?v=131379636371976267351781124412" defer="defer"></script>
9522 9523
9523<script src="//myevergreen.com/cdn/shop/t/101/assets/custom-select.js?v=165097283151564761351781124413" defer="defer"></script>
9523<recently-viewed class="section" data-url="/search?section_id=template--21510772129846__recently_viewed_PhTAVe&type=product" data-limit="8" data-exclude="7616317653046"></recently-viewed> 9524
9525<script> 9526 document.addEventListener('DOMContentLoaded', () => { 9527 if (!customElements.get('recently-viewed')) { 9528 class RecentlyViewed extends HTMLElement { 9529 constructor() { 9530 super(); 9531 this.fetchAttempts = 0; 9532 window.initLazyScript(this, this.init.bind(this), 500); 9533 } 9534 9535 async init() { 9536 try { 9537 const response = await fetch(`${this.dataset.url}&q=${this.getSearchQuery()}`); 9538 if (!response.ok) throw new Error(response.status); 9539 9540 const tmpl = document.createElement('template'); 9541 tmpl.innerHTML = await response.text(); 9542 9543 const el = tmpl.content.querySelector('recently-viewed'); 9544 if (el && el.hasChildNodes()) { 9545 this.innerHTML = el.innerHTML; 9546 } 9547 } catch (error) { 9548 this.fetchAttempts += 1; 9549 9550 if (this.fetchAttempts === 3) { 9551 console.log(error); 9552 } else { 9553 this.init(); 9554 } 9555 } 9556 } 9557 9558 getSearchQuery() { 9559 const items = JSON.parse(localStorage.getItem('cc-recently-viewed') || '[]'); 9560 9561 if (this.dataset.exclude && items.includes(Number(this.dataset.exclude))) { 9562 items.splice(items.indexOf(Number(this.dataset.exclude)), 1); 9563 } 9564 9565 return items.map((item) => `id:${item}`).slice(0, this.dataset.limit).join(' OR '); 9566 } 9567 } 9568 9569 customElements.define('recently-viewed', RecentlyViewed); 9570 } 9571 }); 9572</script>
9572 9573 9574 9575</section><div id="shopify-section-template--21510772129846__bv_tabs_hrPzLt" class="shopify-section grow"><tabbed-content> 9576 <div class="tablist overflow-hidden relative mb-4 no-js-hidden container"> 9577 <div class="tablist__scroller flex" role="tablist"> 9578 <button 9579 type="button" 9580 class="tablist__tab font-bold h4" 9581 id="pwr-tab-1" 9582 role="tab" 9583 aria-controls="pwr-panel-1" 9584 aria-selected="true" 9585 > 9586 RATINGS & REVIEWS 9587 </button> 9588 <button 9589 type="button" 9590 class="tablist__tab font-bold h4" 9591 id="pwr-tab-2" 9592 role="tab" 9593 aria-controls="pwr-panel-2" 9594 aria-selected="false" 9595 > 9596 QUESTIONS & ANSWERS 9597 </button> 9598 </div> 9599 </div><div 9600 id="pwr-panel-1" 9601 role="tabpanel" 9602 tabindex="0" 9603 aria-labelledby="pwr-tab-1" 9604 9605 > 9606 <div id="shopify-block-AeVRxNk5zMXQrdnZpM__bazaarvoice_reviews_photos_reviews_block_NJVaPP" class="shopify-block shopify-app-block"> 9607 9608 9609 9610 9611 9612 9613 <div data-bv-show="reviews" data-bv-seo="true" data-bv-product-id="7616317653046"> </div> 9614 9615 9616 9617 9618 9619</div> 9620 </div><div 9621 id="pwr-panel-2" 9622 role="tabpanel" 9623 tabindex="0" 9624 aria-labelledby="pwr-tab-2" 9625 9626 hidden 9627 9628 > 9629 <div id="shopify-block-Ad25vb2xNckkvTkdvM__bazaarvoice_reviews_photos_questions_and_answers_block_QdqaF3" class="shopify-block shopify-app-block"> 9630 9631 9632 9633 9634 9635 9636 <div data-bv-show="questions" data-bv-product-id="7616317653046"> </div> 9637 9638 9639 9640 9641 9642</div> 9643 </div></tabbed-content>
9644<script src="//myevergreen.com/cdn/shop/t/101/assets/tabs.js?v=135558236254064818051781124412" defer="defer"></script>
9644 9645 9646 9647<style> #shopify-section-template--21510772129846__bv_tabs_hrPzLt [data-bv-show="reviews"], #shopify-section-template--21510772129846__bv_tabs_hrPzLt [data-bv-show="questions"] {width: 100%; max-width: calc(var(--page-width, 1320px) + var(--gutter) * 2); margin: 0 auto; padding: 0 var(--gutter);} </style></div><div id="shopify-section-template--21510772129846__17231488385665ac64" class="shopify-section cc-apps"><div class="section"><div class="container"></div></div> 9648 9649</div> 9650 </main><!-- BEGIN sections: overlay-group --> 9651<div id="shopify-section-sections--21510771867702__cart-drawer" class="shopify-section shopify-section-group-overlay-group cc-cart-drawer"><link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/cart-items.css?v=83904206517603741941781124411" media="print" onload="this.media='all'">
9652<script src="//myevergreen.com/cdn/shop/t/101/assets/cart-drawer.js?v=26715168632776164121781124410" defer="defer"></script>
9652<script src="//myevergreen.com/cdn/shop/t/101/assets/cart-note.js?v=126131321468449833931781124412" defer="defer"></script>
9652<cart-drawer class="drawer drawer--cart fixed top-0 right-0 flex flex-col w-full has-motion" data-name="cart-drawer" id="cart-drawer" role="dialog" aria-label="Your cart" aria-modal="true" aria-hidden="true" tabindex="-1" data-shipping-calculator="false"> 9653 <header class="drawer__header flex justify-between items-center"> 9654 <h2 class="h5 mb-0">Your cart</h2> 9655 <div class="flex items-center gap-x-theme"><button type="button" class="drawer__close-btn js-close-drawer"> 9656 <span class="visually-hidden">Close</span> 9657 <svg width="24" height="24" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5" fill="none" fill-rule="evenodd" stroke-linejoin="round" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M5 19 19 5M5 5l14 14"/></svg> 9658 </button> 9659 </div> 9660 </header> 9661 9662 <div class="drawer__content drawer__content--flex flex-auto items-center"> 9663 9664 9665 <div class="cart-drawer__content grow flex items-center"><form class="form" id="cart-drawer-form" action="/cart" method="post"> 9666 <cart-items id="cart-items" data-section="cart-drawer" data-empty="true"><div class="cart-empty flex flex-col justify-center items-center h-full js-cart-empty"><svg width="24" height="24" viewBox="0 0 24 24" class="icon icon--cart" aria-hidden="true" focusable="false" role="presentation"><path fill="currentColor" d="M17 18a2 2 0 0 1 2 2 2 2 0 0 1-2 2 2 2 0 0 1-2-2c0-1.11.89-2 2-2M1 2h3.27l.94 2H20a1 1 0 0 1 1 1c0 .17-.05.34-.12.5l-3.58 6.47c-.34.61-1 1.03-1.75 1.03H8.1l-.9 1.63-.03.12a.25.25 0 0 0 .25.25H19v2H7a2 2 0 0 1-2-2c0-.35.09-.68.24-.96l1.36-2.45L3 4H1V2m6 16a2 2 0 0 1 2 2 2 2 0 0 1-2 2 2 2 0 0 1-2-2c0-1.11.89-2 2-2m9-7 2.78-5H6.14l2.36 5H16Z"/></svg><p>Your cart is empty</p><a class="btn btn--primary" href="/collections/all">Start shopping</a></div><p class="visually-hidden" id="cart-live-region-text" role="status" aria-live="polite"> 9667 Subtotal:$0.00 USD 9668</p> 9669 <p class="visually-hidden" id="cart-line-item-status" role="status" aria-live="polite" aria-hidden="true">Loading...</p><div class="alert mt-6 bg-error-bg text-error-text" id="cart-errors" role="alert" hidden></div></cart-items> 9670 9671 </form> 9672 </div> 9673 9674 <div id="cart-promoted-products" class="w-full cart-drawer__promoted-products-container"></div><div id="cart-drawer-media-promotion" class="cart-drawer__media-promotion-container w-full"></div> 9675 </div><div class="cart-drawer__summary relative drawer__footer cart-drawer--checkout--sticky-true"></div> 9676<div class="overlay overlay--drawer absolute top-0 right-0 bottom-0 left-0 js-close"></div> 9677</cart-drawer> 9678 9679<style> #shopify-section-sections--21510771867702__cart-drawer .btn {font-weight: 500;} #shopify-section-sections--21510771867702__cart-drawer .dynamic-cart-btns {margin-top: 10px;} #shopify-section-sections--21510771867702__cart-drawer #cart-drawer {z-index: 200 !important;} </style></div><div id="shopify-section-sections--21510771867702__product-compare" class="shopify-section shopify-section-group-overlay-group cc-compare"><template><div data-compare-key="compare-image" class="compare-col compare-col--medium compare-col--7616317653046" ><div class="media relative" style="padding-top: 100.0%;"> 9680 <img data-srcset="//myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=640 640w, //myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=800 800w" 9681 src="//myevergreen.com/cdn/shop/files/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307&width=640" 9682 loading="lazy" 9683 class="img-fit" 9684 width="3000" 9685 height="3000" 9686 alt="https://asset.productmarketingcloud.com/api/assetstorage/3909_c9b37276-4780-4d3f-baf1-60c599eda033"> 9687 </div></div><div data-compare-key="compare-vendor" class="compare-col compare-col--medium compare-col--7616317653046" > 9688 <span class="product-vendor"> 9689 Evergreen 9690 </span> 9691 </div><div data-compare-key="compare-title" class="compare-col compare-col--medium compare-col--7616317653046" > 9692 <h2 class="product-title h5 mb-0">Flag Organizer</h2> 9693 </div><div data-compare-key="compare-price" class="compare-col compare-col--medium compare-col--7616317653046" > 9694 <div class="product-price"> 9695 <div class="price"> 9696 <div class="price__default"> 9697 <strong class="price__current">$25.00 9698</strong> 9699 <s class="price__was"></s> 9700 </div> 9701 9702 <div class="unit-price relative" hidden><span class="visually-hidden">Unit price</span><span class="unit-price__price"> 9703</span><span class="unit-price__separator"> / </span><span class="unit-price__unit"></span></div> 9704 9705 <div class="price__no-variant" hidden> 9706 <strong class="price__current">Unavailable</strong> 9707 </div> 9708</div> 9709 9710 </div> 9711 </div><div data-compare-key="compare-description" class="compare-col rte compare-col--medium compare-col--7616317653046" >Keep all of your flags organized in one easy location! This two-sided flag organizer can hold up to 33 of your favorite house or garden flags, so you'll easily be able to decorate your home appropriately for the season! 9712</div><div data-compare-key="compare-variants" class="compare-col compare-col--medium compare-col--7616317653046 compare-col--7616317653046--variants" ></div><div data-compare-key="compare-actions" class="compare-col compare-col--medium compare-col--7616317653046 compare-col--7616317653046--actions" > 9713 <a href="/products/01245" class="btn btn--primary btn--compare-view w-full"> 9714 View product 9715 </a> 9716 9717 <button class="link text-sm mt-4 w-full js-compare-col-remove" data-product-id="7616317653046"> 9718 Remove 9719 </button> 9720 </div> 9721 </template> 9722<style> #shopify-section-sections--21510771867702__product-compare #compare-drawer-open {font-weight: 400;} </style></div> 9723<!-- END sections: overlay-group --><!-- BEGIN sections: footer-group --> 9724<div id="shopify-section-sections--21510771802166__footer" class="shopify-section shopify-section-group-footer-group cc-footer"><link rel="stylesheet" href="//myevergreen.com/cdn/shop/t/101/assets/footer.css?v=57805532828560293961781124413" media="print" onload="this.media='all'">
9724<script src="//myevergreen.com/cdn/shop/t/101/assets/custom-select.js?v=165097283151564761351781124413" defer="defer"></script>
9724<style data-shopify>.footer { 9725 9726 --bg-color: 0 145 116 / 1.0; 9727 9728 --heading-color: 255 255 255; 9729 9730 --text-color: 255 255 255; 9731 9732 } 9733 9734 #shopify-section-sections--21510771802166__footer { 9735 9736 position: relative; 9737 9738 z-index: 10; 9739 9740 }</style><a href="#" class="back-to-top text-sm block border-top font-bold text-center text-current p-6 border-bottom">Back to top</a><footer class="footer bg-theme-bg text-theme-text"> 9741 <div class="container"><div class="footer__main md:flex md:flex-wrap mb-10 md:mb-6"><div class="footer-col footer-col--text footer-col--not-collapsed" > 9742 <div class="footer-block mb-8 text-start"><div class="media relative" style="max-width: 170px;"> 9743 <img srcset="//myevergreen.com/cdn/shop/files/2024-EGs-white-logo_71fbbdbb-7ace-4779-96c2-cb8b0d864bef.png?v=1721767026&width=170, //myevergreen.com/cdn/shop/files/2024-EGs-white-logo_71fbbdbb-7ace-4779-96c2-cb8b0d864bef.png?v=1721767026&width=340 2x" src="//myevergreen.com/cdn/shop/files/2024-EGs-white-logo_71fbbdbb-7ace-4779-96c2-cb8b0d864bef.png?v=1721767026&width=340" 9744 class="footer-block__image" style="object-position: 50.0% 50.0%" loading="lazy" 9745 width="340" 9746 height="212" 9747 9748 alt=""> 9749 </div><div class="footer-block__text rte"> 9750 <p>Evergreen belongs to a family of distinguished brands, including Plow & Hearth and Team Sports America.</p> 9751 </div><div class="footer-block__btns footer-block__social"> 9752 <ul class="social inline-flex flex-wrap justify-start"><li> 9753 <a class="social__link flex items-center justify-center" href="https://www.facebook.com/shopmyevergreen/" target="_blank" rel="noopener" title="Evergreen on Facebook"><svg width="24" height="24" viewBox="0 0 14222 14222" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M14222 7112c0 3549.352-2600.418 6491.344-6000 7024.72V9168h1657l315-2056H8222V5778c0-562 275-1111 1159-1111h897V2917s-814-139-1592-139c-1624 0-2686 984-2686 2767v1567H4194v2056h1806v4968.72C2600.418 13603.344 0 10661.352 0 7112 0 3184.703 3183.703 1 7111 1s7111 3183.703 7111 7111Zm-8222 7025c362 57 733 86 1111 86-377.945 0-749.003-29.485-1111-86.28Zm2222 0v-.28a7107.458 7107.458 0 0 1-167.717 24.267A7407.158 7407.158 0 0 0 8222 14137Zm-167.717 23.987C7745.664 14201.89 7430.797 14223 7111 14223c319.843 0 634.675-21.479 943.283-62.013Z"/></svg><span class="visually-hidden">Facebook</span> 9754 </a> 9755 </li><li> 9756 <a class="social__link flex items-center justify-center" href="https://www.instagram.com/shopmyevergreen/" target="_blank" rel="noopener" title="Evergreen on Instagram"><svg width="24" height="24" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><circle cx="15.238" cy="4.948" r="1.238"/><path d="M19.47 3.444A5.11 5.11 0 0 0 16.548.527a7.351 7.351 0 0 0-2.43-.466C13.05.014 12.713 0 9.999 0c-2.712 0-3.057 0-4.12.06A7.351 7.351 0 0 0 3.45.528 5.11 5.11 0 0 0 .528 3.444 7.317 7.317 0 0 0 .06 5.87C.014 6.936 0 7.274 0 9.982s0 3.053.06 4.113c.018.829.176 1.649.468 2.425a5.11 5.11 0 0 0 2.922 2.917 7.35 7.35 0 0 0 2.429.5c1.069.047 1.407.06 4.12.06s3.058 0 4.12-.06a7.351 7.351 0 0 0 2.429-.466 5.11 5.11 0 0 0 2.922-2.918 7.31 7.31 0 0 0 .467-2.424c.047-1.067.06-1.405.06-4.113s0-3.053-.06-4.113a7.317 7.317 0 0 0-.467-2.459zm-1.437 10.537a5.439 5.439 0 0 1-.34 1.843 3.262 3.262 0 0 1-1.87 1.87 5.451 5.451 0 0 1-1.825.34c-1.04.046-1.332.06-3.996.06-2.664 0-2.937 0-3.995-.06a5.451 5.451 0 0 1-1.825-.34 3.255 3.255 0 0 1-1.878-1.87 5.439 5.439 0 0 1-.34-1.823c-.046-1.038-.06-1.33-.06-3.992s0-2.934.06-3.992c.006-.63.121-1.253.34-1.844a3.255 3.255 0 0 1 1.878-1.87 5.451 5.451 0 0 1 1.825-.339c1.038-.046 1.331-.06 3.995-.06s2.937 0 3.996.06c.623.008 1.24.123 1.824.34.86.331 1.54 1.01 1.872 1.87.216.583.331 1.2.34 1.823.046 1.038.06 1.33.06 3.992 0 2.661 0 2.948-.047 3.992h-.014z"/><path d="M9.991 14.753a4.761 4.761 0 1 1 0-9.523 4.761 4.761 0 0 1 0 9.523zm0-1.905a2.857 2.857 0 1 0 0-5.713 2.857 2.857 0 0 0 0 5.713z"/></svg><span class="visually-hidden">Instagram</span> 9757 </a> 9758 </li><li> 9759 <a class="social__link flex items-center justify-center" href="https://www.pinterest.com/shopmyevergreen/" target="_blank" rel="noopener" title="Evergreen on Pinterest"><svg width="24" height="24" viewBox="0 0 48 48" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M24.001 0C10.748 0 0 10.745 0 24.001c0 9.825 5.91 18.27 14.369 21.981-.068-1.674-.012-3.689.415-5.512.462-1.948 3.087-13.076 3.087-13.076s-.765-1.533-.765-3.799c0-3.556 2.064-6.212 4.629-6.212 2.182 0 3.237 1.64 3.237 3.604 0 2.193-1.4 5.476-2.12 8.515-.6 2.549 1.276 4.623 3.788 4.623 4.547 0 7.61-5.84 7.61-12.76 0-5.258-3.543-9.195-9.986-9.195-7.279 0-11.815 5.427-11.815 11.49 0 2.094.616 3.567 1.581 4.708.446.527.505.736.344 1.34-.113.438-.378 1.505-.488 1.925-.16.607-.652.827-1.2.601-3.355-1.369-4.916-5.04-4.916-9.17 0-6.816 5.75-14.995 17.152-14.995 9.164 0 15.195 6.636 15.195 13.75 0 9.416-5.233 16.45-12.952 16.45-2.588 0-5.026-1.4-5.862-2.99 0 0-1.394 5.53-1.688 6.596-.508 1.85-1.504 3.7-2.415 5.14 2.159.638 4.44.985 6.801.985C37.255 48 48 37.255 48 24.001 48 10.745 37.255 0 24.001 0"/></svg><span class="visually-hidden">Pinterest</span> 9760 </a> 9761 </li><li> 9762 <a class="social__link flex items-center justify-center" href="https://www.linkedin.com/company/evergreen-enterprises" target="_blank" rel="noopener" title="Evergreen on LinkedIn"><svg width="24" height="24" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M.504 6.413h3.899V20H.504V6.413zm1.85-1.7h-.028C.915 4.714 0 3.676 0 2.36 0 1.018.942 0 2.381 0c1.438 0 2.323 1.015 2.35 2.356 0 1.315-.912 2.358-2.377 2.358zM20 20h-4.42v-7.032c0-1.84-.692-3.095-2.212-3.095-1.163 0-1.81.847-2.11 1.665-.114.292-.096.7-.096 1.11V20h-4.38s.057-12.455 0-13.587h4.38v2.132c.259-.932 1.658-2.263 3.89-2.263 2.771 0 4.948 1.956 4.948 6.163V20z"/></svg><span class="visually-hidden">LinkedIn</span> 9763 </a> 9764 </li></ul> 9765 9766 </div></div> 9767 </div><div class="footer-col footer-col--links footer-col--collapsed" > 9768 <footer-menu> 9769 <details class="footer-menu disclosure footer-menu--first" open> 9770 <summary tabindex="-1"> 9771 <div class="flex justify-between items-center"> 9772 <h2 class="disclosure__title font-body font-bold text-h6 regular-text">RESOURCES</h2>
9773 <span class="disclosure__toggle"><svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 9774</span> 9775 </div> 9776 </summary> 9777 <div class="disclosure__panel has-motion"> 9778 <ul class="footer-menu__links disclosure__content" role="list"><li> 9779 <a href="https://9695f5-c4.myshopify.com/account">My Account</a> 9780 </li><li> 9781 <a href="/pages/about-us">About Us</a> 9782 </li><li> 9783 <a href="/pages/meet-our-team">Meet Our Team</a> 9784 </li><li> 9785 <a href="/pages/careers">Careers</a> 9786 </li><li> 9787 <a href="https://www.myevergreenonline.com/en/welcome">Evergreen Wholesale</a> 9788 </li><li> 9789 <a href="https://www.myevergreenwholesale.com/">Become a Retailer</a> 9790 </li></ul> 9791 </div> 9792 </details> 9793 </footer-menu> 9794 </div><div class="footer-col footer-col--links footer-col--collapsed" > 9795 <footer-menu> 9796 <details class="footer-menu disclosure" open> 9797 <summary tabindex="-1"> 9798 <div class="flex justify-between items-center"> 9799 <h2 class="disclosure__title font-body font-bold text-h6 regular-text">HOW CAN WE HELP?</h2> 9800 <span class="disclosure__toggle"><svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 9801</span> 9802 </div> 9803 </summary> 9804 <div class="disclosure__panel has-motion"> 9805 <ul class="footer-menu__links disclosure__content" role="list"><li> 9806 <a href="/pages/contact-us">Contact Us</a> 9807 </li><li> 9808 <a href="/pages/ccpa-request">Request/Delete my Info - CA</a> 9809 </li><li> 9810 <a href="/policies/terms-of-service">Terms & Conditions</a> 9811 </li><li> 9812 <a href="/pages/faqs">FAQs</a> 9813 </li></ul> 9814 </div> 9815 </details> 9816 </footer-menu> 9817 </div><div class="footer-col footer-col--newsletter footer-col--collapsed" ><footer-menu> 9818 <details class="footer-menu disclosure" open> 9819 <summary tabindex="-1"> 9820 <div class="flex justify-between items-center"> 9821 <h2 class="disclosure__title font-body font-bold text-h6 regular-text"> 9822 SIGN UP FOR OUR EMAILS 9823 </h2> 9824 <span class="disclosure__toggle"><svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M20 8.5 12.5 16 5 8.5" stroke="currentColor" stroke-width="1.5" fill="none"/></svg> 9825</span> 9826 </div> 9827 </summary> 9828 <div class="disclosure__panel has-motion"> 9829 <div class="disclosure__content"><div class="rte"> 9830 <p>Don't miss out on sales, new arrivals, and more.</p> 9831 </div><form method="post" action="/contact#footer-signup_form" id="footer-signup_form" accept-charset="UTF-8" class="form"><input type="hidden" name="form_type" value="customer" /><input type="hidden" name="utf8" value="â" /> 9832 <input type="hidden" name="contact[tags]" value="prospect, newsletter"> 9833 9834 9835 9836 <div class="form__field"> 9837 <label class="label visually-hidden" for="footer-signup">Email</label><div class="input-with-button"><input type="email" 9838 class="input w-full focus-inset" 9839 id="footer-signup" 9840 name="contact[email]" 9841 value="" 9842 placeholder="Your email" 9843 autocomplete="email" 9844 aria-required="true" 9845 required><button class="btn focus-inset has-ltr-icon">
9846 <span class="visually-hidden">Subscribe</span> 9847 <svg width="24" height="24" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5" fill="none" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M4.696 12h14.686m-7.007-7.5 7.5 7.5-7.5 7.5"/></svg> 9848 </button></div></div></form> 9849 9850 </div> 9851 </div> 9852 </details> 9853 </footer-menu></div></div><div class="footer__meta grid grid-cols-1 lg:grid-cols-2 gap-x-theme gap-y-10"><div class="lg:col-start-1 lg:row-start-1 footer__localization"> 9854 <form method="post" action="/localization" id="footer-localization" accept-charset="UTF-8" class="form localization no-js-hidden" enctype="multipart/form-data"><input type="hidden" name="form_type" value="localization" /><input type="hidden" name="utf8" value="â" /><input type="hidden" name="_method" value="put" /><input type="hidden" name="return_to" value="/products/01245" /><div class="localization__grid"></div>
9854<script> 9855 customElements.whenDefined('custom-select').then(() => { 9856 if (!customElements.get('country-selector')) { 9857 class CountrySelector extends customElements.get('custom-select') { 9858 constructor() { 9859 super(); 9860 this.loaded = false; 9861 } 9862 9863 async showListbox() { 9864 if (this.loaded) { 9865 super.showListbox(); 9866 return; 9867 } 9868 9869 this.button.classList.add('is-loading'); 9870 this.button.setAttribute('aria-disabled', 'true'); 9871 9872 try { 9873 const response = await fetch('?section_id=country-selector'); 9874 if (!response.ok) throw new Error(response.status); 9875 9876 const tmpl = document.createElement('template'); 9877 tmpl.innerHTML = await response.text(); 9878 9879 const el = tmpl.content.querySelector('.custom-select__listbox'); 9880 this.listbox.innerHTML = el.innerHTML; 9881 9882 this.options = this.querySelectorAll('.custom-select__option'); 9883 9884 this.popular = this.querySelectorAll('[data-popular]'); 9885 if (this.popular.length) { 9886 this.popular[this.popular.length - 1].closest('.custom-select__option') 9887 .classList.add('custom-select__option--visual-group-end'); 9888 } 9889 9890 this.selectedOption = this.querySelector('[aria-selected="true"]'); 9891 if (!this.selectedOption) { 9892 this.selectedOption = this.listbox.firstElementChild; 9893 } 9894 9895 this.loaded = true; 9896 } catch { 9897 this.listbox.innerHTML = '<li>Error fetching countries, please try again.</li>'; 9898 } finally { 9899 super.showListbox(); 9900 this.button.classList.remove('is-loading'); 9901 this.button.setAttribute('aria-disabled', 'false'); 9902 } 9903 } 9904 9905 setButtonWidth() { 9906 return; 9907 } 9908 } 9909 9910 customElements.define('country-selector', CountrySelector); 9911 } 9912 }); 9913 </script>
9913<script> 9914 document.getElementById('footer-localization').addEventListener('change', (evt) => { 9915 const input = evt.target.previousElementSibling; 9916 if (input && input.tagName === 'INPUT') { 9917 input.value = evt.detail.selectedValue; 9918 evt.currentTarget.submit(); 9919 } 9920 }); 9921 </script>
9921</form> 9922 </div></div><hr class="footer__hr"> 9923 9924 9925 <div class="footer__base grid grid-cols-1 lg:grid-cols-2 gap-x-theme gap-y-6 text-xs"> 9926 <div><span>© 2026 <a href="/">Evergreen</a>.</span> 9927 9928 </div><div> 9929 <ul class="footer-sublinks flex flex-wrap gap-x-theme" role="list"> 9930 9931 <li class="footer-sublinks__item"> 9932 <a href="/policies/privacy-policy">Privacy policy</a> 9933 </li> 9934 9935 <li class="footer-sublinks__item"> 9936 <a href="/policies/shipping-policy">Shipping policy</a> 9937 </li> 9938 9939 <li class="footer-sublinks__item"> 9940 <a href="/policies/refund-policy">Returns policy</a> 9941 </li> 9942 9943 <li class="footer-sublinks__item"> 9944 <a href="/pages/accessibility-statement">Accessibility</a> 9945 </li> 9946 9947 <li class="footer-sublinks__item"> 9948 <a href="/pages/sitemap">Sitemap</a> 9949 </li> 9950 9951 </ul> 9952 </div></div> 9953 </div> 9954</footer> 9955 9956 9957 9958 9959<style> #shopify-section-sections--21510771802166__footer .container {max-width: 1640px;} </style></div> 9960<!-- END sections: footer-group --><quick-add-drawer class="drawer quick-add-drawer overflow-hidden fixed top-0 right-0 flex flex-col w-full has-motion js-product" data-name="quickbuy" role="dialog" tabindex="-1" aria-labelledby="quick-add-heading" aria-modal="true" aria-hidden="true"> 9961 <header class="drawer__header quick-add__header hidden md:flex justify-between items-center relative"> 9962 <button type="button" class="drawer__back-btn js-open-cart-drawer has-ltr-icon" hidden> 9963 <span class="visually-hidden">Back</span> 9964 <svg width="24" height="24" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5" fill="none" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M19.5 12H5m6.9 7.4L4.5 12l7.4-7.4"/></svg> 9965 </button> 9966 <div class="flex-grow"> 9967 <h2 class="h5 mb-0" id="quick-add-heading">Choose options</h2> 9968 </div> 9969 <button type="button" class="drawer__close-btn js-close-drawer"> 9970 <span class="visually-hidden">Close</span> 9971 <svg width="24" height="24" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5" fill="none" fill-rule="evenodd" stroke-linejoin="round" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M5 19 19 5M5 5l14 14"/></svg> 9972 </button> 9973 </header> 9974 <div class="drawer__content quick-add__content flex-auto relative"> 9975 <button type="button" class="drawer__close-btn quick-add__close-btn--mob js-close-drawer md:hidden"> 9976 <span class="visually-hidden">Close</span> 9977 <svg width="24" height="24" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5" fill="none" fill-rule="evenodd" stroke-linejoin="round" aria-hidden="true" focusable="false" role="presentation" class="icon"><path d="M5 19 19 5M5 5l14 14"/></svg> 9978 </button> 9979 <div class="js-product-details quick-add__product-details"></div> 9980 </div> 9981 <footer class="drawer__footer quick-add__footer"> 9982 <div class="alert quick-add__alert absolute left-0 right-0 bg-success-bg text-success-text js-added-to-cart" role="alert" hidden data-visible-for="2000"> 9983 <div class="flex"> 9984 <div> 9985 <svg class="icon icon--check_mark_in_circle" width="32" height="32" viewBox="0 0 16 16" aria-hidden="true" focusable="false" role="presentation"><circle stroke="currentColor" fill="none" cx="8" cy="8" r="6.6666665"/> 9986 <path stroke="currentColor" fill="none" transform="translate(5.0003335,6.0003335)" d="m 6,0 -4,4 L 0,2.1818182" /></svg> 9987 </div> 9988 <div> 9989 <p class="quick-add__alert-heading text-h5 font-bold mb-1">Item added to your cart.</p> 9990 <a class="link text-current js-open-cart-drawer" href="/cart" data-no-instant>View cart</a> 9991 </div> 9992 </div> 9993 </div> 9994 <product-form></product-form> 9995 </footer> 9996</quick-add-drawer> 9997<div class="overlay fixed top-0 right-0 bottom-0 left-0 js-overlay"></div> 9998
9998<script> 9999 window.theme = { 10000 info: { 10001 name: 'Enterprise', 10002 version: '1.6.2' 10003 }, 10004 mediaQueries: { 10005 sm: '(min-width: 600px)', 10006 md: '(min-width: 769px)', 10007 lg: '(min-width: 1024px)', 10008 xl: '(min-width: 1280px)', 10009 xxl: '(min-width: 1536px)', 10010 portrait: '(orientation: portrait)' 10011 }, 10012 device: { 10013 hasTouch: window.matchMedia('(any-pointer: coarse)').matches, 10014 hasHover: window.matchMedia('(hover: hover)').matches 10015 }, 10016 routes: { 10017 cart: '/cart', 10018 cartAdd: '/cart/add', 10019 cartChange: '/cart/change', 10020 cartUpdate: '/cart/update', 10021 predictiveSearch: '/search/suggest' 10022 }, 10023 settings: { 10024 moneyWithCurrencyFormat: "${{amount}} USD", 10025 pSearchLimit: 10, 10026 pSearchLimitScope: 'each', 10027 pSearchIncludeSkus: true, 10028 pSearchIncludeTags: true, 10029 sliderItemsPerNav: 'slide', 10030 10031 vibrateOnATC: true, 10032 compareToggle: "toggle_off", 10033 compareShowEmptyMetafields: false, 10034 blendProductImages: false, 10035 externalLinksNewTab: true, 10036 afterAtc: "drawer", 10037 cartType: "drawer" 10038 }, 10039 strings: { 10040 addCartNote: 'Add gift message', 10041 editCartNote: 'Edit gift message', 10042 cartError: 'There was an error while updating your cart. Please try again.', 10043 cartQtyError: 'You can only add [quantity] of this item to your cart.', 10044 cartTermsConfirmation: 'You must agree to the terms and conditions before continuing.', 10045 imageAvailable: 'Image [index] is now available in gallery view', 10046 veryLowStock: 'Very low stock', 10047 lowStock: 'Low stock', 10048 inStock: 'In stock', 10049 noStock: 'Sold out', 10050 noVariant: 'Unavailable', 10051 noSelectedVariant: 'Make a selection', 10052 onlyXLeft: '[quantity] in stock', 10053 awaitingSale: 'This product is not for sale yet.', 10054 shippingCalculator: { 10055 singleRate: 'There is one shipping rate for this destination:', 10056 multipleRates: 'There are multiple shipping rates for this destination:', 10057 noRates: 'We do not ship to this destination.' 10058 }, 10059 viewDetails: 'View details', 10060 compare: { 10061 limit: 'You can only add a maximum of [quantity] products to compare.', 10062 more: 'Select another product to compare.', 10063 empty: 'Select at least two products to compare.', 10064 continue: 'Close to continue.' 10065 }, 10066 discountCopyFail: 'Could not copy code to clipboard. Your browser may not support this.', 10067 articleReadTime: '[x] minute read', 10068 quickNav: { 10069 button_standard: 'Search', 10070 show_products_none: 'No products :(', 10071 button_one: 'Show [quantity] product', 10072 button_other: 'Show [quantity] products', 10073 }, 10074 }, 10075 scripts: { 10076 cartItems: '//myevergreen.com/cdn/shop/t/101/assets/cart-items.js?v=146908865111116973871781124411', 10077 countryProvinceSelector: '//myevergreen.com/cdn/shop/t/101/assets/country-province-selector.js?v=24158546944577672431781124412', 10078 shippingCalculator: '//myevergreen.com/cdn/shop/t/101/assets/shipping-calculator.js?v=31725526838375758301781124410' 10079 } 10080 }; 10081 10082 // Save product ID to localStorage, for use in the 'Recently viewed products' section. 10083 try { 10084 const items = JSON.parse(localStorage.getItem('cc-recently-viewed') || '[]'); 10085 10086 // If product ID is not already in the recently viewed list, add it to the beginning. 10087 if (!items.includes(7616317653046)) { 10088 items.unshift(7616317653046); 10089 } 10090 10091 // Set recently viewed list and limit to 12 products. 10092 localStorage.setItem('cc-recently-viewed', JSON.stringify(items.slice(0, 12))); 10093 } catch (e) {} 10094 </script>
10094<script src="//myevergreen.com/cdn/shop/t/101/assets/instant-page.js?v=473454186210797571781124414" type="module" defer="defer"></script>
10094<!-- Minty --> 10095
10095<script> 10096 (function() { 10097 var script = document.createElement('script'); 10098 script.id = 'minty-onsite-script'; 10099 script.src = 'https://cdn.addshoppers.com/minty/shopify-onsite/executeminty.js'; 10100 script.async = true; 10101 script.defer = true; 10102 document.head.appendChild(script); 10103 })(); 10104 </script>
10104 10105 <!-- End Minty --> 10106 10107 <!-- Upsellit --> 10108
10108<script type="text/javascript">usi_installed = 0; USI_installCode = function() { if (usi_installed == 0) { usi_installed = 1; var USI_headID = document.getElementsByTagName("head")[0]; var USI_installID = document.createElement('script'); USI_installID.type = 'text/javascript'; USI_installID.src = 'https://www.upsellit.com/active/myevergreen.jsp'; USI_headID.appendChild(USI_installID); } }; if (typeof(document.readyState) != "undefined" && document.readyState === "complete") { USI_installCode(); } else if (window.addEventListener){ window.addEventListener('load', USI_installCode, true); } else if (window.attachEvent) { window.attachEvent('onload', USI_installCode); } else { USI_installCode(); } setTimeout("USI_installCode()", 10000);</script>
10108 10109 <!-- End Upsellit --> 10110 10111 <!-- Start of HubSpot Embed Code --> 10112
10112<script 10113 type="text/javascript" 10114 id="hs-script-loader" 10115 async 10116 defer 10117 src="//js.hs-scripts.com/45696013.js?businessUnitId=2299465" 10118 ></script>
10118 10119 <!-- End of HubSpot Embed Code --> 10120 <style> #shopify-pc__banner__btn-decline {display: none !important;} .ips__sc-5ateei-2.bZvNZL {background: #ffffff !important;} </style> 10121<div id="shopify-block-AeWtjZE1LT2Irb3pva__7079518687644006178" class="shopify-block shopify-app-block">
10121<script> 10122 (function () { 10123 const cartAttributes = {}; 10124 10125 // Helper function to retrieve the UTM from Url 10126 function getUTMFromUrl() { 10127 const url_string = window.location.href; 10128 const url = new URL(url_string); 10129 10130 const utm_id = url.searchParams.get("utm_id"); 10131 const utm_source = url.searchParams.get("utm_source"); 10132 const utm_medium = url.searchParams.get("utm_medium"); 10133 const utm_campaign = url.searchParams.get("utm_campaign"); 10134 const utm_term = url.searchParams.get("utm_term"); 10135 const ref = url.searchParams.get("ref"); 10136 10137 if (!utm_id && !utm_source && !utm_medium && !utm_campaign && !ref) { 10138 return null; 10139 } 10140 10141 let utmParameters = {}; 10142 10143 if (utm_id) { 10144 utmParameters.utm_id = utm_id; 10145 } 10146 if (utm_source) { 10147 utmParameters.utm_source = utm_source; 10148 } 10149 if (utm_medium) { 10150 utmParameters.utm_medium = utm_medium; 10151 } 10152 if (utm_campaign) { 10153 utmParameters.utm_campaign = utm_campaign; 10154 } 10155 if (utm_term) { 10156 utmParameters.utm_term = utm_term; 10157 } 10158 if (ref) { 10159 utmParameters.ref = ref; 10160 } 10161 10162 10163 return Object.keys(utmParameters).length === 0 10164 ? null 10165 : utmParameters; 10166 } 10167 10168 // Helper function to retrieve the UTM from Cookie 10169 function getUTMAttributes() { 10170 const urlUtmParams = getUTMFromUrl(); 10171 10172 if (urlUtmParams) { 10173 return urlUtmParams; 10174 } 10175 10176 // No longer reading from deprecated Shopify cookies 10177 return undefined; 10178 } 10179 10180 function saveUtmParameters() { 10181 const utmParams = getUTMAttributes(); 10182 if (utmParams) { 10183 const cartHasUtmAttributes = Object.keys(cartAttributes).find(attributeKey => attributeKey.startsWith("utm_") || attributeKey === "ref"); 10184 if (cartHasUtmAttributes) { 10185 // Don't call API if it already contains our UTM parameters 10186 return; 10187 } 10188 10189 // Handle both Shopify.routes.root and routes.root_url for better compatibility 10190 var rootUrl = (window.Shopify && window.Shopify.routes && window.Shopify.routes.root) 10191 || (window.routes && window.routes.root_url) 10192 || '/'; 10193 10194 var updateCart = fetch(rootUrl + 'cart/update.js', 10195 { 10196 headers: { 10197 'Content-Type': 'application/json', 10198 }, 10199 method: "POST", 10200 body: JSON.stringify({ 10201 attributes: { 10202 ...utmParams 10203 }, 10204 }) 10205 }) 10206 .then(response => response.json()) 10207 .then(data => { 10208 return data 10209 }); 10210 } 10211 } 10212 10213 saveUtmParameters(); 10214 })(); 10215</script>
10215 10216 10217 10218 10219 10220</div><div id="shopify-block-AZFd6aGFnS21FS1hVa__13768625480086291342" class="shopify-block shopify-app-block">
10220<script> 10221 window['ShopifyForms'] = { 10222 ...window['ShopifyForms'], 10223 currentPageType: "product" 10224 }; 10225</script>
10225 10226 10227 10228</div><div id="shopify-block-AdjkraUk3aFVvenQ3d__8605505498557855500" class="shopify-block shopify-app-block bogos-shopify-block"> 10229 10230 10231<div id="secomapp_freegifts_version" data-version="3.0"></div> 10232 10233 <!-- BEGIN app snippet: freegifts-snippet --><link href="//cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/glider.min.css" rel="stylesheet" type="text/css" media="all" /> 10234<link href="//cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/freegifts-main.min.css" rel="stylesheet" type="text/css" media="all" /> 10235 10236 10237 10238 10239 10240 10241 10242 10243 10244 10245 10246 10247<style id="sca_fg_custom_style"> 10248 10249 .freegifts-main-container .fg-section-title, .freegifts-main-container .bogos-slider-info-title { color: #121212; } 10250 .freegifts-main-container .product-title, .freegifts-main-container .bogos-gift-product-title { color: #000000; } 10251 .freegifts-main-container .original-price, .freegifts-main-container .bogos-gift-item-compare-price { color: #121212; } 10252 .freegifts-main-container .gift-price, .freegifts-main-container .bogos-gift-item-price { color: #ea5455; } 10253 .freegifts-main-container .btn-add-to-cart { color: #FFFFFF; background-color: #00856a; } 10254 .freegifts-main-container .bogos-slider-offer-badge { background: #FFEF9D } 10255 .freegifts-main-container .bogos-slider-offer-badge.success { background: #CDFEE1 } 10256 .freegifts-main-container .bogos-slider-offer-title { color: #000000 } 10257 .freegifts-main-container .btn-add-to-cart svg path { fill: #FFFFFF; } 10258 .bogos-gift-select-variant-title { color: #005BD3; } 10259 .bogos-gift-select-variant-title-contain::after { border-color: #005BD3; } 10260 10261 .fg-gift-thumbnail-offer-title { color: #000000; } 10262 .fg-gift-thumbnail-container { border-color: #006346; } 10263 .fg-gift-thumbnail-offer-time { background-color: #006346; } 10264 #sca-gift-thumbnail .sca-gift-image { width: 50px; max-height: 50px; } 10265 10266 #sca-gift-icon .sca-gift-icon-img { width: 50px; max-height: 50px; } 10267 .sca-gift-icon-collection-page .sca-gift-icon-collection-img { width: 50px; max-height: 50px; } 10268 10269 #sca-promotion-glider { color: #ffffff; background-color: #F72119; } 10270 10271 10272 #sca-fg-today-offer-iframe .sca-fg-header { background-color: #FFFFFF; } 10273 #sca-fg-today-offer-iframe .sca-fg-body { background-color: #FFFFFF; } 10274 #sca-fg-today-offer-iframe .sca-fg-today-offer-title { color: #303030 !important; } 10275 #sca-fg-today-offer-iframe .sca-fg-today-offer-subtitle { color: #202020 !important; } 10276 #sca-fg-today-offer-iframe .sca-offer-title { color: #303030; } 10277 #sca-fg-today-offer-widget { height: 70px !important; width: 70px !important; } 10278 .sca-fg-icon-success-anim { box-shadow: inset 0 0 0 #006346; } 10279 @-webkit-keyframes animated-checkmark-fill { to { box-shadow: inset 0 0 0 30px #006346; } } 10280 @keyframes animated-checkmark-fill { to { box-shadow: inset 0 0 0 30px #006346; } } 10281 .sca-fg-icon-success-circle { stroke: #006346; } 10282 #sca-fg-today-offer-iframe .sca-fg-offer .sca-offer-header-container { background-color: #F7F7F7 } 10283 #sca-fg-today-offer-iframe .sca-fg-offer.sca-offer-archived .sca-offer-header-container { background-color: #00634625 } 10284 #sca-fg-today-offer-iframe .sca-gift-product-title { color: #303030} 10285 #sca-fg-today-offer-iframe .sca-gift-product-discount-price { color: #006346 } 10286 #sca-fg-today-offer-iframe .sca-gift-product-original-price { color: #616161 } 10287 #sca-fg-today-offer-iframe .sca-offer-info .sca-offer-subtitle { color: #616161 } 10288 10289 10290 .bogos-bundles-widget { background-color: #F3F3F3; } 10291 .bogos-bundles-widget-body .bogos-bundle-item { background-color: #FFFFFF; } 10292 .bogos-bundles-widget .bogos-bundles-widget-title { color: #303030; } 10293 .bogos-bundles-widget .bogos-bundles-widget-description { color: #616161; } 10294 .bogos-bundle-item .bogos-bundle-item-title { color: #303030; } 10295 .bogos-bundle-item .bogos-bundle-item-discount-price, .bogos-bundles-widget .bogos-bundles-total-discount-price { color: #005BD3; } 10296 .bogos-bundle-item .bogos-bundle-item-original-price, .bogos-bundles-widget .bogos-bundles-total-original-price { color: #005BD3; } 10297 .bogos-bundles-widget-footer .bogos-bundles-button-add { color: #FFFFFF; background-color: #303030; } 10298 .bogos-bundles-widget .bogos-bundle-shipping-discount-container { background-color: #DEE6FF; } 10299 .bogos-bundles-widget .bogos-bundle-shipping-discount-title { color: #2332D5; } 10300 10301 .bogos-bundles-quantity-break-widget { background-color: #F3F3F3; } 10302 .bogos-bundles-quantity-break-widget-title { color: #303030; } 10303 .bogos-bundles-quantity-break-widget-description { color: #303030; } 10304 .bogos-bundle-quantity-break-item-original-price, .bogos-bundles-quantity-break-origin-price { color: #B5B5B5; } 10305 .bogos-bundles-quantity-break-button-add { background: #303030; color: #FFFFFF; } 10306 .bogos-bundle-quantity-break_item-container { background: #FFFFFF; } 10307 .bogos-bundle-quantity-break-label { background: #303030; color: #FFFFFF; } 10308 .bogos-bundle-quantity-break-tag { background: #F1F1F1; color: #303030; } 10309 .bogos-bundle-quantity-break-sub-title { color: #616161; } 10310 .bogos-bundles-quantity-break-discount-price { color: #303030; } 10311 .bogos-bundle-quantity-break-title { color: #303030; } 10312 .bogos-bundle-quantity-break-item-discount-price { color: #303030; } 10313 10314 .bogos-volume-discount-widget.default-layout { background-color: #F3F3F3; } 10315 .bogos-volume-discount-widget.default-layout .bogos-volume-discount-widget-title { color: #303030; } 10316 .bogos-volume-discount-widget.default-layout .bogos-volume-discount-widget-description { color: #303030; } 10317 .bogos-volume-discount-widget.default-layout .bogos-volume-discount-item-original-price , .bogos-volume-discount-origin-price { color: #303030; } 10318 .bogos-volume-discount-widget.default-layout .bogos-volume-discount-button-add { background: #303030; color: #FFFFFF; } 10319 .bogos-volume-discount-widget.default-layout .bogos-volume-discount_item-container { background: #FFFFFF; } 10320 .bogos-volume-discount-widget.default-layout .bogos-volume-discount-label { background: #303030; color: #FFFFFF; } 10321 .bogos-volume-discount-widget.default-layout .bogos-volume-discount-tag { background: #F1F1F1; color: #303030; } 10322 .bogos-volume-discount-widget.default-layout .bogos-volume-discount-sub-title { color: #616161; } 10323 .bogos-volume-discount-widget.default-layout .bogos-volume-discount-item-discount-price { color: #303030; } 10324 .bogos-volume-discount-widget.default-layout .bogos-volume-discount-tier-price-primary span { color: #303030; } 10325 .bogos-volume-discount-widget.default-layout .bogos-volume-discount-discount-price { color: #303030; } 10326 .bogos-volume-discount-widget.default-layout .bogos-volume-discount-title { color: #303030; } 10327 .bogos-volume-discount-widget.default-layout .bogos-volume-discount-origin-price, .bogos-volume-discount-widget.default-layout .bogos-volume-discount-item-original-price { color: #B5B5B5; } 10328 .bogos-volume-discount-widget.table-layout .bogos-volume-discount-widget-header { background-color: #F3F3F3; } 10329 .bogos-volume-discount-widget.table-layout .bogos-volume-discount-widget-title { color: #303030; } 10330 .bogos-volume-discount-widget.table-layout .bogos-volume-discount-widget-description { color: #303030; } 10331 .bogos-volume-discount-table-container.line-style .bogos-volume-discount-item { background-color: #FFFFFF; } 10332 .bogos-volume-discount-widget.table-layout, .bogos-volume-discount-widget.table-layout .bogos-volume-discount-item, .bogos-volume-discount-widget-body .bogos-volume-discount-tier-info, .bogos-volume-discount-widget.table-layout .bogos-volume-discount-widget-header { border-color: #E0E0E0; } 10333 .bogos-volume-discount-widget.table-layout .bogos-volume-discount-title { color: #303030; } 10334 .bogos-volume-discount-widget.table-layout .bogos-volume-discount-description { color: #616161; } 10335 .bogos-volume-discount-widget.table-layout .bogos-volume-discount-tag { background-color: #F1F1F1; color: #303030; } 10336 .bogos-volume-discount-widget.table-layout .bogos-volume-discount-tier-discount-text { color: #303030; } 10337 .bogos-volume-discount-widget.table-layout .bogos-volume-discount-tier-label { color: #FFFFFF; background-color: #303030; } 10338 .bogos-volume-discount-widget.table-layout .bogos-volume-discount-tier-discount-price { color: #303030; } 10339 .bogos-volume-discount-widget.table-layout .bogos-volume-discount-tier-price-primary span { color: #303030; } 10340 .bogos-volume-discount-widget.table-layout .bogos-volume-discount-tier-origin-price { color: #FFFFFF; } 10341 .bogos-volume-discount-table-container.is-hidden-line .bogos-volume-discount-tier-info { border-color: transparent; } 10342 .bogos-volume-discount-widget.table-layout .bogos-volume-discount-table-container.zebra-style .bogos-volume-discount-item:nth-child(odd) { background-color: #FFFFFF; } 10343 .bogos-volume-discount-widget.table-layout .bogos-volume-discount-table-container.zebra-style .bogos-volume-discount-item:nth-child(even) { background-color: #F5F5F5; } 10344 .bogos-volume-discount-widget .bogos-vl-tb-shipping-label { color: #2332D5; } 10345 .bogos-volume-discount-widget .bogos-vl-shipping-label { color: #2332D5; } 10346 .bogos-volume-discount-widget .bogos-vl-shipping-container { background-color: DEE6FF; } 10347 .bogos-volume-discount-widget.default-layout .bogos-vl-subscription-option-title { color: #303030; } 10348 .bogos-volume-discount-widget.default-layout .bogos-vl-subscription-section-title { color: #303030; } 10349 .bogos-volume-discount-widget.default-layout .bogos-vl-subscription-input-c
10349heckbox:checked { background-color: #8051FF; border-color: #8051FF;} 10350 .bogos-volume-discount-widget.default-layout input[type=radio]:checked { background-color: #8051FF; border-color: #8051FF;} 10351 10352 .bogos-mix-match-widget { background-color: #F3F3F3; ; } 10353 .bogos-mix-match-widget .bogos-mix-item { background-color: #FFFFFF; } 10354 .bogos-mix-match-widget .bogos-mix-match-widget-title { color: #303030; } 10355 .bogos-mix-match-widget .bogos-mix-match-widget-description { color: #616161; } 10356 .bogos-mix-match-widget .bogos-mix-item-title { color: #303030; } 10357 .bogos-mix-match-widget .bogos-mix-item-discount-price { color: #303030; } 10358 .bogos-mix-match-widget .bogos-mix-item-original-price { color: #B5B5B5; } 10359 .bogos-mix-match-widget .bogos-mix-match-button-add { color: #FFFFFF; background-color: #303030; } 10360 .bogos-mix-match-widget .bogos-mix-match-badge-item { background-color: #FFF8DB; } 10361 .bogos-mix-match-widget .bogos-mix-match-badge-item.success { background-color: #CDFEE1; } 10362 .bogos-mix-match-widget .bogos-mix-match-badge-item .bogos-mix-match-badge-title { color: #4F4700; } 10363 .bogos-mix-match-widget .bogos-mix-match-badge-item.success .bogos-mix-match-badge-title { color: #29845A; } 10364 .bogos-mix-match-widget .bogos-mix-match-shipping-discount-container { background-color: #DEE6FF; } 10365 .bogos-mix-match-widget .bogos-mix-match-shipping-discount-title { color: #2332D5; } 10366 10367 .bogos-bundle-page-container .bogos-bp-steps-bar, .bogos-bundle-page-container .bogos-bp-step-bar-single { background-color: #009174; } 10368 .bogos-bundle-page-container .bogos-bp-step-title { color: #ffffff; } 10369 .bogos-bp-steps-container .bogos-bp-step-item.active { border-bottom: solid 3px #0e2934; } 10370 .bogos-bundle-page-container .bogos-bp-header-title { color: #303030; } 10371 .bogos-bundle-page-container .bogos-bp-header-subtitle { color: #303030; } 10372 .bogos-bundle-page-container .bogos-bp-step-header-title { color: #303030; } 10373 .bogos-bundle-page-container .bogos-bp-step-header-subtitle { color: #616161; } 10374 .bogos-bundle-page-container .bogos-bp-product-title, .bogos-step-item .bogos-step-item-title, .bogos-product-detail-modal .bogos-product-title { color: #303030; } 10375 .bogos-step-items-container .bogos-step-item-variant-title { color: #616161; } 10376 .bogos-bundle-page-container .bogos-bp-product-price, .bogos-step-item .bogos-step-item-discount-price, .bogos-bp-widget-footer .bogos-bp-total-discount-price { color: #303030; } 10377 .bogos-step-item .bogos-step-item-original-price, .bogos-bp-widget-footer .bogos-bp-total-original-price { color: #808080; } 10378 .bogos-bundle-page-container .bogos-bp-btn-add-product, .bogos-product-detail-modal .bogos-product-add-btn { background-color: #DA5256; color: #FFFFFF } 10379 .bogos-bp-widget-container .bogos-bp-widget { background-color: #F3F3F3; ; } 10380 .bogos-bp-widget .bogos-bp-widget-title { color: #303030; } 10381 .bogos-bp-widget .bogos-bp-widget-description { color: #303030; } 10382 .bogos-step-items-product-require.success .bogos-step-items-product-require-title { color: #C30006; } 10383 .bogos-bp-widget .bogos-bp-button-add { background-color: #DA5256; color: #FFFFFF; } 10384 .bogos-bp-widget-badges-container .bogos-bp-widget-badge-item { background-color: #FFF8DB; } 10385 .bogos-bp-widget-badges-container .bogos-bp-widget-badge-item.success { background-color: #CDFEE1; } 10386 .bogos-bp-widget-badges-container .bogos-bp-widget-badge-title { color: #4F4700; } 10387 .bogos-bp-widget-badge-item.success .bogos-bp-widget-badge-title { color: #29845A; } 10388 .bogos-bp-widget .bogos-bundle-page-shipping-discount-container { background-color: #F3F3F3; } 10389 .bogos-bp-widget .bogos-bundle-page-shipping-discount-title { color: #009174; } 10390 10391 .bogos-fbt-upsell-container { background: #F6F6F6; border-radius: 15px; } 10392 .bogos-fbt-header-title { color: #303030; } 10393 .bogos-fbt-header-description { color: #303030; } 10394 .bogos-fbt-footer-discounted-price { color: #303030; } 10395 .bogos-fbt-footer-original-price { color: #616161; } 10396 .bogos-fbt-footer-button-add { background: #006C46; color: #FFFFFF; } 10397 .bogos-fbt-product-title {color: #303030; } 10398 .bogos-fbt-upsell-product-discounted-price {color: #303030; } 10399 .bogos-fbt-upsell-product-original-price {color: #808080; } 10400 .is-cheapest-free-label {color: #FFFFFF ;background-color: #FFAA00;} 10401 .is-cheapest-free {background-color: rgba(255, 170, 0, 0.2);} 10402 .bogos-fbt-this-item {background-color: #D1D1D1;color: #303030;} 10403 .bogos-fbt-upsell-body-item-checkbox {border-color: #006C46;} 10404 .bogos-fbt-upsell-body-item-checkbox:checked {border-color: #006C46; background-color: #006C46;} 10405 .bogos-fbt-shipping-discount-container { background-color: #52A886; } 10406 .bogos-fbt-shipping-discount-title { color: #FFFFFF; } 10407 .bogos-fbt-upsell-body-stack-meta .bogos-fbt-upsell-img-wrapper, .bogos-fbt-upsell-body-classic-item-img-wrapper .bogos-fbt-upsell-body-classic-item-img {width: 60px; height: 60px;} 10408 .bogos-fbt-upsell-container img.bogos-fbt-upsell-img {border-radius: 7.5px;} 10409 10410 .bogos-cheapest-discount {background-color: #ffffff; border-color: #888888;} 10411 .bogos-cheapest-discount .bogos-cheapest-title { color: #303030; } 10412 .bogos-cheapest-list-product-modal .bogos-cheapest-title { color: #303030; } 10413 .bogos-cheapest-discount .bogos-cheapest-description { color: #616161; } 10414 .bogos-cheapest-product-card .bogos-cheapest-product-title { color: #303030; } 10415 .bogos-cheapest-product-card .bogos-cheapest-product-price { color: #303030; } 10416 .bogos-cheapest-product-card .bogos-cheapest-select-variant-title { color: #303030; } 10417 .bogos-cheapest-product-card .bogos-cheapest-product-add-btn { color: #ffffff; background-color: #303030} 10418 .bogos-cheapest-label-item.active .bogos-cheapest-label { color: #303030; } 10419 .bogos-cheapest-label-item.active #bogos-active-icon path { fill: #3
1041903030; } 10420 .bogos-cheapest-label-item.excluded .bogos-cheapest-label { color: #CCCCCC; } 10421 .bogos-cheapest-label-item.excluded #bogos-excluded-icon path { fill: #CCCCCC; } 10422 .bogos-cheapest-label-item:not(.active):not(.excluded) #bogos-uncheck-icon path { fill: #4A4A4A; } 10423 .bogos-cheapest-label-item:not(.active):not(.excluded) .bogos-cheapest-label { color: #303030; } 10424 .bogos-cheapest-discount .bogos-cheapest-label-container:not(:has(.bogos-cheapest-discount-bullet-items)) {background-color: #F6F6F6;} 10425 .bogos-cheapest-discount .bogos-cheapest-discount-bullet-item {color: #808080;} 10426 .bogos-cheapest-discount .bogos-cheapest-products-describe {color: #616161;} 10427 .bogos-cheapest-discount .bogos-cheapest-products-more-btn {color: #303030;} 10428 10429 .bogos-select-option-custom-item:not(.bogos-option-default):not(.bogos-active):not(has(.sca-d-none)) {background-color: #F0F0F0; color: #303030;} 10430 .bogos-select-option-custom-item:not(.bogos-option-default).bogos-active:not(has(.sca-d-none)) {background-color: #F0F0F0; color: #303030;} 10431 .bogos-select-option-custom-item:not(.bogos-option-default).bogos-active {border: 0.5px solid #303030;} 10432 .bogos-select-option-custom-item.bogos-option-default:not(.bogos-active) .bogos-option-value-title {background-color: #F0F0F0; color: #303030;} 10433 .bogos-select-option-custom-item.bogos-option-default.bogos-active .bogos-option-value-title {background-color: #F0F0F0; color: #303030;} 10434 .bogos-select-option-custom-item.bogos-option-default.bogos-active {border: 0.5px solid #303030;} 10435 .bogos-mix-item-select-variant-option:hover, .bogos-gift-select-variant-option:hover, .bogos-bundle-select-variant-option:hover, .bogos-vl-select-variant-option:hover, .bogos-fbt-variant-item:hover, .bogos-pa-variant-item:hover, .bogos-pa-variant-item.active {background-color: #F0F0F0;} 10436 10437 10438 10439</style>
10439<script id="sca_fg_custom_script" data-cmp-vendor="bogos" data-cmp-ab="0"> 10440 10441 10442</script>
10442 10443
10444<script src="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/glider.min.js" defer></script>
vendor: 1 bytes, line 10444
10444
10445<script src="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/lz-string.min.js" defer></script>
10445 10446 10447<div id="freegifts-main-popup-container" class="freegifts-main-container sca-modal-fg" 10448 data-animation="slideInOutTop"></div> 10449<div id="sca-fg-notifications" class="sca-fg-notifications"></div> 10450 10451<div id="bogos-to-widget-icon-wrap" style="display:none"></div> 10452<div id="bogos-to-widget-iframe" style="visibility:hidden;opacity:0;position:fixed"></div> 10453 10454<div id="sca-fg-today-offer-widget"></div> 10455<div id="sca-fg-today-offer-iframe"></div> 10456 10457<div id="bogos-mix-match-main-collection-popup-container" class="sca-modal-fg"></div> 10458<div id="bogos-main-popup-product-detail-container" data-animation="slideInOutTop"></div> 10459<div id="bogos-main-popup-more-product-container" data-animation="slideInOutTop"></div> 10460 10461<div id="bogos-cart-discount-congrats-msg-wrap"></div> 10462
10463<script type="text/javascript" data-cmp-vendor="bogos" data-cmp-ab="0"> 10464 if (typeof Shopify === "undefined") window.Shopify = {}; 10465 Shopify.cartItems = []; 10466 Shopify.current_product = {}; 10467 Shopify.current_collection = {}; 10468 Shopify.products = {}; 10469 10470 // current product or collection 10471 Shopify.current_product = {...{"id":7616317653046,"title":"Flag Organizer","handle":"01245","description":"Keep all of your flags organized in one easy location! This two-sided flag organizer can hold up to 33 of your favorite house or garden flags, so you'll easily be able to decorate your home appropriately for the season!","published_at":"2025-05-30T13:45:58-04:00","created_at":"2024-07-22T11:21:52-04:00","vendor":"Evergreen","type":"Flag Accessories","tags":["000003","bestseller","Everyday","price-change-job-active"],"price":2500,"price_min":2500,"price_max":2500,"available":true,"price_varies":false,"compare_at_price":0,"compare_at_price_min":0,"compare_at_price_max":0,"compare_at_price_varies":false,"variants":[{"id":42920115601462,"title":"Default Title","option1":"Default Title","option2":null,"option3":null,"sku":"01245","requires_shipping":true,"taxable":true,"featured_image":{"id":38895329902646,"product_id":7616317653046,"position":1,"created_at":"2026-03-03T08:41:45-05:00","updated_at":"2026-03-03T08:41:47-05:00","alt":"https:\/\/asset.productmarketingcloud.com\/api\/assetstorage\/3909_c9b37276-4780-4d3f-baf1-60c599eda033","width":3000,"height":3000,"src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307","variant_ids":[42920115601462]},"available":true,"name":"Flag Organizer","public_title":null,"options":["Default Title"],"price":2500,"weight":363,"compare_at_price":0,"inventory_management":"shopify","barcode":"746851700033","featured_media":{"alt":"https:\/\/asset.productmarketingcloud.com\/api\/assetstorage\/3909_c9b37276-4780-4d3f-baf1-60c599eda033","id":30261426946102,"position":1,"preview_image":{"aspect_ratio":1.0,"height":3000,"width":3000,"src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307"}},"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}],"images":["\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307","\/\/myevergreen.com\/cdn\/shop\/files\/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307","\/\/myevergreen.com\/cdn\/shop\/files\/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307","\/\/myevergreen.com\/cdn\/shop\/files\/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307","\/\/myevergreen.com\/cdn\/shop\/files\/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307","\/\/myevergreen.com\/cdn\/shop\/files\/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683","\/\/myevergreen.com\/cdn\/shop\/files\/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307"],"featured_image":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307","options":["Title"],"media":[{"alt":"https:\/\/asset.productmarketingcloud.com\/api\/assetstorage\/3909_c9b37276-4780-4d3f-baf1-60c599eda033","id":30261426946102,"position":1,"preview_image":{"aspect_ratio":1.0,"height":3000,"width":3000,"src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307"},"aspect_ratio":1.0,"height":3000,"media_type":"image","src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307","width":3000},{"alt":"https:\/\/asset.productmarketingcloud.com\/api\/assetstorage\/3909_4bdb1383-1b62-4776-919e-642fbf3de913","id":30261426978870,"position":2,"preview_image":{"aspect_ratio":1.0,"height":3000,"width":3000,"src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307"},"aspect_ratio":1.0,"height":3000,"media_type":"image","src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307","width":3000},{"alt":"https:\/\/asset.productmarketingcloud.com\/api\/assetstorage\/3909_9086bef2-c4ed-4a4d-a86f-74fa581e2583","id":30261427011638,"position":3,"preview_image":{"aspect_ratio":1.0,"height":3000,"width":3000,"src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307"},"aspect_ratio":1.0,"height":3000,"media_type":"image","src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307","width":3000},{"alt":"https:\/\/asset.productmarketingcloud.com\/api\/assetstorage\/3909_50c16b2e-148e-4117-a4f7-34cb131df641","id":30261427044406,"position":4,"preview_image":{"aspect_ratio":1.0,"height":3000,"width":3000,"src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307"},"aspect_ratio":1.0,"height":3000,"media_type":"image","src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307","width":3000},{"alt":"https:\/\/asset.productmarketingcloud.com\/api\/assetstorage\/3909_78d85916-fa40-48bb-bb77-5a10608cfb8a","id":30261427077174,"position":5,"preview_image":{"aspect_ratio":1.0,"height":3000,"width":3000,"src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307"},"aspect_ratio":1.0,"height":3000,"media_type":"image","src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307","width":3000},{"alt":"https:\/\/asset.productmarketingcloud.com\/api\/assetstorage\/3909_f2f9b15d-bbf0-46a4-bd85-94be47651f9c","id":32716987531318,"position":6,"preview_image":{"aspect_ratio":1.0,"height":3000,"width":3000,"src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683"},"aspect_ratio":1.0,"height":3000,"media_type":"image","src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683","width":3000},{"alt":"https:\/\/asset.productmarketingcloud.com\/api\/assetstorage\/3909_761861be-abd6-472f-b120-15d110780fb7","id":30261427142710,"position":7,"preview_image":{"aspect_ratio":1.0,"height":3000,"width":3000,"src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307"},"aspect_ratio":1.0,"height":3000,"media_type":"image","src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307","width":3000}],"requires_selling_plan":false,"selling_plan_groups":[],"content":"Keep all of your flags organized in one easy location! This two-sided flag organizer can hold up to 33 of your favorite house or garden flags, so you'll easily be able to decorate your home appropriately for the season!"}}; 10472 10473 Shopify.current_product.current_variant = {...{"id":42920115601462,"title":"Default Title","option1":"Default Title","option2":null,"option3":null,"sku":"01245","requires_shipping":true,"taxable":true,"featured_image":{"id":38895329902646,"product_id":7616317653046,"position":1,"created_at":"2026-03-03T08:41:45-05:00","updated_at":"2026-03-03T08:41:47-05:00","alt":"https:\/\/asset.productmarketingcloud.com\/api\/assetstorage\/3909_c9b37276-4780-4d3f-baf1-60c599eda033","width":3000,"height":3000,"src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307","variant_ids":[42920115601462]},"available":true,"name":"Flag Organizer","public_title":null,"options":["Default Title"],"price":2500,"weight":363,"compare_at_price":0,"inventory_management":"shopify","barcode":"746851700033","featured_media":{"alt":"https:\/\/asset.productmarketingcloud.com\/api\/assetstorage\/3909_c9b37276-4780-4d3f-baf1-60c599eda033","id":30261426946102,"position":1,"preview_image":{"aspect_ratio":1.0,"height":3000,"width":3000,"src":"\/\/myevergreen.com\/cdn\/shop\/files\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307"}},"requires_selling_plan":false,"selling_plan_allocations":[],"quantity_rule":{"min":1,"max":null,"increment":1}}}; 10474 Shopify.current_product['collections'] = Object.values({...[{"id":285105193014,"handle":"all","title":"All","updated_at":"2026-09-29T10:19:04-04:00","body_html":"\u003cp\u003eBrowse our full collection of seasonal décorâflags, door accents, mats, chimes, and gifts for every occasion.\u003c\/p\u003e","published_at":"2024-08-06T14:13:55-04:00","sort_order":"best-selling","template_suffix":"","disjunctive":true,"rules":[{"column":"variant_inventory","relation":"greater_than","condition":"0"},{"column":"variant_inventory","relation":"equals","condition":"0"}],"published_scope":"global"},{"id":286227300406,"handle":"best-sellers","title":"Best Sellers","updated_at":"2026-09-29T07:12:47-04:00","body_html":"\u003cp\u003eShop our best-selling seasonal décor, from garden flags to door décorâloved for their durability, weather-resistance, and vibrant designs. \u003c\/p\u003e","published_at":"2024-08-26T17:20:16-04:00","sort_order":"manual","template_suffix":"","disjunctive":false,"rules":[{"column":"tag","relation":"equals","condition":"bestseller"},{"column":"variant_inventory","relation":"greater_than","condition":"1"}],"published_scope":"global"},{"id":281947570230,"handle":"fall_flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-16T12:38:54-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Fall Flags","body_html":""},{"id":284973826102,"handle":"flag_accessories","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-08-02T20:02:14-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Flag Accessories","body_html":"","image":{"created_at":"2025-11-17T12:04:36-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.webp?v=1776892799"}},{"id":281867354166,"handle":"flag_poles","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-0
104747-23T09:42:38-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Flag Poles","body_html":"","image":{"created_at":"2025-11-14T15:48:12-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/flag-poles.png?v=1763153292"}},{"id":281867321398,"handle":"flag_stands","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-14T17:03:04-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Flag Stands","body_html":"","image":{"created_at":"2025-12-08T16:33:56-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/myeg-flag-stands-slider.webp?v=1765229636"}},{"id":283121025078,"handle":"flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-06-13T13:52:22-04:00","sort_order":"created-desc","template_suffix":"","published_scope":"global","title":"Flags","body_html":"","image":{"created_at":"2025-11-14T15:39:52-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/flags-slider.png?v=1763152792"}},{"id":281947373622,"handle":"flags_by_season","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-16T12:37:57-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Flags by Season","body_html":""},{"id":281961103414,"handle":"flags_by_size_-_type","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-16T21:37:23-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Flags by Size \u0026 Type","body_html":""},{"id":282015727670,"handle":"garden_flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2025-04-28T11:20:39-04:00","sort_order":"created-desc","template_suffix":"","published_scope":"global","title":"Garden Flags","body_html":"","image":{"created_at":"2025-11-14T16:03:00-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/Large_00b71043-b4b1-4690-8686-f314027d5b9e.webp?v=1776892756"}},{"id":284940107830,"handle":"gifts-under-30","title":"Gifts Under $30","updated_at":"2026-09-29T07:12:47-04:00","body_html":"\u003cp\u003eFind thoughtful gifts under $30âperfect for hosts, holidays, or seasonal celebrations. Décor, drinkware, and more.\u003c\/p\u003e","published_at":"2024-08-01T16:54:48-04:00","sort_order":"created-desc","template_suffix":"","disjunctive":false,"rules":[{"column":"variant_price","relation":"less_than","condition":"30.01"}],"published_scope":"global"},{"id":281867124790,"handle":"house_flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2025-04-28T11:20:39-04:00","sort_order":"created-desc","template_suffix":"","published_scope":"global","title":"House Flags","body_html":"","image":{"created_at":"2025-11-14T16:17:15-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/Large_49b14aea-d0a0-4e6d-96df-af0c68919ca7.webp?v=1776892561"}},{"id":315256930358,"handle":"promotion","title":"Promotion","updated_at":"2026-09-29T07:12:47-04:00","body_html":"","published_at":"2026-04-24T09:49:35-04:00","sort_order":"most-relevant","template_suffix":"","disjunctive":false,"rules":[{"column":"tag","relation":"not_equals","condition":"backorder"}],"published_scope":"web"},{"id":281947471926,"handle":"spring_flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-16T12:38:27-04:00","sort_order":"created-desc","template_suffix":"","published_scope":"global","title":"Spring Flags","body_html":""},{"id":281947504694,"handle":"summer_flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-16T12:38:45-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Summer Flags","body_html":"","image":{"created_at":"2026-04-22T13:30:00-04:00","alt":null,"width":3000,"height":3000,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/Large_a2a80016-ec79-4161-a009-c9b6a0f2aa3e.jpg?v=1776879000"}},{"id":281947602998,"handle":"winter_flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-16T12:39:04-04:00","sort_order":"created-desc","template_suffix":"","published_scope":"global","title":"Winter Flags","body_html":"","image":{"created_at":"2025-11-17T12:01:03-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/winter-flaggs-plp.png?v=1763398863"}}]}); 10475 Shopify.current_product['variants_quantity'] = {}; 10476 10477 Shopify.current_product['variants_quantity']['42920115601462'] = "79" - 0; 10478 10479 10480 10481 Shopify.current_collection = {...null}; 10482 10483 window.SECOMAPP = window.SECOMAPP || {}; 10484 SECOMAPP.fg_codes = []; 10485 SECOMAPP.activateOnlyOnePromoCode = false;
10486 10487 SECOMAPP.localization = [];SECOMAPP.localization.push({ 10488 ...{"shop_locale":{"locale":"en","enabled":true,"primary":true,"published":true}}, 10489 root_url: "/" 10490 }); 10491 10492 SECOMAPP.fgData = {...{"appearance":{"bundle":{"color":{"theme_color":"neutral","item_name_color":"#303030","title_text_color":"#303030","button_text_color":"#FFFFFF","bundle_price_color":"#005BD3","original_price_color":"#005BD3","description_text_color":"#616161","button_background_color":"#303030","widget_background_color":"#F3F3F3","item_card_background_color":"#FFFFFF"},"others":{"hidden_brand_mark":false},"content":{"button_text":"Add bundle to cart","show_description":true,"total_price_text":"Total bundle price","shipping_icon_path":"","select_variant_text":"Select variant","show_discount_each_item":true,"show_discount_on_button":true,"shopify_shipping_icon_path":"shipping-icon-1.png"}},"gift_icon":{"product_page":{"gift_icon":{"size":"50","status":false},"gift_thumbnail":{"status":true,"number_text":"Hangers to Choose From","border_color":"#006346","show_multiple":"together","countdown_text":"Limited time offer","use_old_version":false,"offer_name_color":"#000000","show_number_gift":true,"countdown_time_color":"#006346","show_countdown_timer":false}},"gift_icon_path":"images\/fg-icons\/fg-icon-green.png","collection_page":{"size":"50","status":false},"shopify_gift_icon_path":"fg-icon-green.png"},"mix_match":{"color":{"theme_color":"neutral","item_name_color":"#303030","title_text_color":"#303030","button_text_color":"#FFFFFF","bundle_price_color":"#303030","original_price_color":"#B5B5B5","description_text_color":"#616161","button_background_color":"#303030","widget_background_color":"#F3F3F3","default_label_text_color":"#4F4700","success_label_text_color":"#29845A","item_card_background_color":"#FFFFFF","default_label_background_color":"#FFF8DB","success_label_background_color":"#CDFEE1"},"content":{"tier_style":"label","button_text":"Add bundle to cart","out_stock_text":"Out of stock!","mix_item_header":"Mix item {{itemIndex}}","show_description":true,"total_price_text":"Total bundle price","shipping_icon_path":"","select_product_text":"Choose from {{number}} product(s)","select_variant_title":"Variant","select_collection_text":"Choose from {{number}} collection(s)","show_discount_each_item":true,"show_discount_on_button":true,"shopify_shipping_icon_path":"shipping-icon-1.png"}},"fbt_upsell":{"color":{"item_name":"#303030","theme_color":"neutral","widget_title":"#303030","checkbox_color":"#006C46","widget_subtitle":"#303030","atc_button_color":"#006C46","item_price_after":"#303030","item_price_before":"#808080","total_price_after":"#303030","widget_background":"#F6F6F6","total_price_before":"#616161","cheapest_text_color":"#FFFFFF","item_card_background":"#FFFFFF","atc_button_text_color":"#FFFFFF","current_item_tag_text":"#303030","current_item_tag_color":"#D1D1D1","cheapest_highlight_color":"#FFAA00","shipping_discount_background":"#52A886","shipping_discount_text_color":"#FFFFFF"},"content":{"button_text":"Add selected items","free_item_text":"Free 1 item","total_price_text":"Total price","shipping_icon_path":"https:\/\/d33a6lvgbd0fej.cloudfront.net\/OTY5NWY1LWM0Lm15c2hvcGlmeS5jb20=\/custom-shipping-icon-fbt-upsell_1754947035.png","shopify_shipping_icon_path":"https:\/\/d33a6lvgbd0fej.cloudfront.net\/OTY5NWY1LWM0Lm15c2hvcGlmeS5jb20=\/custom-shipping-icon-fbt-upsell_1754947035.png"},"general":{"widget_layout":"classic","maximum_display":3,"show_discount_amount":true,"show_discount_each_item":true}},"bundle_page":{"color":{"theme_color":"neutral","step_text_color":"#ffffff","atc_button_color":"#DA5256","step_title_color":"#303030","cart_button_color":"#DA5256","page_heading_color":"#303030","product_title_color":"#303030","required_text_color":"#C30006","variant_title_color":"#616161","original_price_color":"#808080","side_bar_title_color":"#303030","step_highlight_color":"#0e2934","atc_button_text_color":"#FFFFFF","cart_button_text_color":"#FFFFFF","discounted_price_color":"#303030","page_sub_heading_color":"#303030","step_description_color":"#616161","default_label_text_color":"#4F4700","success_label_text_color":"#29845A","side_bar_background_color":"#F3F3F3","side_bar_description_color":"#303030","shipping_discount_background":"#F3F3F3","shipping_discount_text_color":"#009174","default_step_background_color":"#009174","default_label_background_color":"#FFF8DB","success_label_background_color":"#CDFEE1"},"content":{"step_text":"Step {{index}}","free_price":"FREE","tier_style":"progress","load_more_text":"Load more","out_stock_text":"Out of stock","read_more_text":"View Product","step_icon_path":"https:\/\/cdn.bogos.io\/OTY5NWY1LWM0Lm15c2hvcGlmeS5jb20=\/custom-step-icon-freegift_1771971700.png","atc_button_text":"Add to bundle","blank_step_text":"Add product to this step","cart_button_text":"Add bundle to cart","show_description":true,"total_price_text":"Total bundle price","summary_icon_path":"images\/summary-icons\/summary-icon-2.png","free_product_title":"ð Free Gift","number_cols_mobile":2,"number_rows_mobile":4,"shipping_icon_path":"images\/shipping-icons\/shipping-icon-1.png","summary_title_text":"Your bundle","choose_variant_text":"Choose variant","number_cols_desktop":4,"number_rows_desktop":3,"maximum_quantity_text":"Maximum item reached","required_product_text":"{{number}} item(s) required","shopify_step_icon_path":"https:\/\/cdn.bogos.io\/OTY5NWY1LWM0Lm15c2hvcGlmeS5jb20=\/custom-step-icon-freegift_1771971700.png","summary_description_text":"Choose items from this page to make your own bundle","shopify_summary_icon_path":"summary-icon-2.png","shopify_shipping_icon_path":"shipping-icon-1.png"}},"gift_slider":{"color":{"add_to_cart_color":"#FFFFFF","offer_title_color":"#000000","product_title_color":"#000000","original_price_color":"#121212","add_to_cart_btn_color":"#00856a","discounted_price_color":"#ea5455","gift_slider_title_color":"#121212","notify_add_gift_active_state_color":"#CDFEE1","notify_add_gift_normal_state_color":"#FFEF9D"},"others":{"gift_img_size":"\u0026width=480\u0026height=480","hidden_brand_mark":false,"disable_use_old_version":true},"general":{"running_text":null,"show_gift_type":"all_in_one","select_gift_btn":"Select variants","show_pagination":true,"use_old_version":false,"gift_popup_title":"Select your free gift!","show_product_title":true,"show_variant_title":false,"add_to_cart_btn_title":"Add to cart","number_product_slider":3,"show_gift_for_customer":"by_products","enable_add_multiple_gifts":false}
10492,"pages_display":{"pages":["all"],"custom":[]},"notify_gift_can_add":{"enable":true,"number_gifts_added":"You have added {{number}} gift product(s)","number_gifts_can_be_added":"You can add {{number}} gift product(s)"},"notify_offer_available":{"text":"ð You have qualified for {{qualifiedOffers}} offer(s)!","enable":true},"disable_slider_checkbox":{"text":"Don't show this offer again","time":5,"enable":true}},"today_offer":{"widget_info":{"show_widget":false,"widget_size":70,"gift_display":"by_products","variant_text":"{{number}} variants selected","widget_title":"FREE Gift With Purchase","see_more_text":"See more ({{number}} products)","widget_position":"bottom_left","widget_subtitle":"Buy 4 Sassafras Inserts, Get a Base Mat Free","number_gift_show":3,"gift_notification":"Your Free Gift Awaits!","icon_widget_title":"Today offer","show_gift_preview":true,"widget_icon_style":"icon","button_redirect_text":"Get offer","show_gift_notification":false},"widget_color":{"offer_title_color":"#303030","widget_title_color":"#303030","offer_default_color":"#F7F7F7","offer_success_color":"#006346","product_title_color":"#303030","discount_price_color":"#006346","original_price_color":"#616161","body_background_color":"#FFFFFF","widget_subtitle_color":"#202020","gift_notification_color":"#616161","header_background_color":"#FFFFFF"},"pages_display":{"pages":["all"],"custom":[]},"widget_icon_path":"https:\/\/d33a6lvgbd0fej.cloudfront.net\/OTY5NWY1LWM0Lm15c2hvcGlmeS5jb20=\/custom-widget-icon-freegift_1741899741.png","shopify_widget_icon_path":"https:\/\/d33a6lvgbd0fej.cloudfront.net\/OTY5NWY1LWM0Lm15c2hvcGlmeS5jb20=\/custom-widget-icon-freegift_1741899741.png"},"cart_discount":{"color":{"widget":{"line_color":"#D0D0D0","theme_color":"blue","open_icon_color":"#616161","tier_text_color":"#303030","title_text_color":"#2332D5","active_icon_color":"#008000","excluded_tier_color":"#cccccc","widget_border_color":"#7B84E6","open_tier_text_color":"#303030","tier_background_color":"#FFFFFF","active_tier_text_color":"#008000","description_text_color":"#616161","widget_background_color":"#FFFFFF"},"congrats":{"theme_color":"blue","background_color":"#EEEFFB","title_text_color":"#2332D5","description_text_color":"#303030"}},"content":{"widget":{"icon":"https:\/\/d33a6lvgbd0fej.cloudfront.net\/bogos-images\/1772523961.png","divide_tiers":false,"widget_style":"style_1","discount_tier_style":"checklist","widget_border_radius":12},"congrats":{"title":"Congratulations!","position":"bottom_right","appear_for":5,"description":"You got {{discount_amount}} off!","border_radius":12}}},"product_add_on":{"color":{"theme_color":"neutral","checkbox_color":"#303030","card_border_color":"#888888","widget_background":"#F6F6F6","product_name_color":"#303030","variant_name_color":"#303030","widget_title_color":"#303030","see_more_text_color":"#808080","widget_border_color":"#FFFFFF","discount_price_color":"#303030","original_price_color":"#CCCCCC","card_background_color":"#F6F6F6","widget_subtitle_color":"#303030"},"content":{"title_align":"left","see_less_text":"See less","see_more_text":"See more","see_more_align":"left","number_cols_compact":1,"number_rows_compact":3,"number_cols_full_width":3,"number_rows_full_width":1},"general":{"card_style":"horizon","widget_style":"style_1","widget_radius":12,"product_img_size":80,"checkbox_position":"left_on_img","enable_img_radius":false}},"quantity_break":{"color":{"tag_color":"#F1F1F1","tier_price":"#303030","tier_title":"#303030","label_color":"#303030","theme_color":"neutral","bundle_price":"#303030","bundle_title":"#303030","tag_text_color":"#303030","label_text_color":"#FFFFFF","tier_description":"#616161","button_text_color":"#FFFFFF","bundle_description":"#303030","bundle_origin_price":"#B5B5B5","button_background_color":"#303030","widget_background_color":"#F3F3F3","item_card_background_color":"#FFFFFF"},"content":{"button_text":"Add bundles to cart","show_description":true,"total_price_text":"Total price","shipping_icon_path":null,"select_variant_text":"Select variant","shopify_shipping_icon_path":"shipping-icon-1.png"}},"select_variant":{"type":"variant","color":{"active_tab_text":"#303030","default_tab_text":"#303030","active_tab_border":"#303030","active_tab_background":"#F0F0F0","active_item_background":"#F0F0F0","default_tab_background":"#F0F0F0"},"config":[],"configs":[]},"checkout_upsell":{"color":{"button_style":"primary","widget_price_color":"base","widget_background_color":"base"},"content":{"widget_message":"Limited Time Offer","widget_button_text":"Add to cart"},"general":{"widget_layout":"stack","widget_active_message":true,"widget_active_compare_at_price":true}},"volume_discount":{"table":{"color":{"row_color":"#FFFFFF","tag_color":"#F1F1F1","line_color":"#E0E0E0","theme_color":"neutral","widget_title":"#303030","row_odd_color":"#FFFFFF","widget_header":"#F3F3F3","row_even_color":"#F5F5F5","tag_text_color":"#303030","label_text_color":"#FFFFFF","tier_title_color":"#303030","widget_sub_title":"#303030","discount_text_color":"#303030","original_price_color":"#FFFFFF","discounted_price_color":"#303030","label_background_color":"#303030","tier_description_color":"#616161"},"hide_line":false,"body_style":"line","text_align":"left","discount_text":"{{discountAmount}} OFF","discount_show_as":"discount_text","show_description":true,"show_original_price":true},"content":{"button_text":"Add bundles to cart","total_price_text":"Total price","shipping_icon_path":"","select_variant_text":"Select variant","shopify_shipping_icon_path":"shipping-icon-1.png"},"default":{"color":{"tag_color":"#F1F1F1","tier_price":"#303030","tier_title":"#303030","label_color":"#303030","theme_color":"neutral","bundle_price":"#303030","bundle_title":"#303030","tag_text_color":"#303030","label_text_color":"#FFFFFF","tier_description":"#616161","button_text_color":"#FFFFFF","bundle_description":"#303030","bundle_origin_price":"#B5B5B5","button_background_color":"#303030","widget_background_color":"#F3F3F3","item_card_background_color":"#FFFFFF"},"show_description":true}},"cheapest_discount":{"color":{"theme_color":"neutral","see_more_color":"#303030","open_icon_color":"#4A4A4A","active_icon_color":"#303030","bullet_text_color":"#808080","widget_title_color":"#303030","product_price_color":"#303030","product_title_color":"#303030","variant_title_color":"#303030","widget_border_color":"#888888","open_tier_text_color":"#303030","button_add_text_color":"#ffffff","widget_subtitle_color":"#616161","active_tier_text_color":"#303030","tiers_background_color":"#F6F6F6","widget_background_color":"#ffffff","excluded_tier_text_color":"#CCCCCC","product_list_label_color":"#616161","button_add_background_color":"#303030"},"content":{"tier_style":"checklist","see_more_text":"See all","show_see_more":true,"number_products":4,"number_cols_mobile":2,"number_rows_mobile":2,"product_list_label":"Choose from these products to get discount","number_cols_desktop":4,"number_rows_desktop":2,"add_product_bt
10492n_text":"Add","show_add_product_btn":true}},"promotion_message":{"text_color":"#ffffff","background_color":"#F72119","show_on_cart_page":true},"thanks_page_upsell":{"color":{"button_style":"primary","widget_price_color":"base","widget_background_color":"transparent"},"content":{"widget_message":"You may also like","widget_button_text":"Add to cart"},"general":{"widget_layout":"carousel","widget_position ":"left","widget_active_message":true,"widget_active_compare_at_price":true}},"bundle_product_page":{"color":{"theme_color":"neutral","quantity_color":"#303030","active_tab_text":"#303030","badge_text_color":"#303030","default_tab_text":"#303030","active_tab_border":"#303030","child_theme_color":"neutral","default_tab_border":"#FFFFFF","product_name_color":"#303030","section_name_color":"#303030","variant_name_color":"#616161","discount_price_color":"#303030","original_price_color":"#808080","section_border_color":"#D0D0D0","active_tab_background":"#F0F0F0","add_item_button_color":"#303030","size_list_label_color":"#303030","badge_background_color":"#FFBB4E","child_label_text_color":"#303030","default_tab_background":"#F0F0F0","total_price_text_color":"#616161","add_bundle_button_color":"#303030","product_card_background":"#F6F6F6","child_product_name_color":"#303030","child_variant_name_color":"#616161","child_widget_title_color":"#303030","child_widget_border_color":"#303030","add_item_button_text_color":"#FFFFFF","add_bundle_button_text_color":"#FFFFFF","child_label_background_color":"#E7E7E7","child_widget_background_color":"#F0F0F0","child_redirect_button_text_color":"#303030"},"content":{"child_label":"Includes in {{number}} bundles","cart_button_text":"Add bundle to cart","total_price_text":"Total bundle price","countdown_message":"Added {{amount_added}} items, {{amount_left}} to go","child_widget_style":"filled_background","show_countdown_on_button":true,"child_show_discount_label":true,"child_redirect_button_label":"Go to bundle","child_products_per_row_mobile":2,"child_products_per_row_desktop":4,"child_show_product_variant_name":true}}},"integration":{"transcy":{"install":false},"judgeme":{"settings":[]}},"settings":{"draft_order":{"discount_code":false,"automatic_discount":false},"gift_format":"same_as_original_products","auto_add_gift":false,"offer_process":"function","sale_channels":null,"sync_quantity":false,"barcode_format":"blank","fraud_protection":null,"notify_via_email":null,"cal_gift_discount":"current_price","gift_title_format":"gift","using_draft_order":false,"select_one_gift_price":true,"admin_api_access_token":null,"manual_input_inventory":false,"include_compare_at_price":false,"cart_and_checkout_validation":{"type":[],"offer":false,"value":{"max_gifts":1,"min_cart_value":1,"min_cart_quantity":1},"status":true,"values":[],"condition":"and"},"fraud_protection_cancel_order":null,"other_original_product_detail":null,"compare_gift_price_with_product":false,"delete_gift_after_turn_off_offer":true,"not_show_gift_if_already_on_cart":false,"type_seo":"number_integer","ab_before_charge":1,"mode_override_checkout":"default","publications":null},"storefront":{"access_token":"e6840989e3bdb4b12a8256cb06c7fd0f","created_at":"2026-09-07T01:04:32Z"}}}; 10493 10494//liquid code to get customer history and customer tag 10495 10496 10497 SECOMAPP.current_template = "product"; 10498 SECOMAPP.pathname = window.location.pathname; 10499 if (SECOMAPP.current_template === "404" && SECOMAPP.pathname?.includes("-sca_clone_freegift")) { 10500 window.location.replace(SECOMAPP.pathname.split("-sca_clone_freegift")[0]); 10501 } else if (SECOMAPP.current_template === "404" && SECOMAPP.pathname?.includes("/collections/sca_fg")) { 10502 window.location.replace(`${Shopify?.routes?.root ?? "/"}collections/all`); 10503 } 10504 10505 SECOMAPP.setCookie = function (e, t, o, n, r) { 10506 let i = new Date; 10507 i.setTime(i.getTime() + 24 * o * 36e5 + 60 * n * 1e3); 10508 let f = "expires=" + i.toUTCString(); 10509 document.cookie = e + "=" + t + ";" + f + (r ? ";path=" + r : ";path=/"); 10510 }; 10511 SECOMAPP.deleteCookie = function (e, t) { 10512 document.cookie = e + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; " + (t ? ";path=" + t : ";path=/") 10513 }; 10514 SECOMAPP.getCookie = function (e) { 10515 for (let t = e + "=", o = document.cookie.split(";"), n = 0; n < o.length; n++) { 10516 let r; 10517 for (r = o[n]; " " === r.charAt(0);) r = r.substring(1); 10518 if (0 === r.indexOf(t)) return r.substring(t.length, r.length) 10519 } 10520 return "" 10521 }; 10522 SECOMAPP.getQueryString = function (key) { 10523 let e = {}; 10524 let t = window.location.search.substring(1).split("&"); 10525 let o = 0; 10526 for (; o < t.length; o++) { 10527 let n = t[o].split("="); 10528 if (void 0 === e[n[0]]) e[n[0]] = decodeURIComponent(n[1]); 10529 else if ("string" == typeof e[n[0]]) { 10530 e[n[0]] = [e[n[0]], decodeURIComponent(n[1])] 10531 } else e[n[0]].push(decodeURIComponent(n[1])) 10532 } 10533 return key ? e?.[key] : e; 10534 }; 10535 10536 SECOMAPP.offer_codes = [
10537 {param: "freegifts_code", cookie: "sca_fg_codes"}, 10538 {param: "bundles_code", cookie: "sca_bundle_codes"}, 10539 {param: "upsells_code", cookie: "sca_upsell_codes"}, 10540 {param: "discounts_code", cookie: "sca_discount_codes"}, 10541 ]; 10542 SECOMAPP.offer_codes.forEach(({param, cookie}) => { 10543 SECOMAPP.fg_codes = []; 10544 SECOMAPP.getCookie(cookie) && (SECOMAPP.fg_codes = JSON.parse(SECOMAPP.getCookie(cookie))); 10545 SECOMAPP.current_code = SECOMAPP.getQueryString(param); 10546 SECOMAPP.current_code && !SECOMAPP.fg_codes.includes(SECOMAPP.current_code) 10547 && (function () { 10548 SECOMAPP.activateOnlyOnePromoCode && (SECOMAPP.fg_codes = []); 10549 SECOMAPP.fg_codes.push(SECOMAPP.current_code); 10550 SECOMAPP.setCookie(cookie, JSON.stringify(SECOMAPP.fg_codes)); 10551 })(); 10552 }); 10553 10554 SECOMAPP.customer = {}; 10555 SECOMAPP.customer.orders = []; 10556 SECOMAPP.customer.freegifts = []; 10557 SECOMAPP.customer.freegifts_v2 = []; 10558 10559 SECOMAPP.customer.email = ""; 10560 SECOMAPP.customer.first_name = ""; 10561 SECOMAPP.customer.last_name = ""; 10562 SECOMAPP.customer.tags = Object.values({...null}); 10563 SECOMAPP.customer.orders_count = "" - 0; 10564 SECOMAPP.customer.total_spent = "" - 0; 10565 SECOMAPP.customer.b2b = "" - 0; 10566 SECOMAPP.market = { 10567 id: "15313797174" - 0, 10568 handle: "us", 10569 }; 10570 10571 10572 // get class name config from settings_data.json 10573 if (!Shopify.scaHandleConfigValue) { 10574 Shopify.scaHandleConfigValue = { 10575 ...null, 10576 ...null 10577 }; 10578 } 10579 10580 // add link proxy 10581 SECOMAPP.freegiftProxy = "/apps/secomapp_freegifts_get_order?ver=3.0"; 10582 10583 SECOMAPP.freegiftProxy = "/apps/secomapp_freegifts_get_order?ver=3.0"; 10584 10585 SECOMAPP.bogosCollectUrl = "https://collect.bogos.io/collect" 10586 SECOMAPP.bogosIntegrationUrl = "https://api.bogos.io/integrations" 10587 10588 // get shop locales 10589 SECOMAPP.shop_locales = Object.values({ 10590 ...[{"shop_locale":{"locale":"en","enabled":true,"primary":true,"published":true}}] 10591 }); 10592 10593 SECOMAPP.current_locale = { ...{"shop_locale":{"locale":"en","enabled":true,"primary":true,"published":true}} } 10594 10595 10596 10597 window.fgGiftIcon = "https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/fg-icon-green_small.png"; 10598 window.fgWidgetIconsObj = { 10599 "widget-icon-1.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/widget-icon-1_small.png', 10600 "widget-icon-2.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/widget-icon-2_small.png', 10601 "widget-icon-3.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/widget-icon-3_small.png', 10602 "widget-icon-4.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/widget-icon-4_small.png', 10603 "widget-icon-5.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/widget-icon-5_small.png', 10604 "widget-icon-6.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/widget-icon-6_small.png', 10605 "widget-icon-7.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/widget-icon-7_small.png', 10606 "widget-icon-8.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/widget-icon-8_small.png' 10607 } 10608 10609 window.fgStepIconsObj = { 10610 "step-icon-1.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/step-icon-1_small.png', 10611 "step-icon-2.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/step-icon-2_small.png', 10612 "step-icon-3.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/step-icon-3_small.png', 10613 "step-icon-4.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/step-icon-4_small.png', 10614 "step-icon-5.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/step-icon-5_small.png', 10615 "step-icon-6.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/step-icon-6_small.png', 10616 "step-icon-7.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/step-icon-7_small.png', 10617 } 10618 10619 window.fgSummaryIconsObj = { 10620 "summary-icon-1.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/summary-icon-1_small.png', 10621 "summary-icon-2.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/summary-icon-2_small.png', 10622 "summary-icon-3.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/summary-icon-3_small.png', 10623 "summary-icon-4.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/summary-icon-4_small.png', 10624 "summary-icon-5.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/summary-icon-5_small.png', 10625 "summary-icon-6.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/summary-icon-6_small.png', 10626 "summary-icon-7.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/summary-icon-7_small.png', 10627 "summary-icon-8.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/summary-icon-8_small.png', 10628 } 10629 10630 window.fgShippingIconsObj = { 10631 "shipping-icon-1.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/shipping-icon-1_small.png', 10632 "shipping-icon-2.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/shipping-icon-2_small.png', 10633 "shipping-icon-3.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/shipping-icon-3_small.png', 10634 "shipping-icon-4.png": 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/shipping-icon-4_small.png', 10635 } 10636 10637 // variable from tools 10638 SECOMAPP.variables = { 10639 ...SECOMAPP.variables, 10640 ...null, 10641 ...[], 10642 shipping_product_img: 'https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/shipping_product_small.png' 10643 } 10644 10645 window.fgResource = { 10646 gift: { 10647 js: ["https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/gift.min.js"] 10648 }, 10649 bundle: { 10650 js: ["https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bundle.min.js"], 10651 css: ["https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bogos.bundle.min.css"] 10652 }, 10653 upsell: { 10654 js: ["https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/upsell.min.js"], 10655 css: ["https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bogos.upsell.min.css"] 10656 }, 10657 discount: { 10658 js: ["https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/discount.min.js"], 10659 css: ["https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bogos.discount.min.css"] 10660 }, 10661 "bundle-page": { 10662 js: ["https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bundle-page.min.js"], 10663 css: ["https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bogos.bundle-page.min.css"] 10664 }, 10665 booster: { 10666 js: ["https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/booster.min.js"], 10667 css: ["https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bogos.booster.min.css"] 10668 } 10669 } 10670</script>
10670 10671
10672<script defer src="https://cdn.bogos.io/OTY5NWY1LWM0Lm15c2hvcGlmeS5jb20=/freegifts_data_1784226006.min.js"></script>
10672 10673<div id="secomapp_freegifts_url" data-url="https://cdn.bogos.io/OTY5NWY1LWM0Lm15c2hvcGlmeS5jb20=/freegifts_data_1784226006.min.js"></div> 10674 10675 10676<div id="bogos-gift-script" data-url="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/gift.min.js"></div> 10677<div id="bogos-bundle-script" data-url="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bundle.min.js"></div> 10678<div id="bogos-upsell-script" data-url="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/upsell.min.js"></div> 10679<div id="bogos-discount-script" data-url="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/discount.min.js"></div> 10680<div id="bogos-bundle-page-script" data-url="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bundle-page.min.js"></div> 10681<div id="bogos-booster-script" data-url="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/booster.min.js"></div> 10682<div id="bogos-booster-page-script" data-url="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/booster-page.min.js"></div> 10683 10684 10685<div id="bogos-bundle-style" data-url="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bogos.bundle.min.css"></div> 10686<div id="bogos-upsell-style" data-url="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bogos.upsell.min.css"></div> 10687<div id="bogos-discount-style" data-url="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bogos.discount.min.css"></div> 10688<div id="bogos-bundle-page-style" data-url="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bogos.bundle-page.min.css"></div> 10689<div id="bogos-booster-style" data-url="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bogos.booster.min.css"></div> 10690<div id="bogos-booster-page-style" data-url="https://cdn.shopify.com/extensions/01a0d1bb-e419-72e0-b3db-9b9890abbb77/freegifts-231/assets/bogos.booster-page.min.css"></div> 10691<!-- END app snippet --> 10692 10693 10694<!-- BEGIN app snippet: search --> 10695<!-- END app snippet --> 10696 10697 10698 10699</div><div id="shopify-block-AcVNFMzZ6c2NvTGpQT__15079184273603081885" class="shopify-block shopify-app-block"> 10700 10701 10702 10703 10704 10705
10706<script> 10707 10708 window.essentialOrderValueBoosterConfigs = []; 10709 window.essentialOrderValueBoosterProductsData = []; 10710 10711 10712 window.essentialOrderValueBoosterPageTemplate = "product" 10713 window.essentialOrderValueBoosterMeta = { 10714 productData: "{\"id\":7616317653046,\"title\":\"Flag Organizer\",\"handle\":\"01245\",\"description\":\"Keep all of your flags organized in one easy location! This two-sided flag organizer can hold up to 33 of your favorite house or garden flags, so you'll easily be able to decorate your home appropriately for the season!\",\"published_at\":\"2025-05-30T13:45:58-04:00\",\"created_at\":\"2024-07-22T11:21:52-04:00\",\"vendor\":\"Evergreen\",\"type\":\"Flag Accessories\",\"tags\":[\"000003\",\"bestseller\",\"Everyday\",\"price-change-job-active\"],\"price\":2500,\"price_min\":2500,\"price_max\":2500,\"available\":true,\"price_varies\":false,\"compare_at_price\":0,\"compare_at_price_min\":0,\"compare_at_price_max\":0,\"compare_at_price_varies\":false,\"variants\":[{\"id\":42920115601462,\"title\":\"Default Title\",\"option1\":\"Default Title\",\"option2\":null,\"option3\":null,\"sku\":\"01245\",\"requires_shipping\":true,\"taxable\":true,\"featured_image\":{\"id\":38895329902646,\"product_id\":7616317653046,\"position\":1,\"created_at\":\"2026-03-03T08:41:45-05:00\",\"updated_at\":\"2026-03-03T08:41:47-05:00\",\"alt\":\"https:\\\/\\\/asset.productmarketingcloud.com\\\/api\\\/assetstorage\\\/3909_c9b37276-4780-4d3f-baf1-60c599eda033\",\"width\":3000,\"height\":3000,\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307\",\"variant_ids\":[42920115601462]},\"available\":true,\"name\":\"Flag Organizer\",\"public_title\":null,\"options\":[\"Default Title\"],\"price\":2500,\"weight\":363,\"compare_at_price\":0,\"inventory_management\":\"shopify\",\"barcode\":\"746851700033\",\"featured_media\":{\"alt\":\"https:\\\/\\\/asset.productmarketingcloud.com\\\/api\\\/assetstorage\\\/3909_c9b37276-4780-4d3f-baf1-60c599eda033\",\"id\":30261426946102,\"position\":1,\"preview_image\":{\"aspect_ratio\":1.0,\"height\":3000,\"width\":3000,\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307\"}},\"requires_selling_plan\":false,\"selling_plan_allocations\":[],\"quantity_rule\":{\"min\":1,\"max\":null,\"increment\":1}}],\"images\":[\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307\",\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307\",\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307\",\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307\",\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307\",\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683\",\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307\"],\"featured_image\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307\",\"options\":[\"Title\"],\"media\":[{\"alt\":\"https:\\\/\\\/asset.productmarketingcloud.com\\\/api\\\/assetstorage\\\/3909_c9b37276-4780-4d3f-baf1-60c599eda033\",\"id\":30261426946102,\"position\":1,\"preview_image\":{\"aspect_ratio\":1.0,\"height\":3000,\"width\":3000,\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307\"},\"aspect_ratio\":1.0,\"height\":3000,\"media_type\":\"image\",\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.jpg?v=1772545307\",\"width\":3000},{\"alt\":\"https:\\\/\\\/asset.productmarketingcloud.com\\\/api\\\/assetstorage\\\/3909_4bdb1383-1b62-4776-919e-642fbf3de913\",\"id\":30261426978870,\"position\":2,\"preview_image\":{\"aspect_ratio\":1.
107140,\"height\":3000,\"width\":3000,\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307\"},\"aspect_ratio\":1.0,\"height\":3000,\"media_type\":\"image\",\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_013845bb-ec69-4329-b66b-046c15b4a64d.jpg?v=1772545307\",\"width\":3000},{\"alt\":\"https:\\\/\\\/asset.productmarketingcloud.com\\\/api\\\/assetstorage\\\/3909_9086bef2-c4ed-4a4d-a86f-74fa581e2583\",\"id\":30261427011638,\"position\":3,\"preview_image\":{\"aspect_ratio\":1.0,\"height\":3000,\"width\":3000,\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307\"},\"aspect_ratio\":1.0,\"height\":3000,\"media_type\":\"image\",\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_05c0df60-2f45-4dbc-96b1-77545f38fbe9.jpg?v=1772545307\",\"width\":3000},{\"alt\":\"https:\\\/\\\/asset.productmarketingcloud.com\\\/api\\\/assetstorage\\\/3909_50c16b2e-148e-4117-a4f7-34cb131df641\",\"id\":30261427044406,\"position\":4,\"preview_image\":{\"aspect_ratio\":1.0,\"height\":3000,\"width\":3000,\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307\"},\"aspect_ratio\":1.0,\"height\":3000,\"media_type\":\"image\",\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_f0036d1f-d4f2-4594-9e3e-94d5f6eef08e.jpg?v=1772545307\",\"width\":3000},{\"alt\":\"https:\\\/\\\/asset.productmarketingcloud.com\\\/api\\\/assetstorage\\\/3909_78d85916-fa40-48bb-bb77-5a10608cfb8a\",\"id\":30261427077174,\"position\":5,\"preview_image\":{\"aspect_ratio\":1.0,\"height\":3000,\"width\":3000,\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307\"},\"aspect_ratio\":1.0,\"height\":3000,\"media_type\":\"image\",\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_afd26bcf-2329-48de-8be2-0384a36d28d5.jpg?v=1772545307\",\"width\":3000},{\"alt\":\"https:\\\/\\\/asset.productmarketingcloud.com\\\/api\\\/assetstorage\\\/3909_f2f9b15d-bbf0-46a4-bd85-94be47651f9c\",\"id\":32716987531318,\"position\":6,\"preview_image\":{\"aspect_ratio\":1.0,\"height\":3000,\"width\":3000,\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683\"},\"aspect_ratio\":1.0,\"height\":3000,\"media_type\":\"image\",\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_4c3a32bf-cfe1-48e5-9dda-e8b7ce910a3d.jpg?v=1790016683\",\"width\":3000},{\"alt\":\"https:\\\/\\\/asset.productmarketingcloud.com\\\/api\\\/assetstorage\\\/3909_761861be-abd6-472f-b120-15d110780fb7\",\"id\":30261427142710,\"position\":7,\"preview_image\":{\"aspect_ratio\":1.0,\"height\":3000,\"width\":3000,\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307\"},\"aspect_ratio\":1.0,\"height\":3000,\"media_type\":\"image\",\"src\":\"\\\/\\\/myevergreen.com\\\/cdn\\\/shop\\\/files\\\/Large_4327820f-80dc-4c84-9989-9fa4ad962389.jpg?v=1772545307\",\"width\":3000}],\"requires_selling_plan\":false,\"selling_plan_groups\":[],\"content\":\"Keep all of your flags organized in one easy location! This two-sided flag organizer can hold up to 33 of your favorite house or garden flags, so you'll easily be able to decorate your home appropriately for the season!\"}", 10715 cartItems: [], 10716 cartProducts: [], 10717 mainCurrency: "USD", 10718 productCollections: [{"id":285105193014,"handle":"all","title":"All","updated_at":"2026-09-29T10:19:04-04:00","body_html":"\u003cp\u003eBrowse our full collection of seasonal décorâflags, door accents, mats, chimes, and gifts for every occasion.\u003c\/p\u003e","published_at":"2024-08-06T14:13:55-04:00","sort_order":"best-selling","template_suffix":"","disjunctive":true,"rules":[{"column":"variant_inventory","relation":"greater_than","condition":"0"},{"column":"variant_inventory","relation":"equals","condition":"0"}],"published_scope":"global"},{"id":286227300406,"handle":"best-sellers","title":"Best Sellers","updated_at":"2026-09-29T07:12:47-04:00","body_html":"\u003cp\u003eShop our best-selling seasonal décor, from garden flags to door décorâloved for their durability, weather-resistance, and vibrant designs. \u003c\/p\u003e","published_at":"2024-08-26T17:20:16-04:00","sort_order":"manual","template_suffix":"","disjunctive":false,"rules":[{"column":"tag","relation":"equals","condition":"bestseller"},{"column":"variant_inventory","relation":"greater_than","condition":"1"}],"published_scope":"global"},{"id":281947570230,"handle":"fall_flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-16T12:38:54-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Fall Flags","body_html":""},{"id":284973826102,"handle":"flag_accessories","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-08-02T20:02:14-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Flag Accessories","body_html":"","image":{"created_at":"2025-11-17T12:04:36-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/Large_0c02a7bf-0db5-4906-8432-e204b6d5f4bd.webp?v=1776892799"}},{"id":281867354166,"handle":"flag_poles","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-0
107187-23T09:42:38-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Flag Poles","body_html":"","image":{"created_at":"2025-11-14T15:48:12-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/flag-poles.png?v=1763153292"}},{"id":281867321398,"handle":"flag_stands","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-14T17:03:04-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Flag Stands","body_html":"","image":{"created_at":"2025-12-08T16:33:56-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/myeg-flag-stands-slider.webp?v=1765229636"}},{"id":283121025078,"handle":"flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-06-13T13:52:22-04:00","sort_order":"created-desc","template_suffix":"","published_scope":"global","title":"Flags","body_html":"","image":{"created_at":"2025-11-14T15:39:52-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/flags-slider.png?v=1763152792"}},{"id":281947373622,"handle":"flags_by_season","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-16T12:37:57-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Flags by Season","body_html":""},{"id":281961103414,"handle":"flags_by_size_-_type","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-16T21:37:23-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Flags by Size \u0026 Type","body_html":""},{"id":282015727670,"handle":"garden_flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2025-04-28T11:20:39-04:00","sort_order":"created-desc","template_suffix":"","published_scope":"global","title":"Garden Flags","body_html":"","image":{"created_at":"2025-11-14T16:03:00-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/Large_00b71043-b4b1-4690-8686-f314027d5b9e.webp?v=1776892756"}},{"id":284940107830,"handle":"gifts-under-30","title":"Gifts Under $30","updated_at":"2026-09-29T07:12:47-04:00","body_html":"\u003cp\u003eFind thoughtful gifts under $30âperfect for hosts, holidays, or seasonal celebrations. Décor, drinkware, and more.\u003c\/p\u003e","published_at":"2024-08-01T16:54:48-04:00","sort_order":"created-desc","template_suffix":"","disjunctive":false,"rules":[{"column":"variant_price","relation":"less_than","condition":"30.01"}],"published_scope":"global"},{"id":281867124790,"handle":"house_flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2025-04-28T11:20:39-04:00","sort_order":"created-desc","template_suffix":"","published_scope":"global","title":"House Flags","body_html":"","image":{"created_at":"2025-11-14T16:17:15-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/Large_49b14aea-d0a0-4e6d-96df-af0c68919ca7.webp?v=1776892561"}},{"id":315256930358,"handle":"promotion","title":"Promotion","updated_at":"2026-09-29T07:12:47-04:00","body_html":"","published_at":"2026-04-24T09:49:35-04:00","sort_order":"most-relevant","template_suffix":"","disjunctive":false,"rules":[{"column":"tag","relation":"not_equals","condition":"backorder"}],"published_scope":"web"},{"id":281947471926,"handle":"spring_flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-16T12:38:27-04:00","sort_order":"created-desc","template_suffix":"","published_scope":"global","title":"Spring Flags","body_html":""},{"id":281947504694,"handle":"summer_flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-16T12:38:45-04:00","sort_order":"best-selling","template_suffix":"","published_scope":"global","title":"Summer Flags","body_html":"","image":{"created_at":"2026-04-22T13:30:00-04:00","alt":null,"width":3000,"height":3000,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/Large_a2a80016-ec79-4161-a009-c9b6a0f2aa3e.jpg?v=1776879000"}},{"id":281947602998,"handle":"winter_flags","updated_at":"2026-09-29T07:12:47-04:00","published_at":"2024-05-16T12:39:04-04:00","sort_order":"created-desc","template_suffix":"","published_scope":"global","title":"Winter Flags","body_html":"","image":{"created_at":"2025-11-17T12:01:03-05:00","alt":null,"width":900,"height":900,"src":"\/\/myevergreen.com\/cdn\/shop\/collections\/winter-flaggs-plp.png?v=1763398863"}}], 10719 }; 10720 10721 window.essentialOrderValueBoosterTranslations = { 10722 previousSlide: "Previous slide", 10723 nextSlide: "Next slide", 10724 regularPrice: "Regular price", 10725 salePrice: "Sale price", 10726 slide: "Slide" 10727 }; 10728</script>
10728 10729 10730 10731
10732<script src="https://cdn.shopify.com/extensions/01a0e324-d4fe-7ea8-942e-1256f34b87e4/order-value-booster-355/assets/free_shipping_bar_essential_apps.min.js" defer crossorigin="anonymous"></script>
10732 10733
10734<script> 10735 10736</script>
10736 10737 10738 10739 10740 10741</div><div id="shopify-block-AR2FMSW9nNERWcU9kV__6174324309569838175" class="shopify-block shopify-app-block"> 10742 10743 10744<div class="smile-shopify-init" 10745 data-channel-key="channel_W05kb9Q5Zi8sv18E6WtUuSZd" 10746 10747></div> 10748 10749 10750</div><div id="shopify-block-AVnROZDByMDdzdWs5Z__7415279170309610466" class="shopify-block shopify-app-block">
10751<script> 10752 10753 10754 10755 10756 10757</script>
10757 10758 10759 10760 10761 10762</div>
10762<script src="https://cdn.shopify.com/storefront/standard-actions.js" type="module" data-source-attribution="shopify.standard_actions"></script>
10762 10763</body> 10764</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.