{"version":3,"file":"product-details-page.2b2ea197b8a2be0cdd4a.js?ssi=0","mappings":"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","sources":["webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/businessdesk-edit-link/svgs/edit_pencil_white.svg","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/platform-explainer-header-desktop.svg","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/platform-explainer-header-mobile.svg","webpack://@logos/commerceweb-frontend/./Scripts/site/clients/products-client.js","webpack://@logos/commerceweb-frontend/./Scripts/site/util/hooks/use-in-view.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/recommendations/recommendations-context.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/recommendations/recommendations-carousel.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/recommendations/buy-in-collection.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/recommendations/containing-subscriptions.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/recommendations/customers-also-bought.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/featured-products/featured-products.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/featured-products/index.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/clients/reviews-client.js","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/reviews/rating-selector.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/reviews/text-area.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/reviews/review-editor.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/reviews/review-header.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/reviews/link-button.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/reviews/review-item.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/reviews/reviews-list.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/reviews/sort-mode-selector.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/reviews/divider.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/reviews/reviews-anchor.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/reviews/index.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-content-sections/display-content.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-content-sections/execute-scripts.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-content-sections/embedded-video.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-content-sections/embedded-video-section.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-content-sections/product-details-metadata.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-content-sections/author-bio-section.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-content-sections/section-config.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-content-sections/index.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/right-column/authors-and-publishers.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/sale-price-popover.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/prices.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/subscription-promotion/index.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/purchase-actions.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/gallery.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/types.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/logos-edition-callout/collapsible-callout.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/logos-edition-callout/video-popover.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/logos-edition-callout/index.tsx","webpack://@logos/commerceweb-frontend/javascript/node_modules/@radix-ui/react-dialog/dist/index.mjs","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/see-inside.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/right-column/preordered-product-label.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/selected-sku-and-quantity-util.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/right-column/sku-selector.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/right-column/metadata-row.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/right-column/review-summary.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/right-column/product-description.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/right-column/details.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/sticky-add-to-cart/sticky-add-to-cart-bar.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/sticky-add-to-cart/sticky-add-to-cart-content.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/sticky-add-to-cart/sticky-add-to-cart.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/adzone-block.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/time-sensitive-callout-block.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/platform-explainer.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/breadcrumbs.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/businessdesk-edit-link/index.tsx","webpack://@logos/commerceweb-frontend/javascript/node_modules/swiper/modules/keyboard.mjs","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/left-column/sample-pages.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/left-column/index.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/library-greeting.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/hooks/use-unowned-resources.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/index.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/hooks/use-see-inside-url.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/product/product-details-page/sticky-add-to-cart/use-sticky-add-to-cart-handler.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/util/hooks/use-resource-formats-and-texts.js","webpack://@logos/commerceweb-frontend/javascript/node_modules/js-cookie/dist/js.cookie.mjs","webpack://@logos/commerceweb-frontend/javascript/node_modules/lucide-react/dist/esm/icons/heart.mjs","webpack://@logos/commerceweb-frontend/javascript/node_modules/lucide-react/dist/esm/icons/x.mjs"],"sourcesContent":["module.exports = \"data:image/svg+xml,%3csvg width='12' height='12' viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3e%3cg fill='%23FFF' fill-rule='evenodd'%3e%3cpath d='M8.442 1.99l-7.03 7.074v.818h.892L9.292 2.82l-.85-.83zm2.346.32c.28.272.28.72.006 1l-7.9 7.984H0V8.482L7.925.505c.278-.28.727-.285 1.008-.01l1.855 1.814z'/%3e%3cpath d='M8.998 4.472L7.116 2.355l-1.055.937L7.944 5.41M4.94 10.588h6.455v.807H4.94'/%3e%3c/g%3e%3c/svg%3e\"","module.exports = \"data:image/svg+xml,%3csvg width='290' height='134' viewBox='0 0 290 134' fill='none' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M228.773 11H78.233C76.1063 11 74.3822 12.7081 74.3822 14.8151V129.49C74.3822 131.597 76.1063 133.305 78.233 133.305H228.773C230.899 133.305 232.623 131.597 232.623 129.49V14.8151C232.623 12.7081 230.899 11 228.773 11Z' fill='%23EEEEEE'/%3e%3crect x='260.226' y='11' width='29.0317' height='43.206' rx='2.21139' fill='%2306296C'/%3e%3cline x1='266.509' y1='15.2694' x2='266.509' y2='49.9366' stroke='%23005EC3'/%3e%3crect x='19.7068' y='18.0419' width='29.0317' height='43.206' rx='2.21139' fill='%23509EE5'/%3e%3cline x1='25.3299' y1='22.3112' x2='25.3299' y2='56.9785' stroke='%23005EC3'/%3e%3crect x='19.7446' y='80.5943' width='29.0317' height='43.206' rx='2.21139' fill='%23D8EFFC'/%3e%3cline x1='25.1969' y1='84.8636' x2='25.1969' y2='119.531' stroke='white'/%3e%3cpath d='M225.546 129.115H90.5046C89.277 129.115 88.2827 128.119 88.2827 126.891V18.412C88.2827 17.1841 89.277 16.1885 90.5046 16.1885H126.208C127.435 16.1885 128.43 17.1841 128.43 18.412V21.8087C128.43 23.0366 129.424 24.0322 130.651 24.0322H225.546C226.774 24.0322 227.768 25.0278 227.768 26.2557V126.891C227.768 128.119 226.774 129.115 225.546 129.115Z' fill='white'/%3e%3cpath d='M128.107 17.2729C127.718 16.624 127.014 16.1885 126.208 16.1885H90.5046C89.6981 16.1885 88.9946 16.624 88.6057 17.2729H128.107Z' fill='%234C9DE8'/%3e%3crect x='94.7697' y='30.5808' width='63.3574' height='92.7306' fill='%23005EC3'/%3e%3crect x='158.127' y='30.5808' width='63.3574' height='92.7306' fill='%23509EE5'/%3e%3cline x1='101.088' y1='36.9118' x2='145.319' y2='36.9118' stroke='white'/%3e%3cline x1='101.088' y1='71.2375' x2='145.319' y2='71.2375' stroke='white'/%3e%3cline x1='101.088' y1='105.563' x2='145.319' y2='105.563' stroke='white'/%3e%3cline x1='101.088' y1='48.3537' x2='145.319' y2='48.3537' stroke='white'/%3e%3cline x1='101.088' y1='82.6793' x2='145.319' y2='82.6793' stroke='white'/%3e%3cline x1='101.088' y1='117.005' x2='145.319' y2='117.005' stroke='white'/%3e%3cline x1='101.088' y1='59.7956' x2='145.319' y2='59.7956' stroke='white'/%3e%3cline x1='101.088' y1='94.1212' x2='145.319' y2='94.1212' stroke='white'/%3e%3cline x1='168.715' y1='36.9118' x2='212.946' y2='36.9118' stroke='white'/%3e%3cline x1='168.715' y1='71.2375' x2='212.946' y2='71.2375' stroke='white'/%3e%3cline x1='168.715' y1='105.563' x2='212.946' y2='105.563' stroke='white'/%3e%3cline x1='168.715' y1='48.3537' x2='212.946' y2='48.3537' stroke='white'/%3e%3cline x1='168.715' y1='82.6793' x2='212.946' y2='82.6793' stroke='white'/%3e%3cline x1='168.715' y1='117.005' x2='212.946' y2='117.005' stroke='white'/%3e%3cline x1='168.715' y1='59.7956' x2='212.946' y2='59.7956' stroke='white'/%3e%3cline x1='168.715' y1='94.1212' x2='212.946' y2='94.1212' stroke='white'/%3e%3cpath d='M139.183 48.9391C139.183 49.8924 138.381 50.8956 136.762 51.6902C135.175 52.4688 132.949 52.9646 130.462 52.9646C127.975 52.9646 125.748 52.4688 124.161 51.6902C122.542 50.8956 121.74 49.8924 121.74 48.9391C121.74 47.9857 122.542 46.9825 124.161 46.1879C125.748 45.4093 127.975 44.9135 130.462 44.9135C132.949 44.9135 135.175 45.4093 136.762 46.1879C138.381 46.9825 139.183 47.9857 139.183 48.9391Z' stroke='white'/%3e%3cpath d='M115.175 105.986C115.175 106.958 114.505 107.904 113.281 108.628C112.064 109.346 110.359 109.802 108.457 109.802C106.554 109.802 104.849 109.346 103.633 108.628C102.408 107.904 101.738 106.958 101.738 105.986C101.738 105.014 102.408 104.068 103.633 103.345C104.849 102.627 106.554 102.171 108.457 102.171C110.359 102.171 112.064 102.627 113.281 103.345C114.505 104.068 115.175 105.014 115.175 105.986Z' stroke='white' stroke-width='0.737129'/%3e%3cpath d='M208.859 59.0148C208.859 59.5999 208.566 60.2075 207.928 60.8124C207.289 61.4184 206.338 61.9872 205.122 62.4753C202.691 63.4505 199.299 64.065 195.527 64.065C191.754 64.065 188.362 63.4505 185.932 62.4753C184.715 61.9872 183.764 61.4184 183.125 60.8124C182.487 60.2075 182.194 59.5999 182.194 59.0148C182.194 58.4297 182.487 57.8221 183.125 57.2172C183.764 56.6112 184.715 56.0424 185.932 55.5543C188.362 54.579 191.754 53.9646 195.527 53.9646C199.299 53.9646 202.691 54.579 205.122 55.5543C206.338 56.0424 207.289 56.6112 207.928 57.2172C208.566 57.8221 208.859 58.4297 208.859 59.0148Z' stroke='white'/%3e%3crect x='78.5631' y='26.0861' width='4.38947' height='4.38947' rx='2.19474' fill='%23C7C7C7'/%3e%3crect x='78.5631' y='32.6703' width='4.38947' height='4.38947' rx='2.19474' fill='%23C7C7C7'/%3e%3crect x='78.5631' y='41.4492' width='4.38947' height='4.38947' rx='2.19474' fill='%23C7C7C7'/%3e%3cpath d='M116.971 42.5466C108.939 37.5892 85.6229 28.3252 56.6157 30.9278' stroke='%2306296C'/%3e%3cpath d='M100.51 99.68C91.5665 97.7628 69.6077 95.2841 53.3236 100.707' stroke='%2306296C'/%3e%3cpath d='M210.247 54.6176C216.122 47.1817 233.346 32.8676 255.239 35.0984' stroke='%2306296C'/%3e%3cg filter='url(%23filter0_ddd_154_1007)'%3e%3crect x='16' y='19.4319' width='7.41361' height='7.41361' rx='2' fill='white'/%3e%3c/g%3e%3cpath d='M21.5602 24.4657L21.5555 21.8052C21.5543 21.4927 21.3284 21.2853 21.0332 21.2853L18.362 21.2901C18.0721 21.2961 17.8534 21.5029 17.8534 21.8118L17.8582 24.4752C17.8582 24.5565 17.8743 24.63 17.9024 24.6951L18.7474 23.8526C18.7588 23.8412 18.76 23.8245 18.751 23.8113C18.5896 23.5819 18.5078 23.2932 18.549 22.9837C18.6195 22.4518 19.0576 22.0299 19.5912 21.9785C20.328 21.9074 20.9411 22.5217 20.87 23.2586C20.818 23.7964 20.3902 24.2356 19.8541 24.3013C19.5392 24.3402 19.2464 24.2517 19.0163 24.0832C19.0038 24.0737 18.9858 24.0749 18.9745 24.0862L18.1247 24.9336C18.1958 24.97 18.2783 24.991 18.3667 24.9927L21.0397 24.988C21.3349 24.9874 21.5596 24.7788 21.5596 24.4663L21.5602 24.4657Z' fill='%23005EC3'/%3e%3cpath d='M19.7066 22.2661C19.2243 22.2661 18.8335 22.6569 18.8335 23.1391C18.8335 23.6214 19.2243 24.0122 19.7066 24.0122C20.1888 24.0122 20.5796 23.6214 20.5796 23.1391C20.5796 22.6569 20.1888 22.2661 19.7066 22.2661ZM20.1308 23.1499H19.8428V23.6883H19.5709V23.1499H19.2829V22.8774H19.5709V22.5893H19.8428V22.8774H20.1308V23.1499Z' fill='%23005EC3'/%3e%3cg filter='url(%23filter1_ddd_154_1007)'%3e%3crect x='16' y='83.3744' width='7.41361' height='7.41361' rx='2' fill='white'/%3e%3c/g%3e%3cpath d='M21.5602 88.4081L21.5555 85.7477C21.5543 85.4351 21.3284 85.2278 21.0332 85.2278L18.362 85.2326C18.0721 85.2385 17.8534 85.4453 17.8534 85.7543L17.8582 88.4177C17.8582 88.499 17.8743 88.5725 17.9024 88.6376L18.7474 87.795C18.7588 87.7836 18.76 87.7669 18.751 87.7538C18.5896 87.5243 18.5078 87.2357 18.549 86.9261C18.6195 86.3943 19.0576 85.9724 19.5912 85.921C20.328 85.8499 20.9411 86.4642 20.87 87.201C20.818 87.7388 20.3902 88.1781 19.8541 88.2438C19.5392 88.2826 19.2464 88.1942 19.0163 88.0257C19.0038 88.0161 18.9858 88.0173 18.9745 88.0287L18.1247 88.876C18.1958 88.9125 18.2783 88.9334 18.3667 88.9352L21.0397 88.9304C21.3349 88.9298 21.5596 88.7213 21.5596 88.4087L21.5602 88.4081Z' fill='%23005EC3'/%3e%3cpath d='M19.7066 86.2085C19.2243 86.2085 18.8335 86.5993 18.8335 87.0816C18.8335 87.5638 19.2243 87.9546 19.7066 87.9546C20.1888 87.9546 20.5796 87.5638 20.5796 87.0816C20.5796 86.5993 20.1888 86.2085 19.7066 86.2085ZM20.1308 87.0923H19.8428V87.6307H19.5709V87.0923H19.2829V86.8198H19.5709V86.5318H19.8428V86.8198H20.1308V87.0923Z' fill='%23005EC3'/%3e%3cg filter='url(%23filter2_ddd_154_1007)'%3e%3crect x='256.479' y='13.4084' width='7.41361' height='7.41361' rx='2' fill='white'/%3e%3c/g%3e%3cpath d='M262.039 18.4421L262.034 15.7817C262.033 15.4692 261.807 15.2618 261.512 15.2618L258.841 15.2666C258.551 15.2726 258.332 15.4793 258.332 15.7883L258.337 18.4517C258.337 18.533 258.353 18.6065 258.381 18.6716L259.226 17.829C259.238 17.8177 259.239 17.8009 259.23 17.7878C259.069 17.5583 258.987 17.2697 259.028 16.9601C259.099 16.4283 259.537 16.0064 260.07 15.955C260.807 15.8839 261.42 16.4982 261.349 17.235C261.297 17.7729 260.869 18.2121 260.333 18.2778C260.018 18.3167 259.725 18.2282 259.495 18.0597C259.483 18.0501 259.465 18.0513 259.454 18.0627L258.604 18.9101C258.675 18.9465 258.757 18.9674 258.846 18.9692L261.519 18.9644C261.814 18.9638 262.039 18.7553 262.039 18.4427L262.039 18.4421Z' fill='%23005EC3'/%3e%3cpath d='M260.186 16.2425C259.703 16.2425 259.313 16.6333 259.313 17.1156C259.313 17.5978 259.703 17.9886 260.186 17.9886C260.668 17.9886 261.059 17.5978 261.059 17.1156C261.059 16.6333 260.668 16.2425 260.186 16.2425ZM260.61 17.1263H260.322V17.6648H260.05V17.1263H259.762V16.8538H260.05V16.5658H260.322V16.8538H260.61V17.1263Z' fill='%23005EC3'/%3e%3cpath d='M84.1126 21.7541L84.1042 17.0983C84.1021 16.5514 83.7068 16.1885 83.1902 16.1885L78.5156 16.1969C78.0084 16.2073 77.6256 16.5692 77.6256 17.1098L77.634 21.7708C77.634 21.9131 77.6622 22.0417 77.7114 22.1557L79.1901 20.6811C79.21 20.6613 79.2121 20.632 79.1964 20.609C78.914 20.2074 78.7708 19.7023 78.8429 19.1606C78.9663 18.2299 79.7329 17.4915 80.6667 17.4016C81.9562 17.2772 83.0291 18.3522 82.9047 19.6416C82.8137 20.5828 82.0649 21.3515 81.1269 21.4665C80.5758 21.5345 80.0633 21.3797 79.6607 21.0848C79.6387 21.0681 79.6074 21.0702 79.5875 21.09L78.1004 22.5729C78.2249 22.6367 78.3692 22.6733 78.524 22.6765L83.2017 22.6681C83.7183 22.6671 84.1115 22.3021 84.1115 21.7551L84.1126 21.7541Z' fill='%23005EC3'/%3e%3cpath d='M80.8687 17.9048C80.0248 17.9048 79.3408 18.5887 79.3408 19.4326C79.3408 20.2766 80.0248 20.9605 80.8687 20.9605C81.7126 20.9605 82.3966 20.2766 82.3966 19.4326C82.3966 18.5887 81.7126 17.9048 80.8687 17.9048ZM81.6112 19.4515H81.1071V20.3937H80.6313V19.4515H80.1272V18.9746H80.6313V18.4705H81.1071V18.9746H81.6112V19.4515Z' fill='%23005EC3'/%3e%3cdefs%3e%3cfilter id='filter0_ddd_154_1007' x='0' y='6.43195' width='39.4136' height='39.4136' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3e%3cfeFlood flood-opacity='0' result='BackgroundImageFix'/%3e%3cfeColorMatrix in='SourceAlpha' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0' result='hardAlpha'/%3e%3cfeMorphology radius='3' operator='erode' in='SourceAlpha' result='effect1_dropShadow_154_1007'/%3e%3cfeOffset dy='5'/%3e%3cfeGaussianBlur stdDeviation='2.5'/%3e%3cfeComposite in2='hardAlpha' operator='out'/%3e%3cfeColorMatrix type='matrix' values='0 0 0 0 0.431373 0 0 0 0 0.513726 0 0 0 0 0.717647 0 0 0 0.2 0'/%3e%3cfeBlend mode='normal' in2='BackgroundImageFix' result='effect1_dropShadow_154_1007'/%3e%3cfeColorMatrix in='SourceAlpha' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0' result='hardAlpha'/%3e%3cfeMorphology radius='2' operator='dilate' in='SourceAlpha' result='effect2_dropShadow_154_1007'/%3e%3cfeOffset dy='3'/%3e%3cfeGaussianBlur stdDeviation='7'/%3e%3cfeComposite in2='hardAlpha' operator='out'/%3e%3cfeColorMatrix type='matrix' values='0 0 0 0 0.431373 0 0 0 0 0.513726 0 0 0 0 0.717647 0 0 0 0.12 0'/%3e%3cfeBlend mode='normal' in2='effect1_dropShadow_154_1007' result='effect2_dropShadow_154_1007'/%3e%3cfeColorMatrix in='SourceAlpha' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0' result='hardAlpha'/%3e%3cfeOffset dy='8'/%3e%3cfeGaussianBlur stdDeviation='5'/%3e%3cfeComposite in2='hardAlpha' operator='out'/%3e%3cfeColorMatrix type='matrix' values='0 0 0 0 0.431373 0 0 0 0 0.513726 0 0 0 0 0.717647 0 0 0 0.14 0'/%3e%3cfeBlend mode='normal' in2='effect2_dropShadow_154_1007' result='effect3_dropShadow_154_1007'/%3e%3cfeBlend mode='normal' in='SourceGraphic' in2='effect3_dropShadow_154_1007' result='shape'/%3e%3c/filter%3e%3cfilter id='filter1_ddd_154_1007' x='0' y='70.3744' width='39.4136' height='39.4136' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3e%3cfeFlood flood-opacity='0' result='BackgroundImageFix'/%3e%3cfeColorMatrix in='SourceAlpha' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0' result='hardAlpha'/%3e%3cfeMorphology radius='3' operator='erode' in='SourceAlpha' result='effect1_dropShadow_154_1007'/%3e%3cfeOffset dy='5'/%3e%3cfeGaussianBlur stdDeviation='2.5'/%3e%3cfeComposite in2='hardAlpha' operator='out'/%3e%3cfeColorMatrix type='matrix' values='0 0 0 0 0.431373 0 0 0 0 0.513726 0 0 0 0 0.717647 0 0 0 0.2 0'/%3e%3cfeBlend mode='normal' in2='BackgroundImageFix' result='effect1_dropShadow_154_1007'/%3e%3cfeColorMatrix in='SourceAlpha' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0' result='hardAlpha'/%3e%3cfeMorphology radius='2' operator='dilate' in='SourceAlpha' result='effect2_dropShadow_154_1007'/%3e%3cfeOffset dy='3'/%3e%3cfeGaussianBlur stdDeviation='7'/%3e%3cfeComposite in2='hardAlpha' operator='out'/%3e%3cfeColorMatrix type='matrix' values='0 0 0 0 0.431373 0 0 0 0 0.513726 0 0 0 0 0.717647 0 0 0 0.12 0'/%3e%3cfeBlend mode='normal' in2='effect1_dropShadow_154_1007' result='effect2_dropShadow_154_1007'/%3e%3cfeColorMatrix in='SourceAlpha' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0' result='hardAlpha'/%3e%3cfeOffset dy='8'/%3e%3cfeGaussianBlur stdDeviation='5'/%3e%3cfeComposite in2='hardAlpha' operator='out'/%3e%3cfeColorMatrix type='matrix' values='0 0 0 0 0.431373 0 0 0 0 0.513726 0 0 0 0 0.717647 0 0 0 0.14 0'/%3e%3cfeBlend mode='normal' in2='effect2_dropShadow_154_1007' result='effect3_dropShadow_154_1007'/%3e%3cfeBlend mode='normal' in='SourceGraphic' in2='effect3_dropShadow_154_1007' result='shape'/%3e%3c/filter%3e%3cfilter id='filter2_ddd_154_1007' x='240.479' y='0.408401' width='39.4136' height='39.4136' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3e%3cfeFlood flood-opacity='0' result='BackgroundImageFix'/%3e%3cfeColorMatrix in='SourceAlpha' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0' result='hardAlpha'/%3e%3cfeMorphology radius='3' operator='erode' in='SourceAlpha' result='effect1_dropShadow_154_1007'/%3e%3cfeOffset dy='5'/%3e%3cfeGaussianBlur stdDeviation='2.5'/%3e%3cfeComposite in2='hardAlpha' operator='out'/%3e%3cfeColorMatrix type='matrix' values='0 0 0 0 0.431373 0 0 0 0 0.513726 0 0 0 0 0.717647 0 0 0 0.2 0'/%3e%3cfeBlend mode='normal' in2='BackgroundImageFix' result='effect1_dropShadow_154_1007'/%3e%3cfeColorMatrix in='SourceAlpha' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0' result='hardAlpha'/%3e%3cfeMorphology radius='2' operator='dilate' in='SourceAlpha' result='effect2_dropShadow_154_1007'/%3e%3cfeOffset dy='3'/%3e%3cfeGaussianBlur stdDeviation='7'/%3e%3cfeComposite in2='hardAlpha' operator='out'/%3e%3cfeColorMatrix type='matrix' values='0 0 0 0 0.431373 0 0 0 0 0.513726 0 0 0 0 0.717647 0 0 0 0.12 0'/%3e%3cfeBlend mode='normal' in2='effect1_dropShadow_154_1007' result='effect2_dropShadow_154_1007'/%3e%3cfeColorMatrix in='SourceAlpha' type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0' result='hardAlpha'/%3e%3cfeOffset dy='8'/%3e%3cfeGaussianBlur stdDeviation='5'/%3e%3cfeComposite in2='hardAlpha' operator='out'/%3e%3cfeColorMatrix type='matrix' values='0 0 0 0 0.431373 0 0 0 0 0.513726 0 0 0 0 0.717647 0 0 0 0.14 0'/%3e%3cfeBlend mode='normal' in2='effect2_dropShadow_154_1007' result='effect3_dropShadow_154_1007'/%3e%3cfeBlend mode='normal' in='SourceGraphic' in2='effect3_dropShadow_154_1007' result='shape'/%3e%3c/filter%3e%3c/defs%3e%3c/svg%3e\"","module.exports = \"data:image/svg+xml,%3csvg width='70' height='80' viewBox='0 0 70 80' fill='none' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='41.5246' height='80' rx='9' fill='%23005EC3'/%3e%3cpath d='M36.3742 65.6269C40.8554 64.3565 50.728 59.7262 54.3695 51.3684' stroke='%2306296C'/%3e%3cpath d='M16.2705 4.99595C16.2705 5.10862 16.1773 5.20692 16.0537 5.20692C15.9301 5.20692 15.8369 5.10861 15.8369 4.99595C15.8369 4.88328 15.9301 4.78498 16.0537 4.78498C16.1773 4.78498 16.2705 4.88328 16.2705 4.99595Z' fill='black' stroke='black'/%3e%3cmask id='path-4-inside-1_154_1013' fill='white'%3e%3cpath d='M25.5678 4.69376H18.5969C18.4278 4.69376 18.2908 4.82937 18.2908 4.99665C18.2908 5.16394 18.4278 5.29955 18.5969 5.29955H25.5678C25.7369 5.29955 25.8739 5.16394 25.8739 4.99665C25.8739 4.82937 25.7369 4.69376 25.5678 4.69376Z'/%3e%3c/mask%3e%3cpath d='M25.5678 4.69376H18.5969C18.4278 4.69376 18.2908 4.82937 18.2908 4.99665C18.2908 5.16394 18.4278 5.29955 18.5969 5.29955H25.5678C25.7369 5.29955 25.8739 5.16394 25.8739 4.99665C25.8739 4.82937 25.7369 4.69376 25.5678 4.69376Z' fill='%23509EE5'/%3e%3cpath d='M18.5969 5.69376H25.5678V3.69376H18.5969V5.69376ZM25.5678 5.69376C25.1947 5.69376 24.8739 5.39171 24.8739 4.99665H26.8739C26.8739 4.26702 26.279 3.69376 25.5678 3.69376V5.69376ZM24.8739 4.99665C24.8739 4.60159 25.1947 4.29955 25.5678 4.29955V6.29955C26.2791 6.29955 26.8739 5.72628 26.8739 4.99665H24.8739ZM25.5678 4.29955H18.5969V6.29955H25.5678V4.29955ZM18.5969 4.29955C18.97 4.29955 19.2908 4.60159 19.2908 4.99665H17.2908C17.2908 5.72628 17.8857 6.29955 18.5969 6.29955V4.29955ZM19.2908 4.99665C19.2908 5.39171 18.97 5.69376 18.5969 5.69376V3.69376C17.8857 3.69376 17.2908 4.26702 17.2908 4.99665H19.2908Z' fill='black' mask='url(%23path-4-inside-1_154_1013)'/%3e%3cline x1='2.59521' y1='16.6606' x2='38.9293' y2='16.6606' stroke='white' stroke-width='0.5'/%3e%3cline x1='2.59521' y1='34.2216' x2='38.9293' y2='34.2216' stroke='white' stroke-width='0.5'/%3e%3cline x1='2.59521' y1='51.7825' x2='38.9293' y2='51.7825' stroke='white' stroke-width='0.5'/%3e%3cline x1='2.59521' y1='22.5142' x2='38.9293' y2='22.5142' stroke='white' stroke-width='0.5'/%3e%3cline x1='2.59521' y1='40.0752' x2='38.9293' y2='40.0752' stroke='white' stroke-width='0.5'/%3e%3cline x1='2.59521' y1='57.6362' x2='38.9293' y2='57.6362' stroke='white' stroke-width='0.5'/%3e%3cline x1='2.59521' y1='63.4899' x2='38.9293' y2='63.4899' stroke='white' stroke-width='0.5'/%3e%3cline x1='2.59521' y1='69.3435' x2='38.9293' y2='69.3435' stroke='white' stroke-width='0.5'/%3e%3cline x1='2.59521' y1='28.3679' x2='38.9293' y2='28.3679' stroke='white' stroke-width='0.5'/%3e%3cline x1='2.59521' y1='45.9289' x2='38.9293' y2='45.9289' stroke='white' stroke-width='0.5'/%3e%3crect x='45.3677' y='12.1852' width='24.6322' height='36.4172' rx='1' fill='%23509EE5'/%3e%3cline x1='47.8049' y1='17.1842' x2='68.2927' y2='17.1842' stroke='white'/%3e%3cline x1='47.8049' y1='21.3947' x2='68.2927' y2='21.3947' stroke='white'/%3e%3cline x1='47.8049' y1='44.1316' x2='68.2927' y2='44.1316' stroke='white'/%3e%3c/svg%3e\"","import { fetch } from '../util/fetch';\n\nexport default class ProductsClient {\n\tstatic async getContainingProductsAsync({ containingProductsUrl }) {\n\t\tconst response = await fetch.get({\n\t\t\turl: containingProductsUrl,\n\t\t});\n\n\t\treturn await response.json();\n\t}\n\n\tstatic async getHasContainingProductsAsync({ hasContainingProductsUrl }) {\n\t\tconst response = await fetch.get({\n\t\t\turl: hasContainingProductsUrl,\n\t\t});\n\n\t\treturn await response.json();\n\t}\n\n\tstatic async getContainingSubscriptionsAsync({ containingSubscriptionsUrl }) {\n\t\tconst response = await fetch.get({\n\t\t\turl: containingSubscriptionsUrl,\n\t\t});\n\n\t\treturn await response.json();\n\t}\n\n\tstatic async getProductsCustomersAlsoBoughtAsync({ customersAlsoBoughtUrl, skuIds }) {\n\t\tconst response = await fetch.get({\n\t\t\turl: customersAlsoBoughtUrl,\n\t\t\tparams: { skuIds },\n\t\t});\n\n\t\treturn await response.json();\n\t}\n\n\tstatic async getTooltipAsync({ url }) {\n\t\tconst response = await fetch.get({\n\t\t\turl: url,\n\t\t});\n\t\treturn await response.json();\n\t}\n\n\tstatic async getProductDownloadsAsync({ downloadsUrl, skuIds }) {\n\t\tconst response = await fetch.get({\n\t\t\turl: downloadsUrl,\n\t\t\tparams: { skuIds },\n\t\t});\n\n\t\treturn await response.json();\n\t}\n\n\tstatic async getFeaturedProducts(featuredProductIdsUrl) {\n\t\tlet response;\n\n\t\ttry {\n\t\t\tresponse = await fetch.get({\n\t\t\t\turl: featuredProductIdsUrl,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error.response.status === 404) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn (await response.json()).featuredProducts;\n\t}\n\n\tstatic async getQuickCompare(quickCompareUrl) {\n\t\tlet response;\n\n\t\ttry {\n\t\t\tresponse = await fetch.get({\n\t\t\t\turl: quickCompareUrl,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error.response.status === 404) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn await response.json();\n\t}\n\n\tstatic async getUnownedResourcesInfos(unownedResourcesInfosBaseUrl, productIds) {\n\t\tlet response;\n\n\t\ttry {\n\t\t\tresponse = await fetch.get({\n\t\t\t\turl: `${unownedResourcesInfosBaseUrl}?productIds=${productIds.join()}`,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error.response.status === 404) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn (await response.json()).infos;\n\t}\n\n\tstatic async getShortBlurbsForProductIds(getShortBlurbsUrl, productIds) {\n\t\tconst response = await fetch.postWithBody({\n\t\t\turl: getShortBlurbsUrl,\n\t\t\tbody: {\n\t\t\t\tproductIds: productIds,\n\t\t\t},\n\t\t});\n\t\treturn await response.json();\n\t}\n\n\tstatic async getSubscriptionPromotionsForSkuIds(getSubscriptionPromotionsUrl, skuIds) {\n\t\tconst response = await fetch.get({\n\t\t\turl: getSubscriptionPromotionsUrl,\n\t\t\tparams: { skuIds },\n\t\t});\n\n\t\treturn await response.json();\n\t}\n}\n","import { useEffect, useRef, useState } from 'react';\n\nexport function useInView<T extends HTMLElement>({ threshold = 0.1, rootMargin = '0px' } = {}) {\n\tconst ref = useRef<T | null>(null);\n\tconst [isInView, setIsInView] = useState(false);\n\n\tuseEffect(() => {\n\t\tconst element = ref.current;\n\t\tif (!element) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst observer = new IntersectionObserver(\n\t\t\t([entry]) => {\n\t\t\t\tif (entry.isIntersecting) {\n\t\t\t\t\tsetIsInView(true);\n\t\t\t\t\tobserver.disconnect();\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ threshold, rootMargin }\n\t\t);\n\n\t\tobserver.observe(element);\n\n\t\treturn () => {\n\t\t\tobserver.disconnect();\n\t\t};\n\t}, [threshold, rootMargin]);\n\n\treturn { ref, isInView };\n}\n","import React, { useMemo } from 'react';\nimport type { CatalogProductData } from '@faithlife/commerce-components';\n\nimport { RecommendationsCartProvider } from '../../../commerce-contexts/cart';\nimport {\n\tInitialSkuOwnershipProvider,\n\ttype InitialSkuOwnership,\n\tRecommendationsProductProvider,\n\tStaticProductDataProvider,\n} from '../../../commerce-contexts/product';\nimport { RecommendationsResourcesProvider } from '../../../commerce-contexts/resources';\nimport { StaticWishlistDataProvider, StaticWishlistProvider } from '../../../commerce-contexts/wishlist';\nimport { hasValidReviewData } from '../../shared/ratings/review-data';\n\nexport interface RecommendationProduct {\n\tname: string;\n\timageUrl: string | null;\n\tproductPageUrl: string | null;\n\tregularPrice: string;\n\tregularPriceLocalized: string | null;\n\tcurrentPrice: string;\n\tcurrentPriceLocalized: string | null;\n\tcurrentPriceCurrency?: string | null;\n\tisDiscounted: boolean;\n\tratings: {\n\t\tnumberOfRatings: number;\n\t\taverageRating: number | null;\n\t\tshouldDisplayStars: boolean;\n\t\thyperlink: string;\n\t} | null;\n\ttooltipUrl?: string | null;\n\tunavailabilityReason?: string | null;\n\tprimarySkuId?: string | null;\n\tauthor?: string | null;\n\tisOwned?: boolean;\n\tisInCart?: boolean;\n}\n\n/** Extract product ID from a URL with pattern /product/{id}/{slug} */\nfunction extractProductId(url: string | null, index: number): string {\n\tif (url) {\n\t\tconst match = /\\/product\\/(\\d+)/.exec(url);\n\t\tif (match) {\n\t\t\treturn match[1];\n\t\t}\n\t}\n\treturn `recommendation-${index}`;\n}\n\nfunction mapToProductData(product: RecommendationProduct, index: number): CatalogProductData {\n\tconst id = extractProductId(product.productPageUrl, index);\n\tconst averageRating = product.ratings?.averageRating ?? 0;\n\tconst reviewCount = product.ratings?.numberOfRatings ?? 0;\n\tconst shouldDisplayRatings =\n\t\tproduct.ratings?.shouldDisplayStars === true && hasValidReviewData(averageRating, reviewCount);\n\n\treturn {\n\t\tid,\n\t\tname: product.name,\n\t\tprimarySkuId: product.primarySkuId ?? undefined,\n\t\timageUri: product.imageUrl ?? undefined,\n\t\tproductPageUri: product.productPageUrl ?? undefined,\n\t\tauthor: product.author ?? undefined,\n\t\tskus: product.primarySkuId\n\t\t\t? ([\n\t\t\t\t\t{\n\t\t\t\t\t\tid: product.primarySkuId,\n\t\t\t\t\t\tsalePrice: product.currentPrice,\n\t\t\t\t\t\tsalePriceCurrency: product.currentPriceCurrency,\n\t\t\t\t\t\tanchorPrice: product.isDiscounted ? product.regularPrice : undefined,\n\t\t\t\t\t\tlocalizedSalePrice: product.currentPriceLocalized,\n\t\t\t\t\t\tpriceVariant: product.isDiscounted ? ('sale' as const) : ('default' as const),\n\t\t\t\t\t},\n\t\t\t\t] as NonNullable<CatalogProductData['skus']>)\n\t\t\t: undefined,\n\t\trating: shouldDisplayRatings ? averageRating : undefined,\n\t\treviewCount: shouldDisplayRatings ? reviewCount : undefined,\n\t};\n}\n\ninterface RecommendationsContextProps {\n\tproducts: RecommendationProduct[];\n\tchildren: React.ReactNode;\n}\n\nconst RecommendationsProductIdsContext = React.createContext<{ productId: string }[]>([]);\n\nexport function useRecommendationsProductIds() {\n\treturn React.useContext(RecommendationsProductIdsContext);\n}\n\nexport function RecommendationsContext({ products, children }: RecommendationsContextProps) {\n\tconst { staticProductData, productIds, initialOwnership } = useMemo(() => {\n\t\tconst dataMap: Record<string, CatalogProductData> = {};\n\t\tconst ids: { productId: string }[] = [];\n\t\tconst ownership: InitialSkuOwnership = {};\n\n\t\tproducts.forEach((product, index) => {\n\t\t\tconst catalogData = mapToProductData(product, index);\n\t\t\tif (catalogData.id) {\n\t\t\t\tdataMap[catalogData.id] = catalogData;\n\t\t\t\tids.push({ productId: catalogData.id });\n\t\t\t\tif (product.primarySkuId) {\n\t\t\t\t\townership[product.primarySkuId] = {\n\t\t\t\t\t\tisOwned: product.isOwned === true,\n\t\t\t\t\t\tisInCart: product.isInCart === true,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\treturn { staticProductData: dataMap, productIds: ids, initialOwnership: ownership };\n\t}, [products]);\n\n\treturn (\n\t\t<RecommendationsProductIdsContext.Provider value={productIds}>\n\t\t\t<RecommendationsResourcesProvider>\n\t\t\t\t<RecommendationsCartProvider>\n\t\t\t\t\t<StaticProductDataProvider staticProductData={staticProductData}>\n\t\t\t\t\t\t<InitialSkuOwnershipProvider initialOwnership={initialOwnership}>\n\t\t\t\t\t\t\t<RecommendationsProductProvider>\n\t\t\t\t\t\t\t\t<StaticWishlistDataProvider staticProductData={staticProductData} errorContext=\"RecommendationsContext\">\n\t\t\t\t\t\t\t\t\t<StaticWishlistProvider>{children}</StaticWishlistProvider>\n\t\t\t\t\t\t\t\t</StaticWishlistDataProvider>\n\t\t\t\t\t\t\t</RecommendationsProductProvider>\n\t\t\t\t\t\t</InitialSkuOwnershipProvider>\n\t\t\t\t\t</StaticProductDataProvider>\n\t\t\t\t</RecommendationsCartProvider>\n\t\t\t</RecommendationsResourcesProvider>\n\t\t</RecommendationsProductIdsContext.Provider>\n\t);\n}\n","import React from 'react';\nimport { CarouselProduct, ContentSection } from '@faithlife/commerce-components';\n\nimport {\n\tRecommendationsContext,\n\tuseRecommendationsProductIds,\n\ttype RecommendationProduct,\n} from './recommendations-context';\n\ninterface RecommendationsCarouselProps {\n\tdata: RecommendationProduct[] | null | undefined;\n\tisLoading: boolean;\n\theading: string;\n\tsubHeading?: string;\n\tclassName?: string;\n}\n\nconst ProductCardSkeleton = () => (\n\t<div className=\"swiper-slide swiper-slide-active h-auto w-fit mr-[48px]\">\n\t\t<div className=\"h-full w-64 sm:w-72 lg:w-80\">\n\t\t\t<article className=\"tw-preflight group flex flex-col border-t border-primary-200 h-full\">\n\t\t\t\t<div className=\"relative h-[240px] overflow-hidden\">\n\t\t\t\t\t<div className=\"pt-sp32 flex h-full w-full items-end justify-center overflow-hidden pb-sp24\">\n\t\t\t\t\t\t<div className=\"h-[196px] w-[127px] animate-pulse rounded-sm bg-primary-200\" />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"flex flex-1 flex-col justify-between gap-sp16 pb-sp16\">\n\t\t\t\t\t<div className=\"flex flex-col gap-sp16\">\n\t\t\t\t\t\t<div className=\"flex flex-col gap-sp8\">\n\t\t\t\t\t\t\t<div className=\"w-[190px] h-[20px] animate-pulse rounded-sm bg-primary-200\" />\n\t\t\t\t\t\t\t<div className=\"w-[240px] h-[16px] animate-pulse rounded-sm bg-primary-200\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-col gap-sp20\">\n\t\t\t\t\t\t<div className=\"w-[120px] h-[28px] animate-pulse rounded-sm bg-primary-200\" />\n\t\t\t\t\t\t<button className=\"tw-preflight inline-flex items-center justify-center gap-sp12 rounded-[2px] text-center transition-colors duration-short focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary motion-reduce:transition-none buttonTextLg py-sp14 px-sp16 bg-transparent border border-primary text-primary hover:ring-1 hover:ring-inset hover:ring-primary active:border-primary-500 active:ring-1 active:ring-inset active:ring-primary-500 disabled:border-secondary-200 disabled:text-primary disabled:opacity-[0.33] disabled:cursor-not-allowed w-full self-start\">\n\t\t\t\t\t\t\t<span className=\"block w-[120px] h-[18px] animate-pulse rounded-sm bg-primary-200\" />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</article>\n\t\t</div>\n\t</div>\n);\n\nconst SkeletonCarousel = () => (\n\t<div className=\"overflow-hidden\">\n\t\t<div className=\"swiper swiper-initialized swiper-horizontal overflow-visible swiper-backface-hidden items-stretch max-lg:pl-sp16 lg:pl-sp24\">\n\t\t\t<div className=\"swiper-wrapper\">\n\t\t\t\t<ProductCardSkeleton />\n\t\t\t\t<ProductCardSkeleton />\n\t\t\t\t<ProductCardSkeleton />\n\t\t\t\t<ProductCardSkeleton />\n\t\t\t\t<ProductCardSkeleton />\n\t\t\t</div>\n\t\t</div>\n\t</div>\n);\n\nconst CarouselContent = () => {\n\tconst productIds = useRecommendationsProductIds();\n\treturn (\n\t\t<CarouselProduct\n\t\t\tproductIds={productIds}\n\t\t\tshowArrows\n\t\t\tclassName=\"max-lg:[&_.swiper]:pl-sp16 lg:[&_.swiper]:pl-sp24\"\n\t\t\tscale=\"small\"\n\t\t/>\n\t);\n};\n\nexport const RecommendationsCarousel = ({\n\tdata,\n\tisLoading,\n\theading,\n\tsubHeading,\n\tclassName,\n}: RecommendationsCarouselProps) => {\n\tconst isEmpty = !isLoading && (!data || data.length === 0);\n\n\tif (isEmpty) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<ContentSection\n\t\t\tsectionHeadline={heading}\n\t\t\theadlineBody={subHeading}\n\t\t\theadlineClassName=\"max-lg:px-sp16 lg:px-sp24\"\n\t\t\tclassName={className}\n\t\t>\n\t\t\t{isLoading ? (\n\t\t\t\t<SkeletonCarousel />\n\t\t\t) : (\n\t\t\t\t<RecommendationsContext products={data ?? []}>\n\t\t\t\t\t<CarouselContent />\n\t\t\t\t</RecommendationsContext>\n\t\t\t)}\n\t\t</ContentSection>\n\t);\n};\n","import React, { useCallback, useEffect, useState } from 'react';\nimport ProductsClient from '../../../clients/products-client';\nimport { useLocalization } from '../../../localization';\nimport { useInView } from '../../../util/hooks/use-in-view';\nimport { type RecommendationProduct } from './recommendations-context';\nimport { RecommendationsCarousel } from './recommendations-carousel';\n\ninterface BuyInCollectionProps {\n\tcontainingProductsUrl: string;\n}\n\nexport const BuyInCollection = ({ containingProductsUrl }: BuyInCollectionProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.ContainingProducts');\n\tconst { ref, isInView } = useInView<HTMLDivElement>({ rootMargin: '0px 0px 300px 0px' });\n\tconst [data, setData] = useState<RecommendationProduct[] | null>(null);\n\tconst [isLoading, setIsLoading] = useState(true);\n\n\tconst fetchData = useCallback(async () => {\n\t\ttry {\n\t\t\tconst response = await ProductsClient.getContainingProductsAsync({ containingProductsUrl });\n\t\t\tsetData(response.containingProducts ?? []);\n\t\t} catch {\n\t\t\tsetData([]);\n\t\t} finally {\n\t\t\tsetIsLoading(false);\n\t\t}\n\t}, [containingProductsUrl]);\n\n\tuseEffect(() => {\n\t\tif (isInView) {\n\t\t\tfetchData();\n\t\t}\n\t}, [isInView, fetchData]);\n\n\tconst isEmpty = !isLoading && (!data || data.length === 0);\n\n\tif (isEmpty) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t{isInView && <hr className=\"hidden lg:block border-grey lg:mx-sp24\" />}\n\t\t\t<div ref={ref}>\n\t\t\t\t{isInView && (\n\t\t\t\t\t<RecommendationsCarousel\n\t\t\t\t\t\tdata={data}\n\t\t\t\t\t\theading={resources.BuyInCollectionTitle}\n\t\t\t\t\t\tisLoading={isLoading}\n\t\t\t\t\t\tsubHeading={resources.YouCanSave}\n\t\t\t\t\t\tclassName=\"max-lg:mt-sp24 lg:mt-sp32\"\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</>\n\t);\n};\n","import React, { useCallback, useEffect, useState } from 'react';\nimport ProductsClient from '../../../clients/products-client';\nimport { useLocalization } from '../../../localization';\nimport useResourceFormatsAndTexts from '../../../util/hooks/use-resource-formats-and-texts';\nimport { useInView } from '../../../util/hooks/use-in-view';\n\ninterface ContainingSubscriptionsData {\n\tstartingAtMonthlyPrice: string;\n\tstartingAtLocalizedPrice: string;\n\tbillingMode: string;\n\tfreeTrialPeriodLength: number | null;\n\tfreeTrialPeriodUnit: string | null;\n\tavailableLogosTieredSubscriptionLevels: string[];\n\tlocale: string;\n\tlogosOrVerbum: string;\n\troutes: Record<string, string>;\n}\n\ninterface ContainingSubscriptionsProps {\n\tcontainingSubscriptionsUrl: string;\n}\n\nexport const ContainingSubscriptions = ({ containingSubscriptionsUrl }: ContainingSubscriptionsProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.ContainingSubscriptions');\n\tconst { ref, isInView } = useInView<HTMLDivElement>({ rootMargin: '0px 0px 300px 0px' });\n\tconst [data, setData] = useState<ContainingSubscriptionsData | null>(null);\n\tconst [isLoading, setIsLoading] = useState(true);\n\n\tconst fetchData = useCallback(async () => {\n\t\ttry {\n\t\t\tconst response = await ProductsClient.getContainingSubscriptionsAsync({ containingSubscriptionsUrl });\n\t\t\tsetData(response.containingSubscriptions ?? null);\n\t\t} catch {\n\t\t\tsetData(null);\n\t\t} finally {\n\t\t\tsetIsLoading(false);\n\t\t}\n\t}, [containingSubscriptionsUrl]);\n\n\tuseEffect(() => {\n\t\tif (isInView) {\n\t\t\tfetchData();\n\t\t}\n\t}, [isInView, fetchData]);\n\n\tif (isInView && !isLoading && !data) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t{isInView && <hr className=\"hidden lg:block border-grey lg:mx-sp24\" />}\n\t\t\t<div ref={ref} className=\"max-lg:mt-sp24 lg:mt-sp32\">\n\t\t\t\t{data ? (\n\t\t\t\t\t<ContainingSubscriptionsCard data={data} resources={resources} />\n\t\t\t\t) : (\n\t\t\t\t\t<div className=\"h-[200px] animate-pulse rounded-sm bg-primary-100\" />\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</>\n\t);\n};\n\nfunction ContainingSubscriptionsCard({\n\tdata,\n\tresources,\n}: {\n\tdata: ContainingSubscriptionsData;\n\tresources: Record<string, string>;\n}) {\n\tconst formatsAndTexts = useResourceFormatsAndTexts({\n\t\tlocale: data.locale,\n\t\tbillingMode: data.billingMode,\n\t\tfreeTrialPeriodUnit: data.freeTrialPeriodUnit,\n\t\tfreeTrialPeriodLength: data.freeTrialPeriodLength,\n\t\tavailableLogosTieredSubscriptionLevels: data.availableLogosTieredSubscriptionLevels,\n\t\tsubscriptionResources: undefined,\n\t});\n\n\tif (!formatsAndTexts) {\n\t\treturn null;\n\t}\n\n\tconst isFreeTrial = data.freeTrialPeriodLength !== null && data.freeTrialPeriodLength > 0;\n\n\tconst title = isFreeTrial\n\t\t? resources.AccessThisTitleWithAFreeTrialToLogosOrVerbum?.replace('%LOGOSORVERBUM%', data.logosOrVerbum)\n\t\t: resources.AccessThisTitleWithASubscriptionToLogosOrVerbum?.replace('%LOGOSORVERBUM%', data.logosOrVerbum);\n\n\tconst priceText = formatsAndTexts.priceFormat?.replace('%PRICE%', data.startingAtMonthlyPrice);\n\n\tconst availableInText = resources.AvailableInSubscriptions?.replace(\n\t\t'%AVAILABLESUBSCRIPTIONSLIST%',\n\t\tformatsAndTexts.localizedAvailableSubscriptionLevelListText\n\t)?.replace('%SUBSCRIPTIONSTEXT%', formatsAndTexts.subscriptionsText);\n\n\tconst subscribeUrl = data.routes?.ConfigurationWizardSubscriptions;\n\n\treturn (\n\t\t<div className=\"mx-4 lg:mx-sp24 flex flex-col gap-4 rounded-sm border border-black p-4 text-left text-base leading-[1.35]\">\n\t\t\t<p className=\"m-0 text-[22px] font-bold leading-[28px]\">{title}</p>\n\t\t\t<div className=\"flex flex-col gap-2\">\n\t\t\t\t<div className=\"flex flex-row justify-between gap-3 border-t border-primary-200 bg-primary-100 py-2 pl-3 pr-4\">\n\t\t\t\t\t<div className=\"flex flex-col gap-2 text-primary-400\">\n\t\t\t\t\t\t<div>{resources.StartingAt}</div>\n\t\t\t\t\t\t<div className=\"m-0 text-[20px] font-medium\">{priceText}</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t{subscribeUrl && (\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tclassName=\"my-auto flex items-center gap-2 text-right font-semibold text-primary no-underline\"\n\t\t\t\t\t\t\thref={subscribeUrl}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span>{resources.Subscribe}</span>\n\t\t\t\t\t\t\t<svg fill=\"none\" height=\"16\" viewBox=\"0 0 19 16\" width=\"19\" xmlns=\"http://www.w3.org/2000/svg\">\n\t\t\t\t\t\t\t\t<path d=\"m12 1 6 7-6 7M18 8H0\" stroke=\"currentColor\" />\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div>{availableInText}</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import React, { useCallback, useEffect, useState } from 'react';\nimport ProductsClient from '../../../clients/products-client';\nimport { useLocalization } from '../../../localization';\nimport { useInView } from '../../../util/hooks/use-in-view';\nimport { type RecommendationProduct } from './recommendations-context';\nimport { RecommendationsCarousel } from './recommendations-carousel';\n\ninterface CustomersAlsoBoughtProps {\n\tskuIds: string[];\n\tcustomersAlsoBoughtUrl: string;\n}\n\nexport const CustomersAlsoBought = ({ skuIds, customersAlsoBoughtUrl }: CustomersAlsoBoughtProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.CustomersAlsoBought');\n\tconst { ref, isInView } = useInView<HTMLDivElement>({ rootMargin: '0px 0px 300px 0px' });\n\tconst [data, setData] = useState<RecommendationProduct[] | null>(null);\n\tconst [isLoading, setIsLoading] = useState(true);\n\n\tconst fetchData = useCallback(async () => {\n\t\tif (!skuIds.length) {\n\t\t\tsetData([]);\n\t\t\tsetIsLoading(false);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await ProductsClient.getProductsCustomersAlsoBoughtAsync({\n\t\t\t\tcustomersAlsoBoughtUrl,\n\t\t\t\tskuIds: skuIds.join(','),\n\t\t\t});\n\t\t\tsetData(response.products ?? []);\n\t\t} catch {\n\t\t\tsetData([]);\n\t\t} finally {\n\t\t\tsetIsLoading(false);\n\t\t}\n\t}, [customersAlsoBoughtUrl, skuIds]);\n\n\tuseEffect(() => {\n\t\tif (isInView) {\n\t\t\tfetchData();\n\t\t}\n\t}, [isInView, fetchData]);\n\n\tconst isEmpty = !isLoading && (!data || data.length === 0);\n\n\tif (isEmpty) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t{isInView && <hr className=\"hidden lg:block border-grey lg:mx-sp24\" />}\n\t\t\t<div ref={ref} className=\"max-lg:mt-sp24 lg:mt-sp32\">\n\t\t\t\t<RecommendationsCarousel data={data} heading={resources.CustomersAlsoBoughtTitle} isLoading={isLoading} />\n\t\t\t</div>\n\t\t</>\n\t);\n};\n","import React from 'react';\nimport { useLocalization } from '../../../localization/use-localization';\nimport { type FeaturedProduct } from './types';\n\ninterface FeaturedProductsProps {\n\tfeaturedProducts: FeaturedProduct[];\n\tclassName?: string;\n}\n\nexport const FeaturedProducts = ({ featuredProducts }: FeaturedProductsProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.FeaturedProducts');\n\tif (featuredProducts.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst [primaryProduct, ...secondaryProducts] = featuredProducts;\n\n\treturn (\n\t\t<div className=\"mx-auto lg:w-3/4\">\n\t\t\t<div className=\"mt-sp20 lg:mx-auto lg:mt-sp36 lg:flex lg:w-3/4 lg:justify-center\">\n\t\t\t\t<a href={primaryProduct.productPageUri}>\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={primaryProduct.imageUri}\n\t\t\t\t\t\tclassName=\"mx-auto max-h-[210px] max-w-[210px] sm:mr-sp20 sm:mx-0 sm:mb-sp12 lg:mb-0\"\n\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\trole=\"presentation\"\n\t\t\t\t\t/>\n\t\t\t\t</a>\n\t\t\t\t<div className=\"sm:text-left\">\n\t\t\t\t\t<a\n\t\t\t\t\t\thref={primaryProduct.productPageUri}\n\t\t\t\t\t\tclassName=\"mt-sp20 block text-base font-bold text-black hover:text-black sm:mt-0\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{primaryProduct.title}\n\t\t\t\t\t</a>\n\t\t\t\t\t{primaryProduct.authorDisplayString && (\n\t\t\t\t\t\t<p className=\"mt-sp8 text-sm text-black-70\">{primaryProduct.authorDisplayString}</p>\n\t\t\t\t\t)}\n\t\t\t\t\t{primaryProduct.blurb && <p className=\"mt-sp12 text-sm text-black-70\">{primaryProduct.blurb}</p>}\n\t\t\t\t\t{primaryProduct.regularPrice && (\n\t\t\t\t\t\t<p className=\"mt-sp8 text-sm font-bold\">\n\t\t\t\t\t\t\t{resources.RegularPrice.replace('{0}', primaryProduct.regularPrice)}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t{secondaryProducts.length > 0 && (\n\t\t\t\t<div className=\"sm:flex sm:justify-around\">\n\t\t\t\t\t{secondaryProducts.map(product => (\n\t\t\t\t\t\t<div key={product.title} className=\"mt-sp36 flex flex-col justify-between text-center sm:max-w-[210px]\">\n\t\t\t\t\t\t\t<a href={product.productPageUri} className=\"sm:flex sm:h-[168px] sm:items-center sm:justify-center\">\n\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\tsrc={product.imageUri}\n\t\t\t\t\t\t\t\t\tclassName=\"mx-auto max-h-[210px] max-w-[210px] sm:max-h-full sm:max-w-full\"\n\t\t\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\t\t\trole=\"presentation\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref={product.productPageUri}\n\t\t\t\t\t\t\t\tclassName=\"mt-sp20 block text-base font-bold text-black hover:text-black\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{product.title}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t{product.authorDisplayString && (\n\t\t\t\t\t\t\t\t<p className=\"mt-sp8 text-sm text-black-70\">{product.authorDisplayString}</p>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{product.regularPrice && (\n\t\t\t\t\t\t\t\t<p className=\"mt-sp8 text-sm font-bold\">\n\t\t\t\t\t\t\t\t\t{resources.RegularPrice.replace('{0}', product.regularPrice)}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n","import React, { useCallback, useEffect, useState } from 'react';\nimport ProductsClient from '../../../clients/products-client';\nimport { useLocalization } from '../../../localization/use-localization';\nimport { useInView } from '../../../util/hooks/use-in-view';\nimport { FeaturedProducts } from './featured-products';\nimport { type FeaturedProduct } from './types';\n\ninterface FeaturedProductsSectionProps {\n\tfeaturedProductsUrl: string;\n}\n\nconst FeaturedProductsSkeleton = () => (\n\t<div className=\"animate-pulse\">\n\t\t<div className=\"sm:mx-auto sm:flex sm:w-3/4 sm:justify-center\">\n\t\t\t<div className=\"mx-auto h-[210px] w-[210px] rounded bg-primary-200 sm:mr-sp20 sm:mx-0\" />\n\t\t\t<div className=\"mt-sp20 flex flex-1 flex-col gap-sp8 sm:mt-0\">\n\t\t\t\t<div className=\"h-4 w-3/4 rounded bg-primary-200\" />\n\t\t\t\t<div className=\"h-3 w-1/2 rounded bg-primary-200\" />\n\t\t\t\t<div className=\"h-3 w-full rounded bg-primary-200\" />\n\t\t\t\t<div className=\"h-3 w-5/6 rounded bg-primary-200\" />\n\t\t\t</div>\n\t\t</div>\n\t</div>\n);\n\nexport const FeaturedProductsSection = ({ featuredProductsUrl }: FeaturedProductsSectionProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.FeaturedProducts');\n\tconst { ref, isInView } = useInView<HTMLDivElement>({ rootMargin: '0px 0px 300px 0px' });\n\tconst [data, setData] = useState<FeaturedProduct[] | null>(null);\n\tconst [isLoading, setIsLoading] = useState(true);\n\n\tconst fetchData = useCallback(async () => {\n\t\ttry {\n\t\t\tconst result = await ProductsClient.getFeaturedProducts(featuredProductsUrl);\n\t\t\tsetData(result ?? []);\n\t\t} catch {\n\t\t\tsetData([]);\n\t\t} finally {\n\t\t\tsetIsLoading(false);\n\t\t}\n\t}, [featuredProductsUrl]);\n\n\tuseEffect(() => {\n\t\tif (isInView) {\n\t\t\tfetchData();\n\t\t}\n\t}, [isInView, fetchData]);\n\n\tconst isEmpty = !isLoading && (!data || data.length === 0);\n\n\tif (isEmpty) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t{isInView && <hr className=\"hidden lg:block border-grey lg:mx-sp24\" />}\n\t\t\t<div\n\t\t\t\tref={ref}\n\t\t\t\tclassName=\"tw-preflight mx-auto max-w-[1440px] lg:px-6 lg:pb-sp16 lg:pt-sp16 max-lg:mt-sp24 max-lg:mx-sp16 lg:mt-sp32\"\n\t\t\t>\n\t\t\t\t<h2 className=\"mb-8 text-2xl font-bold text-gray-900\">{resources.ResourceHighlights}</h2>\n\t\t\t\t{isLoading ? <FeaturedProductsSkeleton /> : <FeaturedProducts featuredProducts={data ?? []} />}\n\t\t\t</div>\n\t\t</>\n\t);\n};\n","import { fetch } from '../util/fetch';\n\nexport default class ReviewsClient {\n\tstatic async getReviews(requestUrl) {\n\t\tconst response = await fetch.get({\n\t\t\turl: requestUrl,\n\t\t});\n\n\t\tconst responseData = await response.json();\n\n\t\treturn responseData.reviews;\n\t}\n\n\tstatic async getAdditionalReviews(requestUrl, offset) {\n\t\tconst response = await fetch.get({\n\t\t\turl: `${requestUrl}?offset=${offset}`,\n\t\t});\n\n\t\tconst responseData = await response.json();\n\n\t\treturn responseData.reviews;\n\t}\n\n\tstatic async getRatings(requestUrl) {\n\t\tconst response = await fetch.get({\n\t\t\turl: requestUrl,\n\t\t});\n\n\t\tconst responseData = await response.json();\n\n\t\treturn responseData;\n\t}\n\n\tstatic async getReview(url) {\n\t\tlet response;\n\n\t\ttry {\n\t\t\tresponse = await fetch.get({\n\t\t\t\turl,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error.response.status === 404) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn await response.json();\n\t}\n\n\tstatic async deleteReview(url) {\n\t\tconst response = await fetch.delete({\n\t\t\turl,\n\t\t});\n\n\t\treturn response;\n\t}\n\n\tstatic async createReview(requestUrl, productId, userId, reviewText, rating) {\n\t\tconst response = await fetch.postWithBody({\n\t\t\turl: requestUrl,\n\t\t\tbody: {\n\t\t\t\tproductId,\n\t\t\t\tuserId,\n\t\t\t\treviewText,\n\t\t\t\trating: rating === 0 ? null : rating,\n\t\t\t},\n\t\t});\n\n\t\treturn await response.json();\n\t}\n\n\tstatic async addReactionToReview(url) {\n\t\ttry {\n\t\t\tawait fetch.post({\n\t\t\t\turl,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error.response.status === 500) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tstatic async removeReactionFromReview(url) {\n\t\ttry {\n\t\t\tawait fetch.delete({\n\t\t\t\turl,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error.response.status === 500) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tstatic async flagReview(url) {\n\t\tawait fetch.post({\n\t\t\turl,\n\t\t});\n\t}\n\n\tstatic async followPage(requestUrl) {\n\t\tawait fetch.get({\n\t\t\turl: requestUrl,\n\t\t});\n\t}\n\n\tstatic async unfollowPage(requestUrl) {\n\t\tawait fetch.get({\n\t\t\turl: requestUrl,\n\t\t});\n\t}\n}\n","import React, { useCallback, useState } from 'react';\nimport { StarFilledIcon, StarIcon } from '@faithlife/commerce-components';\nimport { useLocalization } from '../../../localization';\n\ninterface RatingSelectorProps {\n\tselectedRating: number;\n\tonSelectedRatingChange: (rating: number) => void;\n}\n\nexport const RatingSelector = ({ selectedRating, onSelectedRatingChange }: RatingSelectorProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Reviews');\n\tconst [previewRating, setPreviewRating] = useState(0);\n\n\tconst ratingDescriptions = [\n\t\tresources.HatedIt,\n\t\tresources.DidntLikeIt,\n\t\tresources.ItsOkay,\n\t\tresources.LikedIt,\n\t\tresources.LovedIt,\n\t] as const;\n\n\tconst activeRating = selectedRating || previewRating;\n\n\tconst handleMouseEnter = useCallback((point: number) => setPreviewRating(point), []);\n\tconst handleMouseLeave = useCallback(() => setPreviewRating(0), []);\n\tconst handleClick = useCallback((point: number) => onSelectedRatingChange(point), [onSelectedRatingChange]);\n\n\tconst iconSize = 16; // 16px, is the md scale of <StarRating /> component\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-sp4\">\n\t\t\t<div className={`group/star-rating flex flex-row gap-sp4`}>\n\t\t\t\t{ratingDescriptions.map((_desc, index) => {\n\t\t\t\t\tconst point = index + 1;\n\t\t\t\t\tconst isFilled = point <= activeRating;\n\t\t\t\t\tconst isPreviewed = point <= previewRating;\n\t\t\t\t\tconst starClassName = `${isPreviewed ? 'scale-125' : ''}`;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={point}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\taria-label={ratingDescriptions[index]}\n\t\t\t\t\t\t\tclassName={`cursor-pointer p-sp2 focus:outline-hidden focus-visible:ring-2 focus-visible:ring-primary text-primary-400 disabled:text-black group-has-[button:active]/star-rating:opacity-60`}\n\t\t\t\t\t\t\tonMouseEnter={() => handleMouseEnter(point)}\n\t\t\t\t\t\t\tonMouseLeave={handleMouseLeave}\n\t\t\t\t\t\t\tonClick={() => handleClick(point)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{isFilled ? (\n\t\t\t\t\t\t\t\t<StarFilledIcon className={starClassName} size={iconSize} />\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<StarIcon className={starClassName} size={iconSize} />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import React from 'react';\n\nimport { ComponentPropsWithRef, ComponentRef, forwardRef } from 'react';\nimport { cn } from '../../../util/cn';\n\nconst textAreaClassName =\n\t'focus-visible:ring-primary/20 border-2 border-gray-200 py-sp10 px-sp16 placeholder:text-gray-500 hover:border-primary focus-visible:border-primary focus-visible:outline-hidden focus-visible:ring-2 disabled:bg-gray-100';\n\ntype TextAreaProps = ComponentPropsWithRef<'textarea'>;\n\nexport const TextArea = forwardRef<ComponentRef<'textarea'>, TextAreaProps>(({ className, ...props }, ref) => {\n\treturn <textarea className={cn(textAreaClassName, className)} ref={ref} {...props} />;\n});\n\nTextArea.displayName = 'TextArea';\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { Button, Typography } from '@faithlife/commerce-components';\nimport { LoadingSpinner } from '@faithlife/styled-ui';\nimport { CommandSentence } from '@faithlife/command-sentence-control';\nimport { useLocalization } from '../../../localization';\nimport { useLocation } from '../../../location';\nimport ReviewsClient from '../../../clients/reviews-client';\nimport { RatingSelector } from './rating-selector';\nimport type { ReviewViewModel, ReviewsRoutes, ReviewsUserViewModel } from './types';\nimport { TextArea } from './text-area';\n\ninterface ReviewEditorProps {\n\tuser?: ReviewsUserViewModel;\n\tisUserLoggedIn: boolean;\n\tcurrentUserReview?: ReviewViewModel;\n\tproductId: string;\n\troutes: ReviewsRoutes;\n\tonReviewSubmit: () => Promise<void>;\n\tonDeleteReview: (review: ReviewViewModel) => Promise<void>;\n}\n\nexport const ReviewEditor = ({\n\tuser,\n\tisUserLoggedIn,\n\tcurrentUserReview,\n\tproductId,\n\troutes,\n\tonReviewSubmit,\n\tonDeleteReview,\n}: ReviewEditorProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Reviews');\n\tconst { navigate } = useLocation();\n\tconst [selectedRating, setSelectedRating] = useState(0);\n\tconst [reviewText, setReviewText] = useState('');\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst textareaRef = useRef<HTMLTextAreaElement>(null);\n\n\tconst trimmedReviewText = reviewText.trim();\n\n\t// Auto-focus textarea when a rating is selected\n\tuseEffect(() => {\n\t\tif (selectedRating > 0) {\n\t\t\ttextareaRef.current?.focus();\n\t\t}\n\t}, [selectedRating]);\n\n\tconst handleSubmitReview = useCallback(async () => {\n\t\tsetIsLoading(true);\n\t\ttry {\n\t\t\tawait ReviewsClient.createReview(\n\t\t\t\troutes.CreateReviewUrl,\n\t\t\t\tproductId,\n\t\t\t\tuser?.userId,\n\t\t\t\ttrimmedReviewText,\n\t\t\t\tselectedRating\n\t\t\t);\n\t\t\tawait onReviewSubmit();\n\t\t} finally {\n\t\t\tsetIsLoading(false);\n\t\t}\n\t}, [routes, productId, user, trimmedReviewText, selectedRating, onReviewSubmit]);\n\n\tconst handleDeleteClick = useCallback(async () => {\n\t\tif (!currentUserReview) {\n\t\t\treturn;\n\t\t}\n\t\tsetIsLoading(true);\n\t\tawait onDeleteReview(currentUserReview);\n\t\tsetIsLoading(false);\n\t}, [currentUserReview, onDeleteReview]);\n\n\tconst handleSignInClick = useCallback(() => {\n\t\tnavigate(routes.SignInUrl);\n\t}, [navigate, routes.SignInUrl]);\n\n\tif (!isUserLoggedIn) {\n\t\treturn (\n\t\t\t<div className=\"flex justify-start\">\n\t\t\t\t{/* TODO: Replace this with a real link styled like a button when commerce-components supports link semantics here. */}\n\t\t\t\t<Button onClick={handleSignInClick} scale=\"small\" variant=\"secondary\">\n\t\t\t\t\t{resources.SignIn}\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (currentUserReview) {\n\t\treturn (\n\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t<Typography className=\"text-black-100\" variant=\"bodySmall\">\n\t\t\t\t\t<CommandSentence Container=\"span\" template={resources.AlreadyReviewed}>\n\t\t\t\t\t\t<CommandSentence.Field name=\"REVIEWDATE\">{currentUserReview.localeDate ?? ''}</CommandSentence.Field>\n\t\t\t\t\t</CommandSentence>\n\t\t\t\t</Typography>\n\t\t\t\t<div>\n\t\t\t\t\t{isLoading ? (\n\t\t\t\t\t\t<LoadingSpinner small />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<Button onClick={handleDeleteClick} scale=\"small\" variant=\"secondary\">\n\t\t\t\t\t\t\t{resources.Delete}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-sp16\">\n\t\t\t<Typography className=\"text-primary-400\" variant=\"headingH6\">\n\t\t\t\t{resources.ReviewThisProduct}\n\t\t\t</Typography>\n\t\t\t<div className=\"flex items-center gap-sp8\">\n\t\t\t\t<Typography className=\"text-black-100\" variant=\"bodySmall\">\n\t\t\t\t\t{resources.StarRating}\n\t\t\t\t\t{':'}\n\t\t\t\t</Typography>\n\t\t\t\t<RatingSelector onSelectedRatingChange={setSelectedRating} selectedRating={selectedRating} />\n\t\t\t</div>\n\t\t\t<TextArea\n\t\t\t\tref={textareaRef}\n\t\t\t\tclassName=\"w-full resize-none\"\n\t\t\t\tonChange={e => setReviewText(e.target.value)}\n\t\t\t\tplaceholder={resources.ShareYourThoughtsHere}\n\t\t\t\trows={4}\n\t\t\t\tvalue={reviewText}\n\t\t\t/>\n\t\t\t<div className=\"flex flex-col gap-sp8\">\n\t\t\t\t<Typography className=\"text-black-100\" variant=\"bodySmall\">\n\t\t\t\t\t<CommandSentence Container=\"span\" template={resources.PleaseFollowOur}>\n\t\t\t\t\t\t<CommandSentence.Field name=\"GUIDELINESLINK\">\n\t\t\t\t\t\t\t<a className=\"underline\" href={resources.ReviewGuidelinesLink} rel=\"noopener noreferrer\" target=\"_blank\">\n\t\t\t\t\t\t\t\t{resources.ReviewGuidelines}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</CommandSentence.Field>\n\t\t\t\t\t</CommandSentence>\n\t\t\t\t</Typography>\n\t\t\t\t<Typography className=\"text-black-100\" variant=\"bodySmall\">\n\t\t\t\t\t<CommandSentence Container=\"span\" template={resources.AllPostedReviews}>\n\t\t\t\t\t\t<CommandSentence.Field name=\"TOSLINK\">\n\t\t\t\t\t\t\t<a className=\"underline\" href={resources.TermsOfServiceLink} rel=\"noopener noreferrer\" target=\"_blank\">\n\t\t\t\t\t\t\t\t{resources.TermsOfService}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</CommandSentence.Field>\n\t\t\t\t\t</CommandSentence>\n\t\t\t\t</Typography>\n\t\t\t\t<Typography className=\"text-black-100\" variant=\"bodySmall\">\n\t\t\t\t\t<CommandSentence Container=\"span\" template={resources.CanSeeThis}>\n\t\t\t\t\t\t<CommandSentence.Field name=\"EVERYONE\">{resources.Everyone}</CommandSentence.Field>\n\t\t\t\t\t</CommandSentence>\n\t\t\t\t</Typography>\n\t\t\t</div>\n\t\t\t<div className=\"flex justify-start\">\n\t\t\t\t{isLoading ? (\n\t\t\t\t\t<LoadingSpinner small />\n\t\t\t\t) : (\n\t\t\t\t\t<Button\n\t\t\t\t\t\tdisabled={!selectedRating && !trimmedReviewText.length}\n\t\t\t\t\t\tonClick={handleSubmitReview}\n\t\t\t\t\t\tscale=\"small\"\n\t\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{resources.SubmitReview}\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import React from 'react';\nimport { StarRating, Typography } from '@faithlife/commerce-components';\nimport { CommandSentence } from '@faithlife/command-sentence-control';\nimport { useLocalization } from '../../../localization';\nimport { hasValidReviewData } from '../../shared/ratings/review-data';\nimport type { RatingsViewModel } from './types';\n\ninterface ReviewHeaderProps {\n\tratings?: RatingsViewModel;\n}\n\nexport const ReviewHeader = ({ ratings }: ReviewHeaderProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Reviews');\n\tconst averageRating = ratings?.averageRating ?? 0;\n\tconst reviewCount = ratings?.numberOfRatings ?? 0;\n\tconst shouldDisplayRatings = ratings?.shouldDisplayStars === true && hasValidReviewData(averageRating, reviewCount);\n\tconst reviewsTemplate = reviewCount === 1 ? resources.BasedOnSingleReview : resources.BasedOnReviews;\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-sp8\">\n\t\t\t{/* Title */}\n\t\t\t<Typography className=\"text-primary-400\" variant=\"headingH4\">\n\t\t\t\t{resources.CustomerReviews}\n\t\t\t</Typography>\n\n\t\t\t{/* Aggregate rating */}\n\t\t\t{shouldDisplayRatings && (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"flex flex-row items-center gap-sp8\">\n\t\t\t\t\t\t<StarRating rating={averageRating} scale=\"md\" />\n\t\t\t\t\t\t<Typography className=\"text-black\" variant=\"bodySmall\">\n\t\t\t\t\t\t\t<CommandSentence Container=\"span\" template={resources.RatingOutOfMax}>\n\t\t\t\t\t\t\t\t<CommandSentence.Field name=\"RATING\">{averageRating.toFixed(1)}</CommandSentence.Field>\n\t\t\t\t\t\t\t\t<CommandSentence.Field name=\"MAXRATING\">{'5'}</CommandSentence.Field>\n\t\t\t\t\t\t\t</CommandSentence>\n\t\t\t\t\t\t</Typography>\n\t\t\t\t\t</div>\n\t\t\t\t\t<Typography className=\"text-black\" variant=\"bodySmall\">\n\t\t\t\t\t\t<CommandSentence key={reviewsTemplate} Container=\"span\" template={reviewsTemplate}>\n\t\t\t\t\t\t\t<CommandSentence.Field name=\"REVIEWCOUNT\">{String(reviewCount)}</CommandSentence.Field>\n\t\t\t\t\t\t</CommandSentence>\n\t\t\t\t\t</Typography>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n","import React from 'react';\nimport { cn } from '../../../util/cn';\n\ntype LinkButtonScale = 'sm' | 'lg';\nconst classesByScale: Record<LinkButtonScale, string> = {\n\tsm: 'text-sm',\n\tlg: 'text-lg',\n};\ntype LinkButtonProps = {\n\tscale: LinkButtonScale;\n\tchildren: React.ReactNode;\n} & React.ComponentPropsWithoutRef<'button'>;\n\nexport default function LinkButton({ scale, children, ...props }: LinkButtonProps) {\n\treturn (\n\t\t<button\n\t\t\tclassName={cn(\n\t\t\t\t'cursor-pointer text-primary hover:text-secondary-200 active:text-secondary-400 disabled:pointer-events-none disabled:text-black disabled:opacity-25 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary',\n\t\t\t\tclassesByScale[scale]\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</button>\n\t);\n}\n","import React, { useCallback } from 'react';\nimport { StarRating, Typography } from '@faithlife/commerce-components';\nimport { CommandSentence } from '@faithlife/command-sentence-control';\nimport { useLocalization } from '../../../localization';\nimport ReviewsClient from '../../../clients/reviews-client';\nimport type { ReviewViewModel, ReviewsRoutes } from './types';\nimport LinkButton from './link-button';\n\ninterface ReviewItemProps {\n\treview: ReviewViewModel;\n\troutes: ReviewsRoutes;\n\tonDeleteReview: (review: ReviewViewModel) => Promise<void>;\n}\n\nexport const ReviewItem = ({ review, onDeleteReview }: ReviewItemProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Reviews');\n\n\tconst { author, localeDate, text, rating, routes: reviewRoutes } = review;\n\n\tconst canDelete = reviewRoutes.DeleteReviewUrl !== undefined;\n\tconst canFlag = reviewRoutes.FlagReviewUrl !== undefined;\n\n\tconst handleFlagClick = useCallback(() => {\n\t\tif (reviewRoutes.FlagReviewUrl) {\n\t\t\tvoid ReviewsClient.flagReview(reviewRoutes.FlagReviewUrl);\n\t\t}\n\t}, [reviewRoutes.FlagReviewUrl]);\n\n\treturn (\n\t\t<li className=\"flex flex-col gap-sp16 border-b border-b-grey pb-sp16 lg:pb-[32px]\">\n\t\t\t{/* Author row */}\n\t\t\t<div className=\"flex flex-row justify-between items-start\">\n\t\t\t\t<Typography className=\"text-black\" variant=\"bodySmall\">\n\t\t\t\t\t{author?.name}\n\t\t\t\t</Typography>\n\t\t\t\t<Typography className=\"text-black-100\" variant=\"bodySmall\">\n\t\t\t\t\t{localeDate}\n\t\t\t\t</Typography>\n\t\t\t</div>\n\n\t\t\t{/* Star rating */}\n\t\t\t{rating !== undefined && (\n\t\t\t\t<div className=\"flex flex-col gap-sp8 lg:flex-row\">\n\t\t\t\t\t<p className=\"flex flex-nowrap text-primary\">\n\t\t\t\t\t\t<StarRating scale=\"md\" rating={rating} />\n\t\t\t\t\t\t<CommandSentence Container=\"span\" className=\"sr-only\" template={resources.SingleRating}>\n\t\t\t\t\t\t\t<CommandSentence.Field name=\"RATINGSCOUNT\">{String(rating)}</CommandSentence.Field>\n\t\t\t\t\t\t</CommandSentence>\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Review text */}\n\t\t\t{text && (\n\t\t\t\t<Typography className=\"text-black\" variant=\"bodyRegular\">\n\t\t\t\t\t{text}\n\t\t\t\t</Typography>\n\t\t\t)}\n\n\t\t\t{/* Actions row: flag / delete (for logged-in users) */}\n\t\t\t{(canDelete || canFlag) && (\n\t\t\t\t<div className=\"flex flex-row items-center gap-sp12\">\n\t\t\t\t\t{canDelete && (\n\t\t\t\t\t\t<LinkButton onClick={() => void onDeleteReview(review)} scale=\"sm\">\n\t\t\t\t\t\t\t{resources.Delete}\n\t\t\t\t\t\t</LinkButton>\n\t\t\t\t\t)}\n\t\t\t\t\t{canFlag && (\n\t\t\t\t\t\t<LinkButton onClick={handleFlagClick} scale=\"sm\">\n\t\t\t\t\t\t\t{resources.Flag}\n\t\t\t\t\t\t</LinkButton>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</li>\n\t);\n};\n","import React from 'react';\nimport { ReviewItem } from './review-item';\nimport type { ReviewViewModel, ReviewsRoutes } from './types';\n\ninterface ReviewsListProps {\n\treviews: ReviewViewModel[];\n\troutes: ReviewsRoutes;\n\tonDeleteReview: (review: ReviewViewModel) => Promise<void>;\n}\n\nexport const ReviewsList = ({ reviews, routes, onDeleteReview }: ReviewsListProps) => {\n\treturn (\n\t\t<ol className=\"flex w-full flex-col gap-sp16 lg:gap-[32px]\">\n\t\t\t{reviews.map(review => (\n\t\t\t\t<ReviewItem key={review.id} onDeleteReview={onDeleteReview} review={review} routes={routes} />\n\t\t\t))}\n\t\t</ol>\n\t);\n};\n","import React from 'react';\nimport { DropdownButton } from '@faithlife/commerce-components';\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuRadioGroup,\n\tDropdownMenuRadioItem,\n\tDropdownMenuTrigger,\n} from '../../shared/dropdown-menu';\nimport { useLocalization } from '../../../localization';\nimport { cn } from '../../../util/cn';\n\nexport type SortMode = 'latest' | 'earliest' | 'rating';\n\nconst sortModes = ['latest', 'earliest', 'rating'] as SortMode[];\n\ninterface SortModeSelectorProps {\n\tsortMode: SortMode;\n\tonSortModeChanged: (mode: SortMode) => void;\n\tclassName?: string;\n}\n\n/* we're sort of fighting with DropdownButton's styling to get this looking somewhat like spec */\n/* TODO this appears to be an input field with dropdown, in terms of styling */\nexport const SortModeSelector = ({ sortMode, onSortModeChanged, className }: SortModeSelectorProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Reviews');\n\n\tconst sortModeLabels: Record<SortMode, string> = {\n\t\tlatest: resources.LatestFirst ?? 'Latest first',\n\t\tearliest: resources.EarliestFirst ?? 'Earliest first',\n\t\trating: resources.ByRating ?? 'By rating',\n\t};\n\n\treturn (\n\t\t<DropdownMenu>\n\t\t\t<DropdownMenuTrigger asChild>\n\t\t\t\t<DropdownButton\n\t\t\t\t\tclassName={cn('border rounded-sm border-gray-400 w-full justify-between', className)}\n\t\t\t\t\tscale=\"sm\"\n\t\t\t\t\ttext={sortModeLabels[sortMode]}\n\t\t\t\t\tvariant=\"subtle\"\n\t\t\t\t/>\n\t\t\t</DropdownMenuTrigger>\n\t\t\t<DropdownMenuContent className=\"mt-sp4 w-(--radix-popper-anchor-width) min-w-0 rounded-sm border border-grey bg-white py-sp4 shadow-md\">\n\t\t\t\t<DropdownMenuRadioGroup\n\t\t\t\t\tonValueChange={(value: string) => onSortModeChanged(value as SortMode)}\n\t\t\t\t\tvalue={sortMode}\n\t\t\t\t>\n\t\t\t\t\t{sortModes.map(mode => (\n\t\t\t\t\t\t<DropdownMenuRadioItem\n\t\t\t\t\t\t\tclassName=\"w-full px-sp12 py-sp8 text-left text-sm text-black hover:bg-grey active:bg-primary-100 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-primary data-[state=checked]:text-primary-500\"\n\t\t\t\t\t\t\tkey={mode}\n\t\t\t\t\t\t\tvalue={mode}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{sortModeLabels[mode]}\n\t\t\t\t\t\t</DropdownMenuRadioItem>\n\t\t\t\t\t))}\n\t\t\t\t</DropdownMenuRadioGroup>\n\t\t\t</DropdownMenuContent>\n\t\t</DropdownMenu>\n\t);\n};\n","import React from 'react';\n\nexport const Divider = () => {\n\treturn <div className=\"border-t border-t-grey\" />;\n};\n","export const REVIEWS_ANCHOR_ID = 'customer-reviews';\n","import React, { useCallback, useEffect, useState } from 'react';\nimport { Button } from '@faithlife/commerce-components';\nimport { useLocalization } from '../../../localization';\nimport ReviewsClient from '../../../clients/reviews-client';\nimport { ReviewEditor } from './review-editor';\nimport { ReviewHeader } from './review-header';\nimport { ReviewsList } from './reviews-list';\nimport { SortModeSelector, type SortMode } from './sort-mode-selector';\nimport type { RatingsViewModel, ReviewViewModel, ReviewsViewModel } from './types';\nimport { Divider } from './divider';\nimport { REVIEWS_ANCHOR_ID } from './reviews-anchor';\n\nexport { REVIEWS_ANCHOR_ID };\n\n// Number of reviews to show per \"page\" / load-more increment\nconst REVIEW_LIMIT_INCREMENT = 10;\n\nconst sortReviews = (a: ReviewViewModel, b: ReviewViewModel, mode: SortMode): number => {\n\tif (mode === 'earliest') {\n\t\tconst da = a.createdDate ?? '';\n\t\tconst db = b.createdDate ?? '';\n\t\treturn da > db ? 1 : db > da ? -1 : 0;\n\t}\n\tif (mode === 'latest') {\n\t\tconst da = a.createdDate ?? '';\n\t\tconst db = b.createdDate ?? '';\n\t\treturn da < db ? 1 : db < da ? -1 : 0;\n\t}\n\t// By rating descending\n\treturn (b.rating ?? 0) - (a.rating ?? 0);\n};\n\ninterface ReviewsProps {\n\treviews: ReviewsViewModel;\n}\n\nconst Reviews = ({ reviews: reviewsProps }: ReviewsProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Reviews');\n\tconst { user, isUserLoggedIn, productId, routes } = reviewsProps;\n\n\tconst [sortMode, setSortMode] = useState<SortMode>('latest');\n\tconst [reviewLimit, setReviewLimit] = useState(REVIEW_LIMIT_INCREMENT);\n\tconst [allReviews, setAllReviews] = useState<ReviewViewModel[]>([]);\n\tconst [serverMayHaveMoreReviews, setServerMayHaveMoreReviews] = useState(true);\n\tconst [ratings, setRatings] = useState<RatingsViewModel | undefined>(reviewsProps.ratings);\n\tconst [isLoading, setIsLoading] = useState(true);\n\n\t// Reviews visible after sort + pagination\n\tconst sortedReviews = [...allReviews].sort((a, b) => sortReviews(a, b, sortMode)).slice(0, reviewLimit);\n\n\t// The current logged-in user's own review (to show \"already reviewed\" state)\n\tconst currentUserReview = allReviews.find(r => r.author?.id === user?.userId);\n\n\t// ─── Initial load ────────────────────────────────────────────────────────────\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\n\t\tconst loadInitialReviews = async () => {\n\t\t\tsetIsLoading(true);\n\t\t\ttry {\n\t\t\t\tconst loadedReviews = await ReviewsClient.getReviews(routes.GetReviewsUrl);\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tsetAllReviews(loadedReviews ?? []);\n\t\t\t\t\tsetServerMayHaveMoreReviews((loadedReviews?.length ?? 0) >= REVIEW_LIMIT_INCREMENT);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tsetIsLoading(false);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tvoid loadInitialReviews();\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [routes.GetReviewsUrl]);\n\n\t// ─── Refresh helpers ─────────────────────────────────────────────────────────\n\tconst refreshRatings = useCallback(async () => {\n\t\tconst newRatings = await ReviewsClient.getRatings(routes.GetRatingsUrl);\n\t\tsetRatings(newRatings);\n\t}, [routes.GetRatingsUrl]);\n\n\tconst refreshReviews = useCallback(async () => {\n\t\tconst newReviews = await ReviewsClient.getReviews(routes.GetReviewsUrl);\n\t\tsetAllReviews(newReviews ?? []);\n\t\tawait refreshRatings();\n\t}, [routes.GetReviewsUrl, refreshRatings]);\n\n\t// ─── Delete ───────────────────────────────────────────────────────────────────\n\tconst handleDeleteReview = useCallback(\n\t\tasync (review: ReviewViewModel) => {\n\t\t\tif (!review.routes.DeleteReviewUrl) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait ReviewsClient.deleteReview(review.routes.DeleteReviewUrl);\n\t\t\tsetAllReviews(prev => prev.filter(r => r.id !== review.id));\n\t\t\tawait refreshRatings();\n\t\t},\n\t\t[refreshRatings]\n\t);\n\n\t// ─── Pagination ───────────────────────────────────────────────────────────────\n\n\tconst canReadMore = allReviews.length > reviewLimit || serverMayHaveMoreReviews;\n\tconst canReadLess = reviewLimit > REVIEW_LIMIT_INCREMENT;\n\n\tconst [isLoadingMore, setIsLoadingMore] = useState(false);\n\tconst handleReadMoreClick = useCallback(async () => {\n\t\t// Fetch the next chunk from the server if we don't have it yet\n\t\tif (allReviews.length <= reviewLimit) {\n\t\t\tsetIsLoadingMore(true);\n\t\t\ttry {\n\t\t\t\tconst additionalReviews = await ReviewsClient.getAdditionalReviews(routes.GetReviewsUrl, reviewLimit);\n\t\t\t\tsetAllReviews(prev => prev.concat(additionalReviews ?? []));\n\t\t\t\tsetServerMayHaveMoreReviews((additionalReviews?.length ?? 0) >= REVIEW_LIMIT_INCREMENT);\n\t\t\t} finally {\n\t\t\t\tsetIsLoadingMore(false);\n\t\t\t}\n\t\t}\n\t\tsetReviewLimit(prev => prev + REVIEW_LIMIT_INCREMENT);\n\t}, [allReviews.length, reviewLimit, routes.GetReviewsUrl]);\n\n\tconst handleReadLessClick = useCallback(() => {\n\t\tsetReviewLimit(prev => prev - REVIEW_LIMIT_INCREMENT);\n\t}, []);\n\n\treturn (\n\t\t<div className=\"tw-preflight flex flex-col lg:flex-row gap-sp16 lg:gap-8 xl:gap-15\" id={REVIEWS_ANCHOR_ID}>\n\t\t\t{/* Left sidebar: aggregate rating summary + editor */}\n\t\t\t<div className=\"lg:w-[338px] shrink-0 flex flex-col gap-sp16 lg:gap-[32px]\">\n\t\t\t\t<ReviewHeader ratings={ratings} />\n\t\t\t\t<Divider />\n\t\t\t\t<ReviewEditor\n\t\t\t\t\tcurrentUserReview={currentUserReview}\n\t\t\t\t\tisUserLoggedIn={isUserLoggedIn}\n\t\t\t\t\tonDeleteReview={handleDeleteReview}\n\t\t\t\t\tonReviewSubmit={refreshReviews}\n\t\t\t\t\tproductId={productId}\n\t\t\t\t\troutes={routes}\n\t\t\t\t\tuser={user}\n\t\t\t\t/>\n\t\t\t</div>\n\n\t\t\t{/* Right content: reviews list */}\n\t\t\t<div className=\"min-w-0 flex-1 flex flex-col gap-sp16 lg:gap-[32px]\">\n\t\t\t\t{isLoading ? (\n\t\t\t\t\t<p className=\"text-sm text-black-100\">{resources.LoadingReviews}</p>\n\t\t\t\t) : sortedReviews.length === 0 ? (\n\t\t\t\t\t<p className=\"pb-sp24 pt-sp4 text-sm text-black-100\">{resources.WriteAReview}</p>\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<SortModeSelector onSortModeChanged={setSortMode} sortMode={sortMode} className=\"w-full lg:max-w-[400px]\" />\n\n\t\t\t\t\t\t<Divider />\n\n\t\t\t\t\t\t<ReviewsList onDeleteReview={handleDeleteReview} reviews={sortedReviews} routes={routes} />\n\n\t\t\t\t\t\t{/* Read more / Read less */}\n\t\t\t\t\t\t<div className=\"mt-sp24 flex items-center gap-sp12\">\n\t\t\t\t\t\t\t{canReadMore && (\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tonClick={() => void handleReadMoreClick()}\n\t\t\t\t\t\t\t\t\tscale=\"small\"\n\t\t\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\t\t\tloading={isLoadingMore}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{resources.ReadMore}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{canReadMore && canReadLess && <span className=\"text-black-100\">{'|'}</span>}\n\t\t\t\t\t\t\t{canReadLess && (\n\t\t\t\t\t\t\t\t<Button onClick={handleReadLessClick} scale=\"small\" variant=\"secondary\">\n\t\t\t\t\t\t\t\t\t{resources.ReadLess}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n\nexport default Reviews;\n","import React from 'react';\n\nimport { useExecuteContentScripts } from './execute-scripts';\n\nconst c_businessDeskProductContentClass = 'bd-product-display-content';\n\n// Amber embed URLs are rewritten into a responsive 16:9 iframe container, matching Skeletor's DisplayContent renderer.\nconst c_amberVideoEmbedRegex = /https:\\/\\/(test\\.)?amber\\.faithlife\\.com\\/shares\\/\\w*\\/embed\\S*/g;\n\ninterface DisplayContentProps {\n\thtml: string;\n\tclassName?: string;\n}\n\nexport const DisplayContent = ({ html, className }: DisplayContentProps) => {\n\tconst rewritten = html.replace(\n\t\tc_amberVideoEmbedRegex,\n\t\t'<div class=\"pcs-embed-16x9\"><iframe frameborder=\"0\" scrolling=\"no\" allowfullscreen src=\"$&\"></iframe></div>'\n\t);\n\n\tconst ref = useExecuteContentScripts(rewritten);\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={className}\n\t\t\t// eslint-disable-next-line react/no-danger\n\t\t\tdangerouslySetInnerHTML={{ __html: rewritten }}\n\t\t/>\n\t);\n};\n\nexport { c_businessDeskProductContentClass };\n","import { useEffect, useRef } from 'react';\n\n// Browsers do not execute <script> tags inserted via innerHTML (which is what\n// dangerouslySetInnerHTML does). CMS \"Business Desk\" content bodies can embed\n// inline and src scripts (e.g. Wistia embeds, refTagger hooks) that must run, so\n// we clone each script into a fresh element to force execution — mirroring\n// Skeletor's executeScriptTagsInContainer.\nexport function executeScriptTagsInContainer(container: HTMLElement) {\n\tconst scripts = Array.from(container.querySelectorAll('script'));\n\tfor (const oldScript of scripts) {\n\t\tconst newScript = document.createElement('script');\n\t\tfor (const attribute of Array.from(oldScript.attributes)) {\n\t\t\tnewScript.setAttribute(attribute.name, attribute.value);\n\t\t}\n\t\t// document.createElement('script') defaults async to true, unlike scripts parsed from HTML.\n\t\t// Force it back off (unless the markup opted in) so a following inline script that depends on\n\t\t// this one's globals isn't racing an in-flight fetch of `src`.\n\t\tnewScript.async = oldScript.hasAttribute('async');\n\t\tnewScript.text = oldScript.text;\n\t\toldScript.parentNode?.replaceChild(newScript, oldScript);\n\t}\n}\n\n// Clones and re-executes any embedded scripts, then re-runs RefTagger so Bible\n// references inside the freshly injected HTML get tagged. Runs on mount / when the\n// html changes, and again whenever the desktop/mobile breakpoint flips, because\n// Skeletor re-renders section bodies on that transition and re-runs their scripts.\nexport function useExecuteContentScripts(html: string, breakpointQuery = '(min-width: 1024px)') {\n\tconst ref = useRef<HTMLDivElement>(null);\n\n\tuseEffect(() => {\n\t\tconst container = ref.current;\n\t\tif (!container) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst runContentScripts = (target: HTMLElement) => {\n\t\t\texecuteScriptTagsInContainer(target);\n\t\t\ttry {\n\t\t\t\tif (typeof window !== 'undefined' && typeof window.refTagger?.tag === 'function') {\n\t\t\t\t\twindow.refTagger.tag();\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('Failed to run RefTagger tag():', error);\n\t\t\t}\n\t\t};\n\n\t\trunContentScripts(container);\n\n\t\tif (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst mediaQuery = window.matchMedia(breakpointQuery);\n\t\tconst handleChange = () => {\n\t\t\tif (ref.current) {\n\t\t\t\trunContentScripts(ref.current);\n\t\t\t}\n\t\t};\n\n\t\tif (typeof mediaQuery.addEventListener === 'function') {\n\t\t\tmediaQuery.addEventListener('change', handleChange);\n\t\t\treturn () => mediaQuery.removeEventListener('change', handleChange);\n\t\t}\n\n\t\t// Safari < 14 fallback.\n\t\tmediaQuery.addListener(handleChange);\n\t\treturn () => mediaQuery.removeListener(handleChange);\n\t}, [html, breakpointQuery]);\n\n\treturn ref;\n}\n","import React, { useEffect } from 'react';\n\nimport { cn } from '../../../util/cn';\n\nconst c_wistiaPlaylistScriptSrc = 'https://fast.wistia.com/assets/external/playlist-v1.js';\nconst c_wistiaSingleScriptSrc = 'https://fast.wistia.net/assets/external/E-v1.js';\n\ninterface EmbeddedVideoProps {\n\tvideoUrl: string;\n\tallowAutoplay?: boolean;\n\tclassName?: string;\n}\n\nfunction scriptAlreadyPresent(src: string): boolean {\n\treturn Boolean(document.querySelector(`script[src=\"${src}\"]`));\n}\n\n// Faithful port of Skeletor's embedded-video component. The raw section content is a URL with three\n// branches: a Wistia playlist (placeholder div + injected Wistia.playlist script), a single Wistia\n// video (iframe + injected E-v1 loader), or any other embed (wrapped in a responsive 16:9 container).\nexport const EmbeddedVideo = ({ videoUrl, allowAutoplay = false, className }: EmbeddedVideoProps) => {\n\tconst isWistiaUrl = videoUrl.includes('wistia');\n\tconst playlistMatch = isWistiaUrl ? videoUrl.match(/playlists\\/(\\w*)/) : null;\n\tconst wistiaPlaylistId = playlistMatch ? playlistMatch[1] : null;\n\n\tconst allowAttributeEntries = ['fullscreen'];\n\tif (allowAutoplay) {\n\t\tallowAttributeEntries.push('autoplay');\n\t}\n\tconst allowAttribute = allowAttributeEntries.join(';');\n\n\tuseEffect(() => {\n\t\tif (!isWistiaUrl) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (wistiaPlaylistId) {\n\t\t\t// Guard against re-injecting the loader on repeated mounts; Skeletor appends these to the\n\t\t\t// body and never cleans them up.\n\t\t\tif (scriptAlreadyPresent(c_wistiaPlaylistScriptSrc)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst wistiaPlaylistsScript = document.createElement('script');\n\t\t\twistiaPlaylistsScript.src = c_wistiaPlaylistScriptSrc;\n\t\t\twistiaPlaylistsScript.async = false;\n\t\t\twistiaPlaylistsScript.onload = () => {\n\t\t\t\tconst playlistDetailsScript = document.createElement('script');\n\t\t\t\tplaylistDetailsScript.type = 'text/javascript';\n\t\t\t\tplaylistDetailsScript.async = false;\n\t\t\t\tplaylistDetailsScript.text = `wistiaPlaylist = Wistia.playlist(\"${wistiaPlaylistId}\", {\n\t\t\t\t\tversion: \"v1\", theme: \"tab\",\n\t\t\t\t\tvideoOptions: { volumeControl: true, autoPlay: true, videoWidth: \"640\", videoHeight: \"360\", inlineOptionsOnly: true, version: \"v1\" },\n\t\t\t\t\tvideoFoam: \"true\",\n\t\t\t\t\tmedia_0_0: { autoPlay: false, controlsVisibleOnLoad: false }\n\t\t\t\t});`;\n\t\t\t\tdocument.body.appendChild(playlistDetailsScript);\n\t\t\t};\n\t\t\tdocument.body.appendChild(wistiaPlaylistsScript);\n\t\t} else if (!scriptAlreadyPresent(c_wistiaSingleScriptSrc)) {\n\t\t\tconst script = document.createElement('script');\n\t\t\tscript.src = c_wistiaSingleScriptSrc;\n\t\t\tscript.async = true;\n\t\t\tdocument.body.appendChild(script);\n\t\t}\n\t}, [isWistiaUrl, wistiaPlaylistId]);\n\n\tif (wistiaPlaylistId) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tid={`wistia_${wistiaPlaylistId}`}\n\t\t\t\tclassName={cn('wistia_embed', className)}\n\t\t\t\tstyle={{ width: '640px', height: '360px' }}\n\t\t\t\tdata-video-width=\"640\"\n\t\t\t\tdata-video-height=\"360\"\n\t\t\t>\n\t\t\t\t&nbsp;\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (isWistiaUrl) {\n\t\treturn (\n\t\t\t<iframe\n\t\t\t\tsrc={videoUrl}\n\t\t\t\ttitle=\"EmbeddedVideo\"\n\t\t\t\tframeBorder=\"0\"\n\t\t\t\tscrolling=\"no\"\n\t\t\t\tname=\"wistia_embed\"\n\t\t\t\tclassName={cn('wistia_embed', className)}\n\t\t\t\tallowFullScreen\n\t\t\t\tallow={allowAttribute}\n\t\t\t/>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className=\"pcs-embed-16x9\">\n\t\t\t<iframe\n\t\t\t\tsrc={videoUrl}\n\t\t\t\ttitle=\"EmbeddedVideo\"\n\t\t\t\tframeBorder=\"0\"\n\t\t\t\tscrolling=\"no\"\n\t\t\t\tclassName={className}\n\t\t\t\tallowFullScreen\n\t\t\t\tallow={allowAttribute}\n\t\t\t/>\n\t\t</div>\n\t);\n};\n\nexport default EmbeddedVideo;\n","import React from 'react';\n\nimport { EmbeddedVideo } from './embedded-video';\n\ninterface EmbeddedVideoSectionProps {\n\tvideoUrl: string;\n}\n\nexport const EmbeddedVideoSection = ({ videoUrl }: EmbeddedVideoSectionProps) => {\n\tif (!videoUrl) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div className=\"video mb-sp24\">\n\t\t\t<EmbeddedVideo videoUrl={videoUrl} />\n\t\t</div>\n\t);\n};\n","import React from 'react';\n\nimport { useLocalization } from '../../../localization';\n\nimport { NamedLink, ProductDetailsMetadata as ProductDetailsMetadataData } from './types';\n\ninterface ProductDetailsMetadataProps {\n\tproductDetailsMetadata: ProductDetailsMetadataData;\n}\n\ninterface MetadataRow {\n\tkey: string;\n\tlabel: string;\n\tvalue: React.ReactNode;\n}\n\n// Interleaves a separator between rendered nodes (e.g. \", \" between author links).\nconst joinNodes = (nodes: React.ReactNode[], separator: string): React.ReactNode[] =>\n\tnodes.flatMap((node, index) => (index === 0 ? [node] : [separator, node]));\n\nconst renderNamedLinks = (items: readonly NamedLink[]): React.ReactNode =>\n\tjoinNodes(\n\t\titems.map((item, index) =>\n\t\t\titem.searchUrl ? (\n\t\t\t\t<a key={index} href={item.searchUrl}>\n\t\t\t\t\t{item.name}\n\t\t\t\t</a>\n\t\t\t) : (\n\t\t\t\t<React.Fragment key={index}>{item.name}</React.Fragment>\n\t\t\t)\n\t\t),\n\t\t', '\n\t);\n\n// Strip trailing period and convert \"--\" hierarchy separator into \"›\".\nconst formatSubject = (subject: string): string => subject.replace(/\\.$/, '').replace(/--/g, ' › ');\n\nexport const ProductDetailsMetadata = ({ productDetailsMetadata: data }: ProductDetailsMetadataProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Details');\n\n\tconst rows: MetadataRow[] = [];\n\n\tif (data.title) {\n\t\trows.push({ key: 'title', label: resources.Title, value: <span className=\"italic\">{data.title}</span> });\n\t}\n\tif (data.authors?.length) {\n\t\trows.push({\n\t\t\tkey: 'authors',\n\t\t\tlabel: data.authors.length > 1 ? resources.Authors : resources.Author,\n\t\t\tvalue: renderNamedLinks(data.authors),\n\t\t});\n\t}\n\tif (data.edition) {\n\t\trows.push({ key: 'edition', label: resources.Edition, value: data.edition });\n\t}\n\tif (data.series) {\n\t\trows.push({ key: 'series', label: resources.Series, value: data.series });\n\t}\n\tif (data.volume) {\n\t\trows.push({ key: 'volume', label: resources.Volume, value: data.volume });\n\t}\n\tif (data.publishers?.length) {\n\t\trows.push({\n\t\t\tkey: 'publishers',\n\t\t\tlabel: data.publishers.length > 1 ? resources.Publishers : resources.Publisher,\n\t\t\tvalue: renderNamedLinks(data.publishers),\n\t\t});\n\t}\n\tif (data.printPublicationYear) {\n\t\trows.push({ key: 'printPublicationYear', label: resources.PrintPublicationDate, value: data.printPublicationYear });\n\t}\n\tif (data.electronicPublicationYear) {\n\t\trows.push({\n\t\t\tkey: 'electronicPublicationYear',\n\t\t\tlabel: resources.LogosReleaseDate,\n\t\t\tvalue: data.electronicPublicationYear,\n\t\t});\n\t}\n\tif (data.pageCount) {\n\t\trows.push({ key: 'pageCount', label: resources.Pages, value: String(data.pageCount) });\n\t}\n\tif (data.era) {\n\t\trows.push({ key: 'era', label: resources.Era, value: data.era });\n\t}\n\tif (data.languages?.length) {\n\t\trows.push({\n\t\t\tkey: 'languages',\n\t\t\tlabel: data.languages.length > 1 ? resources.Languages : resources.Language,\n\t\t\tvalue: data.languages.join(', '),\n\t\t});\n\t}\n\tif (data.resourceCount) {\n\t\trows.push({ key: 'resourceCount', label: resources.Resources, value: String(data.resourceCount) });\n\t}\n\t// Format always renders, even when the other rows are empty.\n\tif (data.format) {\n\t\trows.push({\n\t\t\tkey: 'format',\n\t\t\tlabel: resources.Format,\n\t\t\tvalue: (\n\t\t\t\t<>\n\t\t\t\t\t{data.format.formatType}\n\t\t\t\t\t{data.format.searchUrl ? (\n\t\t\t\t\t\t<a href={data.format.searchUrl}>{data.format.name}</a>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<span>{data.format.name}</span>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t),\n\t\t});\n\t}\n\tif (data.subjects?.length) {\n\t\trows.push({\n\t\t\tkey: 'subjects',\n\t\t\tlabel: data.subjects.length > 1 ? resources.Subjects : resources.Subject,\n\t\t\tvalue: data.subjects.map(formatSubject).join('; '),\n\t\t});\n\t}\n\tif (data.isbns?.length) {\n\t\trows.push({\n\t\t\tkey: 'isbns',\n\t\t\tlabel: data.isbns.length > 1 ? resources.Isbns : resources.Isbn,\n\t\t\tvalue: joinNodes(\n\t\t\t\tdata.isbns.map((isbn, index) => (\n\t\t\t\t\t<a key={index} href={`/search?query=${isbn}`}>\n\t\t\t\t\t\t{isbn}\n\t\t\t\t\t</a>\n\t\t\t\t)),\n\t\t\t\t', '\n\t\t\t),\n\t\t});\n\t}\n\tif (data.resourceId) {\n\t\trows.push({ key: 'resourceId', label: resources.ResourceId, value: data.resourceId });\n\t}\n\tif (data.resourceType) {\n\t\trows.push({ key: 'resourceType', label: resources.ResourceType, value: data.resourceType });\n\t}\n\tif (data.version) {\n\t\trows.push({ key: 'version', label: resources.MetadataLastUpdated, value: data.version });\n\t}\n\n\treturn (\n\t\t<ul className=\"product-details-metadata\">\n\t\t\t{rows.map(row => (\n\t\t\t\t<li key={row.key}>\n\t\t\t\t\t{`${row.label}: `}\n\t\t\t\t\t{row.value}\n\t\t\t\t</li>\n\t\t\t))}\n\t\t</ul>\n\t);\n};\n\nexport default ProductDetailsMetadata;\n","import React from 'react';\nimport { AuthorBio as SharedAuthorBio } from '../../shared/author-bio';\nimport { useLocalization } from '../../../localization';\nimport { AuthorBio as AuthorBioData } from './types';\n\ninterface AuthorBioSectionProps {\n\tauthorBio: AuthorBioData;\n}\n\nexport const AuthorBioSection = ({ authorBio }: AuthorBioSectionProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Search.AuthorBio');\n\n\treturn (\n\t\t<SharedAuthorBio\n\t\t\tdisplayName={authorBio.name}\n\t\t\timageUrl={authorBio.imageUrl}\n\t\t\tbio={authorBio.bio}\n\t\t\tresources={{ showMore: resources.showMore, showLess: resources.showLess }}\n\t\t/>\n\t);\n};\n","import { DisplayContentKind, DisplayTemplateKind } from './types';\n\nexport type SectionRenderMode = 'inline' | 'video' | 'accordion' | 'hidden' | 'containedResources';\n\nexport interface SectionDescriptor {\n\t// `kind` is set for every CMS-authored section. It is omitted only for the dynamic\n\t// `containedResources` section, which is API-driven rather than CMS content.\n\tkind?: DisplayContentKind;\n\tmode: SectionRenderMode;\n\t// Localization key (in CommerceWeb.Resources.Product.Details) for the dynamic\n\t// contained-resources accordion header. Skeletor titles it \"Resources included\" for\n\t// collections/mobile-ed single resources and \"Courses included\" for mobile-ed bundles.\n\tcontainedResourcesTitleKey?: 'ResourcesIncluded' | 'CoursesIncluded';\n}\n\n// CMS content sections rendered in the content region, in Skeletor's per-template relative order.\n// Dynamic sections (ContainingProducts, SamplePages, Reviews, AdZone, etc.) keep their existing\n// CommerceWeb positions and are not listed here. TimeSensitiveCallOut is rendered above the body by\n// the existing TimeSensitiveCalloutBlock, and the Overview renders in the right column via the\n// ProductDescription component, so both are intentionally omitted here.\nconst c_default: SectionDescriptor[] = [\n\t{ kind: 'InformationalCallOut', mode: 'inline' },\n\t{ kind: 'KeyFeatures', mode: 'accordion' },\n\t{ kind: 'TopHighlights', mode: 'accordion' },\n\t{ kind: 'TableOfContents', mode: 'accordion' },\n\t{ kind: 'Contributors', mode: 'accordion' },\n\t{ kind: 'Endorsements', mode: 'accordion' },\n\t{ kind: 'ProductDetails', mode: 'accordion' },\n\t{ kind: 'AboutAuthor', mode: 'accordion' },\n\t{ kind: 'ExtraProductImages', mode: 'accordion' },\n\t{ kind: 'Extras', mode: 'accordion' },\n];\n\nconst c_singleVolume: SectionDescriptor[] = [\n\t{ kind: 'InformationalCallOut', mode: 'inline' },\n\t{ kind: 'MessagingBanner', mode: 'inline' },\n\t{ kind: 'EmbeddedVideo', mode: 'video' },\n\t{ kind: 'KeyFeatures', mode: 'accordion' },\n\t{ kind: 'TopHighlights', mode: 'accordion' },\n\t{ kind: 'TableOfContents', mode: 'accordion' },\n\t{ kind: 'Contributors', mode: 'accordion' },\n\t{ kind: 'Endorsements', mode: 'accordion' },\n\t{ kind: 'ProductDetails', mode: 'accordion' },\n\t{ kind: 'BenefitsOfLogos', mode: 'accordion' },\n\t{ kind: 'AboutAuthor', mode: 'accordion' },\n\t{ kind: 'ExtraProductImages', mode: 'accordion' },\n\t{ kind: 'Extras', mode: 'accordion' },\n];\n\nconst c_collection: SectionDescriptor[] = [\n\t{ kind: 'InformationalCallOut', mode: 'inline' },\n\t{ kind: 'MessagingBanner', mode: 'inline' },\n\t{ kind: 'EmbeddedVideo', mode: 'video' },\n\t{ kind: 'KeyFeatures', mode: 'accordion' },\n\t{ kind: 'Contributors', mode: 'accordion' },\n\t{ kind: 'Endorsements', mode: 'accordion' },\n\t{ kind: 'ProductDetails', mode: 'accordion' },\n\t{ kind: 'IndividualTitles', mode: 'hidden' },\n\t{ kind: 'BenefitsOfLogos', mode: 'accordion' },\n\t{ kind: 'IndividualOverviews', mode: 'accordion' },\n\t{ kind: 'AboutAuthor', mode: 'accordion' },\n\t{ kind: 'ExtraProductImages', mode: 'accordion' },\n\t{ kind: 'Extras', mode: 'accordion' },\n\t{ mode: 'containedResources', containedResourcesTitleKey: 'ResourcesIncluded' },\n];\n\n// Skeletor's library-details-page renders only: InformationalCallOut, MessagingBanner,\n// EmbeddedVideo, BenefitsOfLogos, and ContainedResources (plus Overview/TimeSensitiveCallOut\n// which are handled outside ProductContentSections). No KeyFeatures, Contributors, or other\n// accordion sections are rendered for library products.\nconst c_library: SectionDescriptor[] = [\n\t{ kind: 'InformationalCallOut', mode: 'inline' },\n\t{ kind: 'MessagingBanner', mode: 'inline' },\n\t{ kind: 'EmbeddedVideo', mode: 'video' },\n\t{ kind: 'BenefitsOfLogos', mode: 'accordion' },\n\t{ kind: 'Extras', mode: 'accordion' },\n\t{ mode: 'containedResources', containedResourcesTitleKey: 'ResourcesIncluded' },\n];\n\nconst c_mobileEdSingleResource: SectionDescriptor[] = [\n\t{ kind: 'EmbeddedVideo', mode: 'video' },\n\t{ kind: 'InformationalCallOut', mode: 'inline' },\n\t{ kind: 'MessagingBanner', mode: 'inline' },\n\t{ kind: 'LearningObjectives', mode: 'accordion' },\n\t{ kind: 'CourseOutline', mode: 'accordion' },\n\t{ kind: 'AssociatedReading', mode: 'accordion' },\n\t{ kind: 'ProductDetails', mode: 'accordion' },\n\t{ kind: 'AboutInstructor', mode: 'accordion' },\n\t{ kind: 'BenefitsOfMobileEd', mode: 'hidden' },\n\t{ kind: 'Extras', mode: 'accordion' },\n\t{ mode: 'containedResources', containedResourcesTitleKey: 'ResourcesIncluded' },\n];\n\nconst c_mobileEdBundle: SectionDescriptor[] = [\n\t{ kind: 'EmbeddedVideo', mode: 'video' },\n\t{ kind: 'InformationalCallOut', mode: 'inline' },\n\t{ kind: 'MessagingBanner', mode: 'inline' },\n\t{ kind: 'LearningObjectives', mode: 'accordion' },\n\t{ kind: 'IndividualCourses', mode: 'hidden' },\n\t{ kind: 'ProductDetails', mode: 'accordion' },\n\t{ kind: 'IndividualOverviews', mode: 'accordion' },\n\t{ kind: 'Extras', mode: 'accordion' },\n\t{ mode: 'containedResources', containedResourcesTitleKey: 'CoursesIncluded' },\n];\n\nexport function getSectionsForTemplate(kind: DisplayTemplateKind): SectionDescriptor[] {\n\tswitch (kind) {\n\t\tcase 'singleVolume':\n\t\t\treturn c_singleVolume;\n\t\tcase 'collection':\n\t\tcase 'featureSet':\n\t\t\treturn c_collection;\n\t\tcase 'library':\n\t\t\treturn c_library;\n\t\tcase 'mobileEdSingleResource':\n\t\t\treturn c_mobileEdSingleResource;\n\t\tcase 'mobileEdBundle':\n\t\t\treturn c_mobileEdBundle;\n\t\tdefault:\n\t\t\treturn c_default;\n\t}\n}\n","import React from 'react';\nimport {\n\tAccordion,\n\tAccordionContent,\n\tAccordionItem,\n\tAccordionTrigger,\n\tContainedResources,\n\tContentSection,\n\tuseContainedResourcesContext,\n\ttype ContainedResourcesData,\n\ttype DataResult,\n} from '@faithlife/commerce-components';\n\nimport { useLocalization } from '../../../localization';\nimport { useCurrentUser } from '../../per-user-data/per-user-data-context';\n\nimport '../product-details-page/product-details.css';\nimport './product-content-sections.css';\n\nimport { DisplayContent, c_businessDeskProductContentClass } from './display-content';\nimport { EmbeddedVideoSection } from './embedded-video-section';\nimport { ProductDetailsMetadata } from './product-details-metadata';\nimport { AuthorBioSection } from './author-bio-section';\nimport { getSectionsForTemplate } from './section-config';\nimport {\n\tDisplayContent as DisplayContentData,\n\tDisplayTemplate,\n\tProductDetailsMetadata as ProductDetailsMetadataData,\n\tAuthorBio as AuthorBioData,\n} from './types';\n\ninterface ProductContentSectionsProps {\n\tdisplayTemplate?: DisplayTemplate | null;\n\tproductId?: string;\n\tproductDetailsMetadata?: ProductDetailsMetadataData | null;\n\tauthorBio?: AuthorBioData | null;\n}\n\ninterface AccordionSectionData {\n\ttitle: string;\n\tchildren: React.ReactNode;\n}\n\n// CMS-authored content-section titles can contain inline markup (e.g. <i>Book Title</i>),\n// drawn from the same trusted \"Business Desk\" HTML as the section body. This node is passed\n// directly as children to <AccordionTrigger>, which renders it as a React child so the\n// markup displays correctly. Plain localized/resource titles pass through unchanged\n// (rendering a plain string as HTML is a no-op). The codebase trusts CMS HTML directly;\n// there is no separate sanitizer.\nconst AccordionHtmlTitle = ({ html }: { html: string }) => (\n\t// eslint-disable-next-line react/no-danger\n\t<span className=\"line-clamp-2 font-semibold\" dangerouslySetInnerHTML={{ __html: html }} />\n);\n\nconst c_noProductComponents: DataResult<ContainedResourcesData> = {\n\tdata: null,\n\tisLoading: false,\n\tisRefetching: false,\n\terror: null,\n};\n\nconst useNoProductComponents = () => c_noProductComponents;\n\nexport const ProductContentSections = ({\n\tdisplayTemplate,\n\tproductId,\n\tproductDetailsMetadata,\n\tauthorBio,\n}: ProductContentSectionsProps) => {\n\tconst { useProductComponents = useNoProductComponents } = useContainedResourcesContext();\n\tconst { isSignedIn } = useCurrentUser();\n\tconst detailsResources = useLocalization('CommerceWeb.Resources.Product.Details');\n\tconst authorBioResources = useLocalization('CommerceWeb.Resources.Search.AuthorBio');\n\n\tconst templateKind = displayTemplate?.kind;\n\t// Skeletor fetches contained resources (and thus can suppress the legacy CMS\n\t// IndividualTitles/IndividualOverviews sections) only for templates that actually\n\t// render a dynamic contained-resources section.\n\tconst templateFetchesContainedResources =\n\t\t!!templateKind && getSectionsForTemplate(templateKind).some(descriptor => descriptor.mode === 'containedResources');\n\n\tconst { data: productComponents } = useProductComponents(templateFetchesContainedResources ? productId : undefined);\n\tconst hasContainedResources = (productComponents?.sections?.length ?? 0) > 0;\n\tconst isProductOwned = !!productComponents?.isOwnedByUser;\n\n\tif (!displayTemplate) {\n\t\treturn null;\n\t}\n\n\tconst descriptors = getSectionsForTemplate(displayTemplate.kind);\n\tconst nodes: React.ReactNode[] = [];\n\tlet containedResourcesTitle: string | null = null;\n\tlet pendingAccordion: AccordionSectionData[] = [];\n\tlet accordionGroupIndex = 0;\n\n\tconst flushAccordion = () => {\n\t\tif (pendingAccordion.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tnodes.push(\n\t\t\t<Accordion key={`accordion-${accordionGroupIndex}`}>\n\t\t\t\t{pendingAccordion.map((section, sectionIndex) => (\n\t\t\t\t\t<AccordionItem key={`section-${sectionIndex}`} value={`section-${sectionIndex}`}>\n\t\t\t\t\t\t<AccordionTrigger>\n\t\t\t\t\t\t\t<AccordionHtmlTitle html={section.title} />\n\t\t\t\t\t\t</AccordionTrigger>\n\t\t\t\t\t\t<AccordionContent>{section.children}</AccordionContent>\n\t\t\t\t\t</AccordionItem>\n\t\t\t\t))}\n\t\t\t</Accordion>\n\t\t);\n\t\taccordionGroupIndex += 1;\n\t\tpendingAccordion = [];\n\t};\n\n\tdescriptors.forEach(descriptor => {\n\t\tif (descriptor.mode === 'containedResources') {\n\t\t\tif (hasContainedResources && productId) {\n\t\t\t\tcontainedResourcesTitle =\n\t\t\t\t\tdescriptor.containedResourcesTitleKey === 'CoursesIncluded'\n\t\t\t\t\t\t? detailsResources.CoursesIncluded\n\t\t\t\t\t\t: detailsResources.ResourcesIncluded;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst { kind } = descriptor;\n\t\tif (!kind) {\n\t\t\treturn;\n\t\t}\n\n\t\t// When dynamic contained-resources data is present, it supersedes the legacy CMS\n\t\t// IndividualTitles/IndividualOverviews sections (matching Skeletor's suppression).\n\t\tif (hasContainedResources && (kind === 'IndividualTitles' || kind === 'IndividualOverviews')) {\n\t\t\treturn;\n\t\t}\n\n\t\t// The ProductDetails slot is mutually exclusive: CMS-authored HTML wins, otherwise the\n\t\t// dynamic metadata list (supplied by the backend only for single-volume products lacking\n\t\t// authored ProductDetails HTML) renders in the same accordion slot.\n\t\tif (kind === 'ProductDetails') {\n\t\t\tconst productDetailsSection = displayTemplate.content.ProductDetails;\n\t\t\tconst productDetailsContent = productDetailsSection?.content;\n\t\t\tif (productDetailsContent) {\n\t\t\t\tpendingAccordion.push({\n\t\t\t\t\ttitle: productDetailsSection?.title ?? '',\n\t\t\t\t\tchildren: <DisplayContent html={productDetailsContent} />,\n\t\t\t\t});\n\t\t\t} else if (productDetailsMetadata) {\n\t\t\t\tpendingAccordion.push({\n\t\t\t\t\ttitle: detailsResources.ProductDetails,\n\t\t\t\t\tchildren: <ProductDetailsMetadata productDetailsMetadata={productDetailsMetadata} />,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// The AboutAuthor / AboutInstructor slot is mutually exclusive with the OPPOSITE precedence\n\t\t// from ProductDetails: the dynamically-fetched author bio wins, and the authored content\n\t\t// section is only the fallback. Per product decision, the slot renders only when there is\n\t\t// either an author bio or non-whitespace authored content (no empty accordion).\n\t\tif (kind === 'AboutAuthor' || kind === 'AboutInstructor') {\n\t\t\tif (authorBio) {\n\t\t\t\tpendingAccordion.push({\n\t\t\t\t\ttitle: authorBioResources.aboutName.replace('%NAME%', authorBio.name),\n\t\t\t\t\tchildren: <AuthorBioSection authorBio={authorBio} />,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst authorSection = displayTemplate.content[kind];\n\t\t\t\tconst authorContent = authorSection?.content;\n\t\t\t\tif (authorContent && authorContent.trim()) {\n\t\t\t\t\tpendingAccordion.push({\n\t\t\t\t\t\ttitle: authorSection?.title ?? '',\n\t\t\t\t\t\tchildren: <DisplayContent html={authorContent} />,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst section: DisplayContentData | undefined = displayTemplate.content[kind];\n\t\tconst content = section?.content;\n\t\tif (!content) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (descriptor.mode) {\n\t\t\tcase 'inline':\n\t\t\t\tflushAccordion();\n\t\t\t\tnodes.push(<DisplayContent key={kind} html={content} />);\n\t\t\t\tbreak;\n\t\t\tcase 'video':\n\t\t\t\tflushAccordion();\n\t\t\t\tnodes.push(<EmbeddedVideoSection key={kind} videoUrl={content} />);\n\t\t\t\tbreak;\n\t\t\tcase 'hidden':\n\t\t\t\tflushAccordion();\n\t\t\t\tnodes.push(\n\t\t\t\t\t<div\n\t\t\t\t\t\tkey={kind}\n\t\t\t\t\t\tclassName=\"hidden\"\n\t\t\t\t\t\t// eslint-disable-next-line react/no-danger\n\t\t\t\t\t\tdangerouslySetInnerHTML={{ __html: content }}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase 'accordion':\n\t\t\tdefault:\n\t\t\t\t// The accordion chrome requires a title to render its collapse toggle, so\n\t\t\t\t// a missing title falls back to an empty string rather than rendering the\n\t\t\t\t// section outside the accordion. The backend always supplies a title when the\n\t\t\t\t// CMS title is blank (deriving one from the content's first heading, or a\n\t\t\t\t// per-kind default such as \"Benefits of Logos Edition\" for BenefitsOfLogos).\n\t\t\t\tpendingAccordion.push({\n\t\t\t\t\ttitle: section?.title || '',\n\t\t\t\t\tchildren: <DisplayContent html={content} />,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\tflushAccordion();\n\n\tconst hasContainedSection = !!containedResourcesTitle && !!productId;\n\n\tif (nodes.length === 0 && !hasContainedSection) {\n\t\treturn null;\n\t}\n\n\tconst c_innerConstraint = 'max-w-[696px] max-lg:mx-sp16 lg:w-1/2 lg:px-6 lg:pb-6 lg:pr-sp16';\n\n\treturn (\n\t\t<div className={c_businessDeskProductContentClass}>\n\t\t\t{nodes.length > 0 && <div className={c_innerConstraint}>{nodes}</div>}\n\t\t\t{hasContainedSection && (\n\t\t\t\t<>\n\t\t\t\t\t<hr className=\"hidden lg:block border-grey lg:mx-sp24\" />\n\t\t\t\t\t<div className={c_innerConstraint}>\n\t\t\t\t\t\t<ContentSection sectionHeadline={containedResourcesTitle ?? ''}>\n\t\t\t\t\t\t\t<ContainedResources defaultHideOwned={isSignedIn && !isProductOwned} productId={productId ?? ''} />\n\t\t\t\t\t\t</ContentSection>\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n\nexport default ProductContentSections;\n","import React, { useState } from 'react';\nimport { CommandSentence } from '@faithlife/command-sentence-control';\nimport * as Popover from '@radix-ui/react-popover';\nimport { ChevronDown } from 'lucide-react';\nimport { useLocalization } from '../../../../localization';\nimport useScreensize from '../../../../util/hooks/use-screensize';\n\nconst formatName = (name: string) => {\n\tconst [lastName, firstName] = name.split(', ');\n\n\treturn firstName && lastName ? `${firstName} ${lastName}` : name;\n};\n\ninterface Chip {\n\tname: string;\n\turl: string | null | undefined;\n}\n\ninterface AttributeChipsProps {\n\tchips: readonly Chip[];\n\tlabel?: string;\n\tlabelClassName?: string;\n\ttrailingContent?: React.ReactNode;\n}\n\nconst linkClassName =\n\t'text-primary hover:underline focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-primary';\n\nexport const AttributeChips = ({ chips, label, labelClassName, trailingContent }: AttributeChipsProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Details');\n\tconst { isMobile } = useScreensize();\n\tconst [open, setOpen] = useState(false);\n\n\tif (!chips.length) {\n\t\treturn null;\n\t}\n\n\tconst visibleChipCount = isMobile ? 1 : 4;\n\tconst visibleChips = chips.slice(0, visibleChipCount);\n\tconst overflowChips = chips.slice(visibleChipCount);\n\n\treturn (\n\t\t<div className=\"flex flex-wrap items-baseline gap-x-1 text-sm leading-5 text-black-200\">\n\t\t\t{label ? <span className={labelClassName}>{label}</span> : null}\n\t\t\t{visibleChips.map((chip, i) => (\n\t\t\t\t<span data-testid=\"attribute-chip\" key={i}>\n\t\t\t\t\t<a className={linkClassName} href={chip.url ?? undefined}>\n\t\t\t\t\t\t{formatName(chip.name)}\n\t\t\t\t\t</a>\n\t\t\t\t\t{i < visibleChips.length - 1 ? <span>{';'}</span> : null}\n\t\t\t\t</span>\n\t\t\t))}\n\t\t\t{overflowChips.length ? (\n\t\t\t\t<CommandSentence\n\t\t\t\t\tContainer=\"span\"\n\t\t\t\t\tclassName=\"inline-flex items-baseline gap-x-1\"\n\t\t\t\t\ttemplate={resources.AndMoreTooltip}\n\t\t\t\t>\n\t\t\t\t\t<CommandSentence.Field name=\"MORETOOLTIP\">\n\t\t\t\t\t\t<Popover.Root onOpenChange={setOpen} open={open}>\n\t\t\t\t\t\t\t<Popover.Trigger\n\t\t\t\t\t\t\t\tclassName=\"inline-flex cursor-pointer items-center gap-0.5 text-primary underline decoration-dashed underline-offset-2 hover:text-primary-400 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-primary\"\n\t\t\t\t\t\t\t\tonClick={() => setOpen(true)}\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<CommandSentence Container=\"span\" template={resources.MoreTooltipText}>\n\t\t\t\t\t\t\t\t\t<CommandSentence.Field name=\"AMOUNT\">{String(overflowChips.length)}</CommandSentence.Field>\n\t\t\t\t\t\t\t\t</CommandSentence>\n\t\t\t\t\t\t\t\t<ChevronDown className=\"size-4\" />\n\t\t\t\t\t\t\t</Popover.Trigger>\n\t\t\t\t\t\t\t<Popover.Content className=\"z-50 flex max-h-[40vh] max-w-sm flex-col gap-1 overflow-y-auto rounded-sm bg-white p-4 text-sm shadow\">\n\t\t\t\t\t\t\t\t{overflowChips.map((chip, i) => (\n\t\t\t\t\t\t\t\t\t<a className={linkClassName} href={chip.url ?? undefined} key={i}>\n\t\t\t\t\t\t\t\t\t\t{formatName(chip.name)}\n\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</Popover.Content>\n\t\t\t\t\t\t</Popover.Root>\n\t\t\t\t\t</CommandSentence.Field>\n\t\t\t\t</CommandSentence>\n\t\t\t) : null}\n\t\t\t{trailingContent}\n\t\t</div>\n\t);\n};\n\ninterface AuthorsAndPublishersProps {\n\tauthors: readonly Chip[];\n\tpublishers: readonly Chip[];\n\tpublisherMetadata?: React.ReactNode;\n}\n\nexport const AuthorsAndPublishers = ({ authors, publishers, publisherMetadata }: AuthorsAndPublishersProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Details');\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-1 text-black-200\">\n\t\t\t<AttributeChips chips={authors} label={resources.By} />\n\t\t\t{publishers.length || publisherMetadata ? (\n\t\t\t\t<div className=\"flex flex-wrap items-baseline gap-x-2 gap-y-1\">\n\t\t\t\t\t<AttributeChips\n\t\t\t\t\t\tchips={publishers}\n\t\t\t\t\t\tlabel={`${resources.Publisher}:`}\n\t\t\t\t\t\tlabelClassName=\"font-semibold\"\n\t\t\t\t\t\ttrailingContent={publisherMetadata}\n\t\t\t\t\t/>\n\t\t\t\t\t{publishers.length ? null : publisherMetadata}\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t</div>\n\t);\n};\n","import React from 'react';\nimport cn from 'classnames';\nimport * as Popover from '@radix-ui/react-popover';\nimport { Typography } from '@faithlife/commerce-components';\nimport { useLocalization } from '../../../localization';\nimport { ProductPricingSkuData } from '../../per-user-data/per-user-data-context';\n\ninterface SalePricePopoverProps {\n\tprices: NonNullable<ProductPricingSkuData['prices']>;\n\tclassName?: string;\n}\n\nexport const SalePricePopover = ({ prices, className }: SalePricePopoverProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.DisplayTemplates.PricingSidebarViewModel');\n\n\tconst triggerLabel = prices.breakdownTriggerLabel;\n\tconst lines = prices.breakdownLines ?? [];\n\tif (!triggerLabel || lines.length === 0) {\n\t\treturn null;\n\t}\n\n\t// Reference/list prices display in USD; savings and collection rows display in the user's\n\t// localized currency. The server decides per row via `displayInUsd`.\n\tconst resolveAmount = (line: (typeof lines)[number]) =>\n\t\tline.displayInUsd\n\t\t\t? (line.amount.displayAmount ?? line.amount.localizedDisplayAmount ?? '')\n\t\t\t: (line.amount.localizedDisplayAmount ?? line.amount.displayAmount ?? '');\n\n\tconst finalAmount = prices.salePrice?.displayAmount ?? prices.salePrice?.localizedDisplayAmount ?? '';\n\n\treturn (\n\t\t<Popover.Root>\n\t\t\t<Popover.Trigger asChild>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\taria-label={resources.SeePricingBreakdown}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'w-fit cursor-pointer whitespace-nowrap text-sm font-semibold text-primary underline decoration-dashed underline-offset-2 hover:text-primary-400 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-primary',\n\t\t\t\t\t\tclassName\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<Typography variant=\"ui2\" className=\"font-semibold\">\n\t\t\t\t\t\t{triggerLabel}\n\t\t\t\t\t</Typography>\n\t\t\t\t</button>\n\t\t\t</Popover.Trigger>\n\t\t\t<Popover.Portal>\n\t\t\t\t<Popover.Content\n\t\t\t\t\tsideOffset={8}\n\t\t\t\t\talign=\"start\"\n\t\t\t\t\tclassName=\"z-50 flex w-max min-w-72 max-w-[90vw] flex-col gap-2 rounded-sm bg-white p-6 text-sm shadow-lg\"\n\t\t\t\t>\n\t\t\t\t\t{lines.map((line, index) => {\n\t\t\t\t\t\tconst amount = resolveAmount(line);\n\t\t\t\t\t\tconst label = line.href ? (\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref={line.href}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\tclassName=\"text-black-200 underline hover:text-primary\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{line.label}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\tline.label\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<div className=\"flex items-baseline justify-between gap-6\" key={`${line.label}-${index}`}>\n\t\t\t\t\t\t\t\t<Typography aria-label={line.label} className=\"text-black-200\" tag=\"span\" variant=\"ui2\">\n\t\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t\t\t<Typography\n\t\t\t\t\t\t\t\t\tclassName={cn('whitespace-nowrap', line.isDeduction ? 'text-danger' : 'text-black-200')}\n\t\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\t\tvariant=\"ui2\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{line.isDeduction ? `-${amount}` : amount}\n\t\t\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t\t<hr className=\"my-1 border-black-50\" />\n\t\t\t\t\t<div className=\"flex items-baseline justify-between gap-6\">\n\t\t\t\t\t\t<Typography className=\"font-semibold\" tag=\"span\" variant=\"ui1\">\n\t\t\t\t\t\t\t{triggerLabel}\n\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t<Typography className=\"whitespace-nowrap font-semibold\" tag=\"span\" variant=\"ui1\">\n\t\t\t\t\t\t\t{finalAmount}\n\t\t\t\t\t\t</Typography>\n\t\t\t\t\t</div>\n\t\t\t\t\t<Popover.Arrow className=\"fill-white\" />\n\t\t\t\t</Popover.Content>\n\t\t\t</Popover.Portal>\n\t\t</Popover.Root>\n\t);\n};\n","import React from 'react';\nimport cn from 'classnames';\nimport { Typography } from '@faithlife/commerce-components';\nimport { ProductPriceDiscount, ProductPricingSkuData } from '../../per-user-data/per-user-data-context';\nimport { SalePricePopover } from './sale-price-popover';\n\ntype PricesVariant = 'full' | 'salePriceOnly';\n\ninterface PricesProps {\n\tprices: ProductPricingSkuData['prices'];\n\tisRestricted: boolean;\n\tvariant?: PricesVariant;\n}\n\nexport const Prices = ({ prices, isRestricted, variant = 'full' }: PricesProps) => {\n\tif (!prices) {\n\t\treturn null;\n\t}\n\n\tconst salePrice = prices.salePrice?.displayAmount ?? '';\n\tconst discounts = prices.discounts?.filter(discount => discount.description);\n\tconst nonStackingDiscounts = discounts?.filter(discount => !discount.shouldStack);\n\tconst stackingDiscounts = discounts?.filter(discount => discount.shouldStack);\n\n\tconst localizedSalePrice = prices.salePrice?.localizedDisplayAmount;\n\n\tconst salePriceTemplate = (\n\t\t<Typography\n\t\t\taria-label=\"Sale Price\"\n\t\t\tvariant=\"bodyLarge\"\n\t\t\tclassName={cn('font-semibold', isRestricted && 'text-black-100')}\n\t\t\ttag=\"span\"\n\t\t>\n\t\t\t{salePrice}\n\t\t</Typography>\n\t);\n\n\tconst renderDiscountPills = (discounts: ProductPriceDiscount[] | undefined, className: string) =>\n\t\tdiscounts &&\n\t\tdiscounts.map((discount, index) => (\n\t\t\t<Typography\n\t\t\t\tkey={`${discount.description}-${index}`}\n\t\t\t\taria-label=\"Discount Description\"\n\t\t\t\tvariant=\"ui2\"\n\t\t\t\tclassName={cn('rounded-full px-sp8 py-sp2', className)}\n\t\t\t\ttag=\"span\"\n\t\t\t>\n\t\t\t\t{discount.description}\n\t\t\t</Typography>\n\t\t));\n\n\tif (variant === 'salePriceOnly') {\n\t\treturn salePriceTemplate;\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-sp12\">\n\t\t\t{nonStackingDiscounts && nonStackingDiscounts.length > 0 ? (\n\t\t\t\t<div className=\"flex flex-wrap gap-2\">{renderDiscountPills(nonStackingDiscounts, `bg-red-200 text-black`)}</div>\n\t\t\t) : null}\n\t\t\t<div className=\"flex flex-wrap items-center gap-2\">\n\t\t\t\t<SalePricePopover prices={prices} className=\"shrink-0\" />\n\t\t\t\t{renderDiscountPills(stackingDiscounts, 'bg-primary-200 text-primary-400')}\n\t\t\t</div>\n\t\t\t{salePriceTemplate}\n\t\t\t{localizedSalePrice ? (\n\t\t\t\t<Typography\n\t\t\t\t\taria-label=\"Localized Sale Price\"\n\t\t\t\t\tvariant=\"ui2\"\n\t\t\t\t\tclassName=\"text-black-200 font-normal\"\n\t\t\t\t\ttag=\"span\"\n\t\t\t\t>{`(${localizedSalePrice})`}</Typography>\n\t\t\t) : null}\n\t\t\t{(prices.anchorPriceLines ?? []).map(({ label, displayAmount, localizedDisplayAmount }) => {\n\t\t\t\tconst amount = localizedDisplayAmount ?? displayAmount;\n\t\t\t\treturn (\n\t\t\t\t\t<Typography\n\t\t\t\t\t\tkey={label}\n\t\t\t\t\t\taria-label={`Anchor Price ${label}`}\n\t\t\t\t\t\tvariant=\"ui2\"\n\t\t\t\t\t\tclassName=\"text-black-200\"\n\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{label} <span className={cn('line-through', isRestricted && 'text-black-100')}>{amount}</span>\n\t\t\t\t\t</Typography>\n\t\t\t\t);\n\t\t\t})}\n\t\t\t{prices.savingsDescription ? (\n\t\t\t\t<Typography\n\t\t\t\t\taria-label=\"Savings Description\"\n\t\t\t\t\tvariant=\"ui2\"\n\t\t\t\t\tclassName={cn('text-black-200', prices.discountSavings && 'text-danger')}\n\t\t\t\t\ttag=\"span\"\n\t\t\t\t>\n\t\t\t\t\t{prices.savingsDescription}\n\t\t\t\t</Typography>\n\t\t\t) : null}\n\t\t</div>\n\t);\n};\n","import React, { Fragment } from 'react';\nimport { CommandSentence } from '@faithlife/command-sentence-control';\nimport { Checkbox, LinkButton, Typography } from '@faithlife/commerce-components';\nimport { useLocalization } from '../../../../localization';\nimport { ProductSubscriptionPromotion } from '../../../per-user-data/per-user-data-context';\n\ntype PeriodUnit = 'day' | 'month' | 'year';\n\nconst singularPeriodUnitResourceKey: Record<PeriodUnit, string> = {\n\tday: 'DayPeriodUnit',\n\tmonth: 'MonthPeriodUnit',\n\tyear: 'YearPeriodUnit',\n};\n\nconst pluralPeriodUnitResourceKey: Record<PeriodUnit, string> = {\n\tday: 'DaysPeriodUnit',\n\tmonth: 'MonthsPeriodUnit',\n\tyear: 'YearsPeriodUnit',\n};\n\nfunction getPeriodUnitText(periodLength: number, periodUnit: PeriodUnit, resources: Record<string, string>): string {\n\tconst resourceKey =\n\t\tperiodLength === 1 ? singularPeriodUnitResourceKey[periodUnit] : pluralPeriodUnitResourceKey[periodUnit];\n\treturn resources[resourceKey] ?? '';\n}\n\ninterface SubscriptionPromotionProps {\n\tpromotion: ProductSubscriptionPromotion;\n\tchecked: boolean;\n\tonChange: (checked: boolean) => void;\n\tdisabled?: boolean;\n}\n\nexport const SubscriptionPromotion = ({\n\tpromotion,\n\tchecked,\n\tonChange,\n\tdisabled = false,\n}: SubscriptionPromotionProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.SubscriptionPromotion');\n\n\tconst { freeTrialInfo, percentOff, logosOrVerbum, routes } = promotion;\n\n\tconst subscribableProductTitle = (\n\t\t<b>\n\t\t\t<CommandSentence Container=\"span\" template={resources.TitleFormat}>\n\t\t\t\t<CommandSentence.Field name=\"LOGOSORVERBUM\">{logosOrVerbum}</CommandSentence.Field>\n\t\t\t\t<CommandSentence.Field name=\"PROLEVEL\">{resources.ProLevel}</CommandSentence.Field>\n\t\t\t</CommandSentence>\n\t\t</b>\n\t);\n\n\tconst checkboxLabel = freeTrialInfo ? (\n\t\t<CommandSentence Container={Fragment} template={resources.AddFreeTrial}>\n\t\t\t<CommandSentence.Field name=\"PERIODUNITQUANTITY\">{freeTrialInfo.periodLength}</CommandSentence.Field>\n\t\t\t<CommandSentence.Field name=\"PERIODUNIT\">\n\t\t\t\t{getPeriodUnitText(freeTrialInfo.periodLength, freeTrialInfo.periodUnit, resources)}\n\t\t\t</CommandSentence.Field>\n\t\t</CommandSentence>\n\t) : (\n\t\tresources.SubscribeNow\n\t);\n\tconst savingsTemplate = freeTrialInfo ? resources.StartFreeTrialForSavings : resources.SubscribeForSavings;\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-3 rounded bg-primary-100 p-4\">\n\t\t\t<Typography variant=\"ui2\">\n\t\t\t\t<CommandSentence key={savingsTemplate} Container=\"span\" template={savingsTemplate}>\n\t\t\t\t\t<CommandSentence.Field name=\"SUBSCRIBABLEPRODUCTTITLE\">{subscribableProductTitle}</CommandSentence.Field>\n\t\t\t\t\t<CommandSentence.Field name=\"PERCENTAGESAVINGS\">{percentOff}</CommandSentence.Field>\n\t\t\t\t</CommandSentence>\n\t\t\t</Typography>\n\t\t\t<div className=\"flex flex-row flex-wrap justify-between gap-x-6 gap-y-2\">\n\t\t\t\t<Checkbox\n\t\t\t\t\tlabel={checkboxLabel}\n\t\t\t\t\tchecked={checked}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tonChange={() => onChange(!checked)}\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\ttypography=\"ui2\"\n\t\t\t\t/>\n\t\t\t\t{routes?.LearnMore && (\n\t\t\t\t\t<LinkButton as=\"button\" onClick={() => window.open(routes.LearnMore, '_blank')}>\n\t\t\t\t\t\t{resources.LearnMore}\n\t\t\t\t\t</LinkButton>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n\nexport default SubscriptionPromotion;\n","import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { AddToCartButton, Button, IdentifierTypes } from '@faithlife/commerce-components';\nimport CartClient from '../../../clients/cart-client';\nimport eventAggregator from '../../../cart/utility/eventaggregator';\nimport { useLocalization } from '../../../localization';\nimport { ProductPricingData, useSubscriptionPromotion } from '../../per-user-data/per-user-data-context';\nimport { SubscriptionPromotion } from './subscription-promotion';\n\ninterface PurchaseActionsProduct {\n\tid: string;\n\tresourceId?: string;\n\tisPrepubProduct?: boolean;\n\tisCollection: boolean;\n}\n\ninterface PurchaseActionsSelectedSku {\n\tid: string;\n\tisGroupLicenseEscrow?: boolean;\n\tisSubscription?: boolean;\n\tallowsMultipleQuantity?: boolean;\n}\n\ninterface PurchaseActionCartItem {\n\tidentifier: string;\n\ttype: (typeof IdentifierTypes)[keyof typeof IdentifierTypes];\n\tquantity: number;\n\tproductId?: string;\n}\n\ntype PurchaseActionProductPricingData = Pick<\n\tProductPricingData,\n\t'accessKind' | 'isOwned' | 'isGeographicallyRestricted' | 'openInLogosBaseUrl' | 'skus'\n>;\n\ninterface PurchaseActionStateInput {\n\tproduct: PurchaseActionsProduct;\n\tselectedSku: PurchaseActionsSelectedSku;\n\tpricingData?: PurchaseActionProductPricingData | null;\n}\n\ninterface PurchaseActionsProps extends PurchaseActionStateInput {\n\tshowGeoRestrictionMessage?: boolean;\n\tshowSubscriptionPromotion?: boolean;\n\tclassName?: string;\n\t/** Quantity to use for add-to-cart. Only propagated when the selected SKU supports multiple quantity. */\n\tquantity?: number;\n\taddToCartButtonRef?: React.Ref<HTMLDivElement>;\n}\n\ninterface QuantityUpdateButtonProps {\n\tcartItemId: number;\n\tcartUpdateUrl: string;\n\tquantity: number;\n\tclassName?: string;\n}\n\nconst QuantityUpdateButton = ({ cartItemId, cartUpdateUrl, quantity, className }: QuantityUpdateButtonProps) => {\n\tconst addToCartButtonResources = useLocalization('CommerceWeb.Resources.Shared.AddToMiniCartButton');\n\tconst errorResources = useLocalization('Logos.CommerceWeb.ShoppingCarts.Resources.ErrorMessages');\n\tconst [isUpdating, setIsUpdating] = useState(false);\n\tconst isUpdatingRef = useRef(false);\n\n\tconst handleUpdate = useCallback(async () => {\n\t\tif (isUpdatingRef.current) {\n\t\t\treturn;\n\t\t}\n\n\t\tisUpdatingRef.current = true;\n\t\tsetIsUpdating(true);\n\t\teventAggregator.trigger('cart:updating');\n\n\t\ttry {\n\t\t\tconst newCart = await CartClient.updateCartAsync(cartUpdateUrl, {\n\t\t\t\tquantityByCartItemId: {\n\t\t\t\t\t[cartItemId]: quantity,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tfor (const item of newCart.order?.analyticsTelemetry ?? []) {\n\t\t\t\t(window.dataLayer ??= []).push(item);\n\t\t\t}\n\n\t\t\teventAggregator.trigger('cart:updated', newCart);\n\t\t\tdocument.dispatchEvent(new CustomEvent('faithlife.sites.cart.updated', { detail: { cart: newCart } }));\n\t\t\tdocument.dispatchEvent(new CustomEvent('faithlife.sites.minicart.open'));\n\t\t} catch (error) {\n\t\t\tif (window.NotificationUtility) {\n\t\t\t\twindow.NotificationUtility.notify(errorResources.errorOccurredDuringCartUpdate, 'error');\n\t\t\t}\n\t\t\teventAggregator.trigger('cart:error');\n\t\t} finally {\n\t\t\tisUpdatingRef.current = false;\n\t\t\tsetIsUpdating(false);\n\t\t}\n\t}, [cartItemId, cartUpdateUrl, errorResources.errorOccurredDuringCartUpdate, quantity]);\n\n\treturn (\n\t\t<Button variant=\"primary\" scale=\"large\" onClick={handleUpdate} disabled={isUpdating} className={className}>\n\t\t\t{isUpdating ? addToCartButtonResources.updatingQuantity : addToCartButtonResources.updateQuantity}\n\t\t</Button>\n\t);\n};\n\nexport const getPurchaseActionState = ({ product, selectedSku, pricingData }: PurchaseActionStateInput) => {\n\tconst hasTemporaryAccess = pricingData?.accessKind === 'Temporary';\n\tconst hasPermanentAccess = pricingData?.accessKind === 'Permanent' || (pricingData?.isOwned && !hasTemporaryAccess);\n\tconst isRestricted = pricingData?.isGeographicallyRestricted ?? false;\n\tconst isSellable = pricingData?.skus?.[selectedSku.id]?.isSellable ?? true;\n\tconst isPurchasable = pricingData?.skus?.[selectedSku.id]?.isPurchasable ?? true;\n\tconst canShowAddToCart =\n\t\tisSellable && isPurchasable && !isRestricted && (selectedSku.isGroupLicenseEscrow || !hasPermanentAccess);\n\t// Server-decided eligibility (site settings + PreviewKind), mirroring Skeletor: shown regardless\n\t// of purchasability or restrictions.\n\tconst openInLogosUrl =\n\t\tpricingData?.openInLogosBaseUrl && product.resourceId && (hasTemporaryAccess || hasPermanentAccess)\n\t\t\t? `${pricingData.openInLogosBaseUrl}/${encodeURIComponent(product.resourceId)}`\n\t\t\t: null;\n\tconst canShowOpenInLogos = openInLogosUrl !== null;\n\n\treturn {\n\t\thasTemporaryAccess,\n\t\thasPermanentAccess,\n\t\tisRestricted,\n\t\tcanShowAddToCart,\n\t\tcanShowOpenInLogos,\n\t\topenInLogosUrl,\n\t\tshouldRenderButtons: canShowAddToCart || canShowOpenInLogos,\n\t};\n};\n\nexport const PurchaseActions = ({\n\tproduct,\n\tselectedSku,\n\tpricingData,\n\tshowGeoRestrictionMessage = false,\n\tshowSubscriptionPromotion = false,\n\tclassName,\n\tquantity,\n\taddToCartButtonRef,\n}: PurchaseActionsProps) => {\n\tconst openInLogosResources = useLocalization('CommerceWeb.Resources.Shared.OpenInLogos');\n\tconst addToCartButtonResources = useLocalization('CommerceWeb.Resources.Shared.AddToMiniCartButton');\n\tconst { canShowAddToCart, canShowOpenInLogos, openInLogosUrl, isRestricted } = getPurchaseActionState({\n\t\tproduct,\n\t\tselectedSku,\n\t\tpricingData,\n\t});\n\n\tconst { data: subscriptionPromotion } = useSubscriptionPromotion(\n\t\tshowSubscriptionPromotion && !selectedSku.isGroupLicenseEscrow ? selectedSku.id : undefined\n\t);\n\tconst [isSubscriptionPromotionChecked, setIsSubscriptionPromotionChecked] = useState(false);\n\tconst subscribableProductOptionId = subscriptionPromotion?.subscribableProductOptionId ?? null;\n\n\t// Reset the checkbox whenever the applicable promotion changes (e.g. the user selects a different SKU).\n\tuseEffect(() => {\n\t\tsetIsSubscriptionPromotionChecked(false);\n\t}, [subscribableProductOptionId]);\n\n\tconst shouldAddSubscriptionToCart =\n\t\tshowSubscriptionPromotion &&\n\t\tcanShowAddToCart &&\n\t\tisSubscriptionPromotionChecked &&\n\t\tBoolean(subscribableProductOptionId);\n\n\tconst supportsMultipleQuantity =\n\t\tselectedSku.isGroupLicenseEscrow || (!selectedSku.isSubscription && selectedSku.allowsMultipleQuantity);\n\tconst selectedSkuPricingData = pricingData?.skus?.[selectedSku.id];\n\tconst cartUpdateUrl = selectedSkuPricingData?.cartUpdateUrl;\n\tconst effectiveQuantity =\n\t\tsupportsMultipleQuantity && quantity !== null && quantity !== undefined && quantity > 1 ? quantity : 1;\n\tconst cartQuantityUpdate =\n\t\tsupportsMultipleQuantity &&\n\t\t!shouldAddSubscriptionToCart &&\n\t\tselectedSkuPricingData?.isInCart === true &&\n\t\ttypeof selectedSkuPricingData.cartItemId === 'number' &&\n\t\tselectedSkuPricingData.cartItemId > 0 &&\n\t\ttypeof cartUpdateUrl === 'string' &&\n\t\tcartUpdateUrl.length > 0\n\t\t\t? {\n\t\t\t\t\tcartItemId: selectedSkuPricingData.cartItemId,\n\t\t\t\t\tcartUpdateUrl,\n\t\t\t\t}\n\t\t\t: null;\n\tconst cartItems = useMemo(() => {\n\t\tconst items: PurchaseActionCartItem[] = [\n\t\t\t{ identifier: selectedSku.id, type: IdentifierTypes.SKU, quantity: effectiveQuantity, productId: product.id },\n\t\t];\n\n\t\tif (shouldAddSubscriptionToCart && subscribableProductOptionId) {\n\t\t\titems.push({ identifier: subscribableProductOptionId, type: IdentifierTypes.SPOID, quantity: 1 });\n\t\t}\n\n\t\treturn items;\n\t}, [product.id, selectedSku.id, shouldAddSubscriptionToCart, subscribableProductOptionId, effectiveQuantity]);\n\n\tif (isRestricted && !canShowOpenInLogos) {\n\t\treturn showGeoRestrictionMessage ? <div className={className}>{'Geo Restriction'}</div> : null;\n\t}\n\n\tif (!canShowAddToCart && !canShowOpenInLogos) {\n\t\treturn null;\n\t}\n\n\tconst showPromotion = showSubscriptionPromotion && canShowAddToCart && Boolean(subscriptionPromotion);\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-3\">\n\t\t\t{(canShowAddToCart || canShowOpenInLogos) && (\n\t\t\t\t<div ref={addToCartButtonRef} className={className}>\n\t\t\t\t\t{canShowAddToCart ? (\n\t\t\t\t\t\tcartQuantityUpdate ? (\n\t\t\t\t\t\t\t<QuantityUpdateButton\n\t\t\t\t\t\t\t\tcartItemId={cartQuantityUpdate.cartItemId}\n\t\t\t\t\t\t\t\tcartUpdateUrl={cartQuantityUpdate.cartUpdateUrl}\n\t\t\t\t\t\t\t\tquantity={cartItems[0].quantity}\n\t\t\t\t\t\t\t\tclassName=\"w-full md:w-auto\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<AddToCartButton\n\t\t\t\t\t\t\t\tkey={selectedSku.id}\n\t\t\t\t\t\t\t\tbuttonTextOverride={product.isPrepubProduct ? addToCartButtonResources.preorder : undefined}\n\t\t\t\t\t\t\t\titems={cartItems}\n\t\t\t\t\t\t\t\tscale=\"large\"\n\t\t\t\t\t\t\t\tclassName=\"w-full md:w-auto\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)\n\t\t\t\t\t) : null}\n\t\t\t\t\t{canShowOpenInLogos && openInLogosUrl ? (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tonClick={() => window.open(openInLogosUrl, '_blank')}\n\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\tscale=\"large\"\n\t\t\t\t\t\t\tclassName=\"w-full md:w-auto\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{openInLogosResources.OpenInLogosLinkText}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{showPromotion && subscriptionPromotion ? (\n\t\t\t\t<SubscriptionPromotion\n\t\t\t\t\tpromotion={subscriptionPromotion}\n\t\t\t\t\tchecked={isSubscriptionPromotionChecked}\n\t\t\t\t\tonChange={setIsSubscriptionPromotionChecked}\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t</div>\n\t);\n};\n","import React from 'react';\nimport { useLocalization } from '../../../localization';\nimport { cn } from '../../../util/cn';\nimport { Image } from '../../shared/enhanced-image-tag/image';\n\ninterface GalleryProps {\n\timageUri: string | null | undefined;\n\tproductName: string;\n}\n\nexport const Gallery = ({ imageUri, productName }: GalleryProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Details');\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'border border-grey p-6 mx-auto xmd:max-w-[343px] md:ml-0 md:mr-auto lg:mx-0 lg:max-w-full lg:px-4 lg:py-12',\n\t\t\t\t!imageUri && '!p-0'\n\t\t\t)}\n\t\t>\n\t\t\t{/* Fixed square dimensions per breakpoint keep the rendered image width constant within each\n\t\t\t    `sizes` band, so every viewport in a band selects the same srcset candidate. */}\n\t\t\t<figure className=\"relative mx-auto aspect-square max-h-[268px] w-full lg:h-[400px] lg:max-h-none lg:w-[400px] xlg:h-[504px] xlg:w-[504px]\">\n\t\t\t\t{imageUri ? (\n\t\t\t\t\t<Image\n\t\t\t\t\t\tsrc={imageUri}\n\t\t\t\t\t\talt={productName ?? ''}\n\t\t\t\t\t\tclassName=\"absolute inset-0 h-full w-full object-scale-down object-center\"\n\t\t\t\t\t\tfetchPriority=\"high\"\n\t\t\t\t\t\ttargetAspectRatio={[1, 1]}\n\t\t\t\t\t\tsizes={{\n\t\t\t\t\t\t\tmobile: 268,\n\t\t\t\t\t\t\tdesktop: 400,\n\t\t\t\t\t\t\tlargeDesktop: 504,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<div className=\"absolute inset-0 flex items-center justify-center bg-gray-200\">\n\t\t\t\t\t\t<div className=\"text-base font-semibold text-gray-500\">{resources.ComingSoon}</div>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</figure>\n\t\t</div>\n\t);\n};\n","import { SubscriptionInfo } from '../../per-user-data/per-user-data-context';\n\nexport type PurchaseOptionType = 'payInFull' | 'subscription';\n\nexport interface PurchaseOption {\n\ttype: PurchaseOptionType;\n\ttitle: string;\n}\n\nexport type FormatGroup = 'logosEdition' | 'ebook' | 'other';\n\nexport const ResourceFormats = {\n\tEbook: 'ebook',\n\tReaderEdition: 'reader-edition',\n\tResearchEdition: 'research-edition',\n\tLogosEditionCollection: 'logos-edition-collection',\n} as const;\n\ninterface Chip {\n\tname: string;\n\turl: string | null | undefined;\n}\n\ninterface RatingSummary {\n\taverageRating: number | null | undefined;\n\tnumberOfReviews: number;\n}\n\nexport interface StaticProduct {\n\tid: string;\n\tresourceId: string;\n\tname: string;\n\tisCollection: boolean;\n\tsourceToken: string;\n\timageUri?: string | null;\n\tsamplePageImageUrls?: readonly string[] | null;\n\tauthors?: readonly Chip[] | null;\n\tpublishers?: readonly Chip[] | null;\n\tisbn?: string | null;\n\tpublicationPeriod?: string | null;\n\tdescriptionHtml?: string | null;\n\tratingSummary?: RatingSummary | null;\n\tisPrepubProduct: boolean;\n\tallowsSeeInside: boolean;\n}\n\nexport interface SkuPriceAmount {\n\tamount: number;\n\tdisplayAmount: string;\n\tdisplayAmountCurrencyCode?: string | null;\n\tlocalizedDisplayAmount?: string | null;\n\tcurrencyCode: string;\n\tdisplayAmountByCurrency?: Record<string, string> | null;\n}\n\nexport interface SkuPriceBreakdownLine {\n\tlabel: string;\n\tisDeduction: boolean;\n\tdisplayInUsd: boolean;\n\thref?: string | null;\n\tamount: SkuPriceAmount;\n}\n\nexport interface SkuPriceDiscount {\n\tdescription: string;\n\tshouldStack: boolean;\n}\n\ninterface SkuPrices {\n\tsalePrice?: SkuPriceAmount | null;\n\tanchorPrice?: SkuPriceAmount | null;\n\tanchorSavings?: SkuPriceAmount | null;\n\tdiscountSavings?: SkuPriceAmount | null;\n\tdiscounts?: SkuPriceDiscount[] | null;\n\tbreakdownTriggerLabel?: string | null;\n\tbreakdownLines?: SkuPriceBreakdownLine[] | null;\n\tanchorPriceLines?:\n\t\t| { label: string; displayAmount?: string | null; displayAmountByCurrency?: Record<string, string> | null }[]\n\t\t| null;\n\tsavingsDescription?: string | null;\n}\n\nexport interface StaticSku {\n\tid: string;\n\tformatDisplayName: string;\n\tsubscriptionInfo?: SubscriptionInfo | null;\n\tisSubscription: boolean;\n\tprice: SkuPrices;\n\tisSellable: boolean;\n\tisGroupLicenseEscrow: boolean;\n\tallowsMultipleQuantity: boolean;\n\tformatGroup: FormatGroup;\n\tresourceFormat?: string | null;\n}\n\nexport interface User {\n\tuserId?: number;\n\tdisplayName?: string | null;\n}\n","import React, { useState } from 'react';\nimport { ChevronDown, X } from 'lucide-react';\nimport { cn } from '../../../../util/cn';\n\ninterface CollapsibleCalloutProps {\n\tvariant?: 'default' | 'logos-edition';\n\tcollapsedContent: React.ReactNode;\n\texpandText: string;\n\tcollapseText: string;\n\tchildren: React.ReactNode;\n}\n\nexport const CollapsibleCallout = ({\n\tvariant = 'default',\n\tcollapsedContent,\n\texpandText,\n\tcollapseText,\n\tchildren,\n}: CollapsibleCalloutProps) => {\n\tconst [isExpanded, setIsExpanded] = useState(false);\n\n\tconst panelClass = cn('rounded-[6px] text-sm', variant === 'logos-edition' ? 'bg-primary-100' : 'bg-grey-200');\n\treturn (\n\t\t<div className={panelClass}>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'flex flex-col items-center justify-between gap-sp8 px-sp12 py-sp8 xs:p-sp16 xs:text-center sm:flex-row sm:text-left',\n\t\t\t\t\tisExpanded && 'flex-row justify-end'\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{!isExpanded && <span>{collapsedContent}</span>}\n\t\t\t\t<button\n\t\t\t\t\taria-expanded={isExpanded}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'flex shrink-0 items-center gap-sp4 font-bold cursor-pointer',\n\t\t\t\t\t\tvariant === 'logos-edition' ? 'text-primary hover:text-primary-400' : 'text-current hover:text-primary'\n\t\t\t\t\t)}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={() => setIsExpanded(prev => !prev)}\n\t\t\t\t>\n\t\t\t\t\t{isExpanded ? collapseText : expandText}\n\t\t\t\t\t{isExpanded ? <X className=\"h-3 w-3\" /> : <ChevronDown className=\"h-3 w-3\" />}\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t{isExpanded && <div className=\"sm:px-sp90 sm:pb-sp32 p-sp16\">{children}</div>}\n\t\t</div>\n\t);\n};\n","import React from 'react';\nimport { Modal, UtilityButton } from '@faithlife/styled-ui';\nimport { EmbeddedVideo } from '@faithlife/commerce-components';\nimport { X } from 'lucide-react';\n\ninterface VideoPopoverProps {\n\tvideoUrl: string;\n\tisModalOpen: boolean;\n\tonClose: () => void;\n}\n\nexport const VideoPopover = ({ videoUrl, isModalOpen, onClose }: VideoPopoverProps) => (\n\t<Modal isOpen={isModalOpen} onClose={onClose} container=\"body\" width=\"1280px\" background=\"transparent\">\n\t\t<Modal.Header\n\t\t\tpadding={0}\n\t\t\tactions={\n\t\t\t\t<UtilityButton onClick={onClose}>\n\t\t\t\t\t<X color=\"white\" />\n\t\t\t\t</UtilityButton>\n\t\t\t}\n\t\t/>\n\t\t<EmbeddedVideo className=\"border-0 bg-[#1f1f1f]\" videoUrl={videoUrl} />\n\t</Modal>\n);\n","import React, { Fragment, useState } from 'react';\nimport { CommandSentence } from '@faithlife/command-sentence-control';\nimport { PlayIcon, Typography } from '@faithlife/commerce-components';\nimport { useLocalization } from '../../../../localization';\nimport { cn } from '../../../../util/cn';\nimport { ResourceFormats } from '../types';\nimport { CollapsibleCallout } from './collapsible-callout';\nimport { VideoPopover } from './video-popover';\n\nconst resourceGroupKey = 'CommerceWeb.Resources.Product.ResourceFormatCallout';\n\nconst calloutResourceFormats: readonly string[] = [\n\tResourceFormats.Ebook,\n\tResourceFormats.ReaderEdition,\n\tResourceFormats.ResearchEdition,\n\tResourceFormats.LogosEditionCollection,\n];\n\nexport const hasResourceFormatCallout = (resourceFormat?: string | null): boolean =>\n\t!!resourceFormat && calloutResourceFormats.includes(resourceFormat);\n\ninterface LogosEditionCalloutProps {\n\tresourceFormat?: string | null;\n\tlogosOrVerbum: string;\n\tlogosEditionLearnMoreVideoUrl?: string | null;\n}\n\ninterface EditionFlags {\n\tisEbook: boolean;\n\tisVerbum: boolean;\n\tisReaderEdition: boolean;\n\tisLogosEditionCollection: boolean;\n}\n\nconst CalloutSummary = ({ isEbook, isVerbum }: Pick<EditionFlags, 'isEbook' | 'isVerbum'>) => {\n\tconst resources = useLocalization(resourceGroupKey);\n\n\treturn isEbook ? (\n\t\t<CommandSentence template={resources.EbooksCalloutSummary} Container={Fragment}>\n\t\t\t<CommandSentence.Field name=\"EBOOKS\">\n\t\t\t\t<strong>{resources.Ebooks}</strong>\n\t\t\t</CommandSentence.Field>\n\t\t</CommandSentence>\n\t) : (\n\t\t<CommandSentence template={resources.LogosEditionsCalloutSummary} Container={Fragment}>\n\t\t\t<CommandSentence.Field name=\"LOGOSEDITIONS\">\n\t\t\t\t<strong>{isVerbum ? resources.VerbumEditions : resources.LogosEditions}</strong>\n\t\t\t</CommandSentence.Field>\n\t\t</CommandSentence>\n\t);\n};\n\nconst EditionBadge = ({\n\tisEbook,\n\tisVerbum,\n\tisReaderEdition,\n}: Pick<EditionFlags, 'isEbook' | 'isVerbum' | 'isReaderEdition'>) => {\n\tconst resources = useLocalization(resourceGroupKey);\n\n\treturn (\n\t\t<span\n\t\t\tclassName={cn('rounded-[3px] px-sp12 py-sp4', isEbook ? 'bg-grey-400 font-bold' : 'bg-primary-200 font-normal')}\n\t\t>\n\t\t\t{isEbook ? (\n\t\t\t\tresources.Ebook\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<span className=\"font-bold\">\n\t\t\t\t\t\t<span>{isVerbum ? resources.VerbumEdition : resources.LogosEdition}</span>\n\t\t\t\t\t\t{':'}\n\t\t\t\t\t</span>{' '}\n\t\t\t\t\t<span>{isReaderEdition ? resources.ReaderEdition : resources.ResearchEdition}</span>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</span>\n\t);\n};\n\nconst CalloutHeader = ({\n\tisEbook,\n\tisVerbum,\n\tisReaderEdition,\n\tisLogosEditionCollection,\n\tlogosOrVerbum,\n}: EditionFlags & { logosOrVerbum: string }) => {\n\tconst resources = useLocalization(resourceGroupKey);\n\n\treturn (\n\t\t<div className=\"mb-sp20 flex flex-row flex-wrap items-center gap-x-sp12 gap-y-sp8 xs:flex-col xs:items-start xs:gap-sp8\">\n\t\t\t{isLogosEditionCollection ? (\n\t\t\t\t<Typography tag=\"span\" variant=\"headingH5\">\n\t\t\t\t\t<CommandSentence template={resources.ThisCollectionContainsLogosEditions} Container={Fragment}>\n\t\t\t\t\t\t<CommandSentence.Field name=\"LOGOSORVERBUM\">{logosOrVerbum}</CommandSentence.Field>\n\t\t\t\t\t</CommandSentence>\n\t\t\t\t</Typography>\n\t\t\t) : (\n\t\t\t\t<div className=\"flex gap-x-sp12 gap-y-sp8 align-items-baseline\">\n\t\t\t\t\t<Typography tag=\"span\" variant=\"headingH5\">\n\t\t\t\t\t\t{resources.ThisResource}\n\t\t\t\t\t\t{':'}\n\t\t\t\t\t</Typography>\n\t\t\t\t\t<EditionBadge isEbook={isEbook} isVerbum={isVerbum} isReaderEdition={isReaderEdition} />\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n\nconst TwoTypesOfLogosEditionsHeading = ({ logosOrVerbum }: { logosOrVerbum: string }) => {\n\tconst resources = useLocalization(resourceGroupKey);\n\n\treturn (\n\t\t<Typography tag=\"div\" variant=\"headingH5\">\n\t\t\t<CommandSentence template={resources.TwoTypesOfLogosEditions} Container={Fragment}>\n\t\t\t\t<CommandSentence.Field name=\"LOGOSORVERBUM\">{logosOrVerbum}</CommandSentence.Field>\n\t\t\t</CommandSentence>\n\t\t</Typography>\n\t);\n};\n\nconst CalloutBody = ({\n\tisEbook,\n\tisVerbum,\n\tlogosOrVerbum,\n}: Pick<EditionFlags, 'isEbook' | 'isVerbum'> & { logosOrVerbum: string }) => {\n\tconst resources = useLocalization(resourceGroupKey);\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-sp20\">\n\t\t\t{isEbook ? (\n\t\t\t\t<CommandSentence template={resources.EbooksCallout} Container={Fragment}>\n\t\t\t\t\t<CommandSentence.Field name=\"LOGOSORVERBUM\">{logosOrVerbum}</CommandSentence.Field>\n\t\t\t\t</CommandSentence>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<CommandSentence template={resources.LogosEditionsCallout}>\n\t\t\t\t\t\t<CommandSentence.Field name=\"LOGOSORVERBUM\">{logosOrVerbum}</CommandSentence.Field>\n\t\t\t\t\t\t<CommandSentence.Field name=\"LOGOSEDITIONS\">\n\t\t\t\t\t\t\t<strong>{isVerbum ? resources.VerbumEditions : resources.LogosEditions}</strong>\n\t\t\t\t\t\t</CommandSentence.Field>\n\t\t\t\t\t</CommandSentence>\n\t\t\t\t\t<div className=\"order-first md:order-none\">\n\t\t\t\t\t\t<TwoTypesOfLogosEditionsHeading logosOrVerbum={logosOrVerbum} />\n\t\t\t\t\t</div>\n\t\t\t\t\t<CommandSentence template={resources.ResearchEditionsCallout}>\n\t\t\t\t\t\t<CommandSentence.Field name=\"LOGOSORVERBUM\">{logosOrVerbum}</CommandSentence.Field>\n\t\t\t\t\t\t<CommandSentence.Field name=\"RESEARCHEDITIONS\">\n\t\t\t\t\t\t\t<strong>{resources.ResearchEditions}</strong>\n\t\t\t\t\t\t</CommandSentence.Field>\n\t\t\t\t\t</CommandSentence>\n\t\t\t\t\t<CommandSentence template={resources.ReaderEditionsCallout}>\n\t\t\t\t\t\t<CommandSentence.Field name=\"LOGOSORVERBUM\">{logosOrVerbum}</CommandSentence.Field>\n\t\t\t\t\t\t<CommandSentence.Field name=\"READEREDITIONS\">\n\t\t\t\t\t\t\t<strong>{resources.ReaderEditions}</strong>\n\t\t\t\t\t\t</CommandSentence.Field>\n\t\t\t\t\t</CommandSentence>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n\nconst LearnMoreVideoButton = ({ videoUrl }: { videoUrl: string }) => {\n\tconst resources = useLocalization(resourceGroupKey);\n\tconst [isVideoShown, setIsVideoShown] = useState(false);\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\"mt-sp16\">\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"inline-flex flex-row items-center gap-sp8 border-none bg-transparent p-sp0 font-semibold text-primary cursor-pointer hover:text-primary-400\"\n\t\t\t\t\tonClick={() => setIsVideoShown(true)}\n\t\t\t\t>\n\t\t\t\t\t<PlayIcon size={16} />\n\t\t\t\t\t{resources.LearnMore}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<VideoPopover isModalOpen={isVideoShown} videoUrl={videoUrl} onClose={() => setIsVideoShown(false)} />\n\t\t</>\n\t);\n};\n\nexport const LogosEditionCallout = ({\n\tresourceFormat,\n\tlogosOrVerbum,\n\tlogosEditionLearnMoreVideoUrl,\n}: LogosEditionCalloutProps) => {\n\tconst resources = useLocalization(resourceGroupKey);\n\n\tconst isEbook = resourceFormat === ResourceFormats.Ebook;\n\tconst isReaderEdition = resourceFormat === ResourceFormats.ReaderEdition;\n\tconst isResearchEdition = resourceFormat === ResourceFormats.ResearchEdition;\n\tconst isLogosEditionCollection = resourceFormat === ResourceFormats.LogosEditionCollection;\n\tconst isLogosEdition = isReaderEdition || isResearchEdition || isLogosEditionCollection;\n\n\tif (!hasResourceFormatCallout(resourceFormat)) {\n\t\treturn null;\n\t}\n\n\tconst isVerbum = logosOrVerbum.toLowerCase() === 'verbum';\n\n\treturn (\n\t\t<CollapsibleCallout\n\t\t\tcollapseText={resources.Close}\n\t\t\tcollapsedContent={<CalloutSummary isEbook={isEbook} isVerbum={isVerbum} />}\n\t\t\texpandText={resources.LearnMore}\n\t\t\tvariant={isEbook ? 'default' : 'logos-edition'}\n\t\t>\n\t\t\t<CalloutHeader\n\t\t\t\tisEbook={isEbook}\n\t\t\t\tisVerbum={isVerbum}\n\t\t\t\tisReaderEdition={isReaderEdition}\n\t\t\t\tisLogosEditionCollection={isLogosEditionCollection}\n\t\t\t\tlogosOrVerbum={logosOrVerbum}\n\t\t\t/>\n\t\t\t<CalloutBody isEbook={isEbook} isVerbum={isVerbum} logosOrVerbum={logosOrVerbum} />\n\t\t\t{isLogosEdition && logosEditionLearnMoreVideoUrl && (\n\t\t\t\t<LearnMoreVideoButton videoUrl={logosEditionLearnMoreVideoUrl} />\n\t\t\t)}\n\t\t</CollapsibleCallout>\n\t);\n};\n","\"use client\";\nvar __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, \"name\", { value, configurable: true });\n\n// src/dialog.tsx\nimport * as React from \"react\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { createContextScope } from \"@radix-ui/react-context\";\nimport { useId } from \"@radix-ui/react-id\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { DismissableLayer, useDismissableLayerSurface } from \"@radix-ui/react-dismissable-layer\";\nimport { FocusScope } from \"@radix-ui/react-focus-scope\";\nimport { Portal as PortalPrimitive } from \"@radix-ui/react-portal\";\nimport { Presence } from \"@radix-ui/react-presence\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { useFocusGuards } from \"@radix-ui/react-focus-guards\";\nimport { useLayoutEffect } from \"@radix-ui/react-use-layout-effect\";\nimport { RemoveScroll } from \"react-remove-scroll\";\nimport { hideOthers } from \"aria-hidden\";\nimport { createSlot } from \"@radix-ui/react-slot\";\nimport { Fragment, jsx } from \"react/jsx-runtime\";\nvar DIALOG_NAME = \"Dialog\";\nvar [createDialogContext, createDialogScope] = createContextScope(DIALOG_NAME);\nvar [DialogProvider, useDialogContext] = createDialogContext(DIALOG_NAME);\nvar Dialog = /* @__PURE__ */ __name((props) => {\n  const {\n    __scopeDialog,\n    children,\n    open: openProp,\n    defaultOpen,\n    onOpenChange,\n    modal = true\n  } = props;\n  const triggerRef = React.useRef(null);\n  const contentRef = React.useRef(null);\n  const [open, setOpen] = useControllableState({\n    prop: openProp,\n    defaultProp: defaultOpen ?? false,\n    onChange: onOpenChange,\n    caller: DIALOG_NAME\n  });\n  const [titleCount, setTitleCount] = React.useState(0);\n  const [descriptionCount, setDescriptionCount] = React.useState(0);\n  return /* @__PURE__ */ jsx(\n    DialogProvider,\n    {\n      scope: __scopeDialog,\n      triggerRef,\n      contentRef,\n      contentId: useId(),\n      titleId: useId(),\n      descriptionId: useId(),\n      titlePresent: titleCount > 0,\n      descriptionPresent: descriptionCount > 0,\n      setTitleCount,\n      setDescriptionCount,\n      open,\n      onOpenChange: setOpen,\n      onOpenToggle: React.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen]),\n      modal,\n      children\n    }\n  );\n}, \"Dialog\");\nvar TRIGGER_NAME = \"DialogTrigger\";\nvar DialogTrigger = /* @__PURE__ */ React.forwardRef(\n  /* @__PURE__ */ __name(function DialogTrigger2(props, forwardedRef) {\n    const { __scopeDialog, ...triggerProps } = props;\n    const context = useDialogContext(TRIGGER_NAME, __scopeDialog);\n    const composedTriggerRef = useComposedRefs(forwardedRef, context.triggerRef);\n    return /* @__PURE__ */ jsx(\n      Primitive.button,\n      {\n        type: \"button\",\n        \"aria-haspopup\": \"dialog\",\n        \"aria-expanded\": context.open,\n        \"aria-controls\": context.open ? context.contentId : void 0,\n        \"data-state\": getState(context.open),\n        ...triggerProps,\n        ref: composedTriggerRef,\n        onClick: composeEventHandlers(props.onClick, context.onOpenToggle)\n      }\n    );\n  }, \"DialogTrigger\")\n);\nvar PORTAL_NAME = \"DialogPortal\";\nvar [PortalProvider, usePortalContext] = createDialogContext(PORTAL_NAME, {\n  forceMount: void 0\n});\nvar DialogPortal = /* @__PURE__ */ __name((props) => {\n  const { __scopeDialog, forceMount, children, container } = props;\n  const context = useDialogContext(PORTAL_NAME, __scopeDialog);\n  return /* @__PURE__ */ jsx(PortalProvider, { scope: __scopeDialog, forceMount, children: React.Children.map(children, (child) => /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(PortalPrimitive, { asChild: true, container, children: child }) })) });\n}, \"DialogPortal\");\nvar OVERLAY_NAME = \"DialogOverlay\";\nvar DialogOverlay = /* @__PURE__ */ React.forwardRef(\n  /* @__PURE__ */ __name(function DialogOverlay2(props, forwardedRef) {\n    const portalContext = usePortalContext(OVERLAY_NAME, props.__scopeDialog);\n    const { forceMount = portalContext.forceMount, ...overlayProps } = props;\n    const context = useDialogContext(OVERLAY_NAME, props.__scopeDialog);\n    return context.modal ? /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(DialogOverlayImpl, { ...overlayProps, ref: forwardedRef }) }) : null;\n  }, \"DialogOverlay\")\n);\nvar Slot = createSlot(\"DialogOverlay.RemoveScroll\");\nvar DialogOverlayImpl = /* @__PURE__ */ React.forwardRef(\n  // blank line to reduce diff noise\n  /* @__PURE__ */ __name(function DialogOverlayImpl2(props, forwardedRef) {\n    const { __scopeDialog, ...overlayProps } = props;\n    const context = useDialogContext(OVERLAY_NAME, __scopeDialog);\n    const registerDismissableSurface = useDismissableLayerSurface();\n    const composedRefs = useComposedRefs(forwardedRef, registerDismissableSurface);\n    return (\n      // Make sure `Content` is scrollable even when it doesn't live inside `RemoveScroll`\n      // ie. when `Overlay` and `Content` are siblings\n      /* @__PURE__ */ jsx(RemoveScroll, { as: Slot, allowPinchZoom: true, shards: [context.contentRef], children: /* @__PURE__ */ jsx(\n        Primitive.div,\n        {\n          \"data-state\": getState(context.open),\n          ...overlayProps,\n          ref: composedRefs,\n          style: { pointerEvents: \"auto\", ...overlayProps.style }\n        }\n      ) })\n    );\n  }, \"DialogOverlayImpl\")\n);\nvar CONTENT_NAME = \"DialogContent\";\nvar DialogContent = /* @__PURE__ */ React.forwardRef(\n  /* @__PURE__ */ __name(function DialogContent2(props, forwardedRef) {\n    const portalContext = usePortalContext(CONTENT_NAME, props.__scopeDialog);\n    const { forceMount = portalContext.forceMount, ...contentProps } = props;\n    const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);\n    return /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: context.modal ? /* @__PURE__ */ jsx(DialogContentModal, { ...contentProps, ref: forwardedRef }) : /* @__PURE__ */ jsx(DialogContentNonModal, { ...contentProps, ref: forwardedRef }) });\n  }, \"DialogContent\")\n);\nvar DialogContentModal = /* @__PURE__ */ React.forwardRef(\n  // blank line to reduce diff noise\n  /* @__PURE__ */ __name(function DialogContentModal2(props, forwardedRef) {\n    const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);\n    const contentRef = React.useRef(null);\n    const composedRefs = useComposedRefs(forwardedRef, context.contentRef, contentRef);\n    React.useEffect(() => {\n      const content = contentRef.current;\n      if (content) return hideOthers(content);\n    }, []);\n    return /* @__PURE__ */ jsx(\n      DialogContentImpl,\n      {\n        ...props,\n        ref: composedRefs,\n        trapFocus: context.open,\n        disableOutsidePointerEvents: context.open,\n        onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, (event) => {\n          event.preventDefault();\n          context.triggerRef.current?.focus();\n        }),\n        onPointerDownOutside: composeEventHandlers(props.onPointerDownOutside, (event) => {\n          const originalEvent = event.detail.originalEvent;\n          const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true;\n          const isRightClick = originalEvent.button === 2 || ctrlLeftClick;\n          if (isRightClick) event.preventDefault();\n        }),\n        onFocusOutside: composeEventHandlers(\n          props.onFocusOutside,\n          (event) => event.preventDefault()\n        )\n      }\n    );\n  }, \"DialogContentModal\")\n);\nvar DialogContentNonModal = /* @__PURE__ */ React.forwardRef(\n  // blank line to reduce diff noise\n  /* @__PURE__ */ __name(function DialogContentNonModal2(props, forwardedRef) {\n    const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);\n    const hasInteractedOutsideRef = React.useRef(false);\n    const hasPointerDownOutsideRef = React.useRef(false);\n    return /* @__PURE__ */ jsx(\n      DialogContentImpl,\n      {\n        ...props,\n        ref: forwardedRef,\n        trapFocus: false,\n        disableOutsidePointerEvents: false,\n        onCloseAutoFocus: (event) => {\n          props.onCloseAutoFocus?.(event);\n          if (!event.defaultPrevented) {\n            if (!hasInteractedOutsideRef.current) context.triggerRef.current?.focus();\n            event.preventDefault();\n          }\n          hasInteractedOutsideRef.current = false;\n          hasPointerDownOutsideRef.current = false;\n        },\n        onInteractOutside: (event) => {\n          props.onInteractOutside?.(event);\n          if (!event.defaultPrevented) {\n            hasInteractedOutsideRef.current = true;\n            if (event.detail.originalEvent.type === \"pointerdown\") {\n              hasPointerDownOutsideRef.current = true;\n            }\n          }\n          const target = event.target;\n          const targetIsTrigger = context.triggerRef.current?.contains(target);\n          if (targetIsTrigger) event.preventDefault();\n          if (event.detail.originalEvent.type === \"focusin\" && hasPointerDownOutsideRef.current) {\n            event.preventDefault();\n          }\n        }\n      }\n    );\n  }, \"DialogContentNonModal\")\n);\nvar DialogContentImpl = /* @__PURE__ */ React.forwardRef(\n  // blank line to reduce diff noise\n  /* @__PURE__ */ __name(function DialogContentImpl2(props, forwardedRef) {\n    const { __scopeDialog, trapFocus, onOpenAutoFocus, onCloseAutoFocus, ...contentProps } = props;\n    const context = useDialogContext(CONTENT_NAME, __scopeDialog);\n    useFocusGuards();\n    return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(\n      FocusScope,\n      {\n        asChild: true,\n        loop: true,\n        trapped: trapFocus,\n        onMountAutoFocus: onOpenAutoFocus,\n        onUnmountAutoFocus: onCloseAutoFocus,\n        children: /* @__PURE__ */ jsx(\n          DismissableLayer,\n          {\n            role: \"dialog\",\n            id: context.contentId,\n            \"aria-describedby\": context.descriptionPresent ? context.descriptionId : void 0,\n            \"aria-labelledby\": context.titlePresent ? context.titleId : void 0,\n            \"data-state\": getState(context.open),\n            ...contentProps,\n            ref: forwardedRef,\n            deferPointerDownOutside: true,\n            onDismiss: () => context.onOpenChange(false)\n          }\n        )\n      }\n    ) });\n  }, \"DialogContentImpl\")\n);\nvar TITLE_NAME = \"DialogTitle\";\nvar DialogTitle = /* @__PURE__ */ React.forwardRef(\n  /* @__PURE__ */ __name(function DialogTitle2(props, forwardedRef) {\n    const { __scopeDialog, ...titleProps } = props;\n    const context = useDialogContext(TITLE_NAME, __scopeDialog);\n    const { setTitleCount } = context;\n    useLayoutEffect(() => {\n      setTitleCount((count) => count + 1);\n      return () => setTitleCount((count) => count - 1);\n    }, [setTitleCount]);\n    return /* @__PURE__ */ jsx(Primitive.h2, { id: context.titleId, ...titleProps, ref: forwardedRef });\n  }, \"DialogTitle\")\n);\nvar DESCRIPTION_NAME = \"DialogDescription\";\nvar DialogDescription = /* @__PURE__ */ React.forwardRef(\n  // blank line to reduce diff noise\n  /* @__PURE__ */ __name(function DialogDescription2(props, forwardedRef) {\n    const { __scopeDialog, ...descriptionProps } = props;\n    const context = useDialogContext(DESCRIPTION_NAME, __scopeDialog);\n    const { setDescriptionCount } = context;\n    useLayoutEffect(() => {\n      setDescriptionCount((count) => count + 1);\n      return () => setDescriptionCount((count) => count - 1);\n    }, [setDescriptionCount]);\n    return /* @__PURE__ */ jsx(Primitive.p, { id: context.descriptionId, ...descriptionProps, ref: forwardedRef });\n  }, \"DialogDescription\")\n);\nvar CLOSE_NAME = \"DialogClose\";\nvar DialogClose = /* @__PURE__ */ React.forwardRef(\n  /* @__PURE__ */ __name(function DialogClose2(props, forwardedRef) {\n    const { __scopeDialog, ...closeProps } = props;\n    const context = useDialogContext(CLOSE_NAME, __scopeDialog);\n    return /* @__PURE__ */ jsx(\n      Primitive.button,\n      {\n        type: \"button\",\n        ...closeProps,\n        ref: forwardedRef,\n        onClick: composeEventHandlers(props.onClick, () => context.onOpenChange(false))\n      }\n    );\n  }, \"DialogClose\")\n);\nvar WarningProvider = /* @__PURE__ */ __name((props) => {\n  return props.children;\n}, \"WarningProvider\");\nfunction getState(open) {\n  return open ? \"open\" : \"closed\";\n}\n__name(getState, \"getState\");\nexport {\n  DialogClose as Close,\n  DialogContent as Content,\n  DialogDescription as Description,\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogOverlay,\n  DialogPortal,\n  DialogTitle,\n  DialogTrigger,\n  DialogOverlay as Overlay,\n  DialogPortal as Portal,\n  Dialog as Root,\n  DialogTitle as Title,\n  DialogTrigger as Trigger,\n  WarningProvider,\n  createDialogScope\n};\n//# sourceMappingURL=index.mjs.map\n","import React from 'react';\nimport * as DialogPrimitive from '@radix-ui/react-dialog';\nimport { VisuallyHidden } from '@radix-ui/react-visually-hidden';\nimport { Button } from '@faithlife/commerce-components';\nimport { X } from 'lucide-react';\nimport { useLocalization } from '../../../localization';\n\ninterface SeeInsideProps {\n\tseeInsideIframeUrl: string | null | undefined;\n}\n\nexport const SeeInside = ({ seeInsideIframeUrl }: SeeInsideProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Details');\n\n\tif (!seeInsideIframeUrl) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<DialogPrimitive.Root>\n\t\t\t<DialogPrimitive.Trigger asChild>\n\t\t\t\t<Button variant=\"secondary\" scale=\"medium\" className=\"mx-auto mt-sp24 block py-sp12!\">\n\t\t\t\t\t{resources.SeeInside}\n\t\t\t\t</Button>\n\t\t\t</DialogPrimitive.Trigger>\n\t\t\t<DialogPrimitive.Portal>\n\t\t\t\t<DialogPrimitive.Overlay className=\"fixed inset-0 z-[50] h-screen w-screen bg-gray-600/40\" />\n\t\t\t\t<VisuallyHidden>\n\t\t\t\t\t<DialogPrimitive.Title>{resources.SeeInside}</DialogPrimitive.Title>\n\t\t\t\t</VisuallyHidden>\n\t\t\t\t<DialogPrimitive.Content\n\t\t\t\t\taria-describedby={undefined}\n\t\t\t\t\tclassName=\"fixed left-1/2 top-1/2 z-[100] max-h-screen w-screen max-w-[80vh] -translate-x-1/2 -translate-y-1/2 transform rounded-sm bg-white p-4 pt-0 md:w-[800px]\"\n\t\t\t\t>\n\t\t\t\t\t<div className=\"text-right\">\n\t\t\t\t\t\t<DialogPrimitive.Close asChild>\n\t\t\t\t\t\t\t<button aria-label={resources.Close} className=\"m-5 mr-0 inline-block\" type=\"button\">\n\t\t\t\t\t\t\t\t<X />\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</DialogPrimitive.Close>\n\t\t\t\t\t</div>\n\t\t\t\t\t<iframe className=\"h-[80vh] w-full\" src={seeInsideIframeUrl} title={resources.SeeInside} />\n\t\t\t\t</DialogPrimitive.Content>\n\t\t\t</DialogPrimitive.Portal>\n\t\t</DialogPrimitive.Root>\n\t);\n};\n","import React, { Fragment } from 'react';\nimport { CommandSentence } from '@faithlife/command-sentence-control';\nimport { Typography } from '@faithlife/commerce-components';\nimport { useLocalization } from '../../../../localization';\n\ninterface PreorderedProductLabelProps {\n\torderDate: string;\n\troutes: {\n\t\tPreorderManagementPage: string;\n\t};\n}\n\nexport const PreorderedProductLabel = ({ orderDate, routes }: PreorderedProductLabelProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.DisplayTemplates.PricingSidebarViewModel');\n\n\treturn (\n\t\t<Typography tag=\"div\" variant=\"ui2\">\n\t\t\t<CommandSentence template={resources.YouPreorderedOn} Container={Fragment}>\n\t\t\t\t<CommandSentence.Field name=\"PRE_ORDER_DATE\">\n\t\t\t\t\t<a className=\"text-primary\" href={routes.PreorderManagementPage}>\n\t\t\t\t\t\t{orderDate}\n\t\t\t\t\t</a>\n\t\t\t\t</CommandSentence.Field>\n\t\t\t</CommandSentence>\n\t\t</Typography>\n\t);\n};\n","import { useCallback, useState } from 'react';\nimport { FormatGroup } from './types';\n\nexport const GLE_MAX_QUANTITY = 1000;\n\ninterface ISku {\n\tid: string;\n\tisSubscription: boolean;\n\tisGroupLicenseEscrow: boolean;\n\tallowsMultipleQuantity: boolean;\n\tformatGroup: FormatGroup;\n}\n\nfunction reconcilePurchaseQuantityWithSku(selectedSku: ISku, currentQuantity: number) {\n\tif (selectedSku.isSubscription) {\n\t\t// For subscription SKUs, purchase quantity is not applicable, so just return the current quantity without modification\n\t\treturn currentQuantity;\n\t}\n\tif (selectedSku.isGroupLicenseEscrow) {\n\t\treturn Math.max(currentQuantity, 2);\n\t}\n\treturn selectedSku.allowsMultipleQuantity ? currentQuantity : 1;\n}\n\nexport function useSelectedSkuAndPurchaseQuantity<Sku extends ISku>(skus: Sku[]) {\n\tconst [selectedSku, setSelectedSku] = useState(skus[0]);\n\tconst [purchaseQuantity, setPurchaseQuantity] = useState(() => reconcilePurchaseQuantityWithSku(skus[0], 1));\n\n\tconst handleSelectedSkuChange = useCallback(\n\t\t(skuId: string, alternateSkuIds?: string[]) => {\n\t\t\tconst allSkuIdsToCheck = [skuId, ...(alternateSkuIds ?? [])];\n\t\t\tconst allSkusToCheck = allSkuIdsToCheck\n\t\t\t\t.map(id => skus.find(sku => sku.id === id))\n\t\t\t\t.filter((sku): sku is Sku => sku !== undefined);\n\n\t\t\t// check if there is a SKU that supports the currently selected purchase quantity\n\t\t\tlet matchingSku: Sku | null = null;\n\t\t\tfor (const sku of allSkusToCheck) {\n\t\t\t\t// skip subscription SKUs as they don't use purchase quantity\n\t\t\t\tif (sku.isSubscription) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (reconcilePurchaseQuantityWithSku(sku, purchaseQuantity) === purchaseQuantity) {\n\t\t\t\t\tmatchingSku = sku;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmatchingSku ??= allSkusToCheck[0];\n\n\t\t\tif (matchingSku) {\n\t\t\t\tconst nextSelectedSku = matchingSku;\n\t\t\t\tsetSelectedSku(nextSelectedSku);\n\t\t\t\tsetPurchaseQuantity(prevQuantity => reconcilePurchaseQuantityWithSku(nextSelectedSku, prevQuantity));\n\t\t\t}\n\t\t},\n\t\t[skus, purchaseQuantity]\n\t);\n\n\tconst handlePurchaseQuantityChange = useCallback(\n\t\t(quantity: number) => {\n\t\t\t// find a SKU that supports the new quantity if possible, otherwise keep the currently selected SKU\n\n\t\t\tconst clampedQuantity = Math.min(Math.max(quantity, 1), GLE_MAX_QUANTITY);\n\n\t\t\tconst eligibleSkus =\n\t\t\t\tselectedSku.formatGroup === 'logosEdition' || selectedSku.formatGroup === 'ebook'\n\t\t\t\t\t? skus.filter(sku => sku.formatGroup === selectedSku.formatGroup)\n\t\t\t\t\t: [selectedSku];\n\n\t\t\tconst matchingSku =\n\t\t\t\teligibleSkus.find(sku => reconcilePurchaseQuantityWithSku(sku, clampedQuantity) === clampedQuantity) ??\n\t\t\t\tselectedSku;\n\n\t\t\tsetSelectedSku(matchingSku);\n\t\t\tsetPurchaseQuantity(reconcilePurchaseQuantityWithSku(matchingSku, clampedQuantity));\n\t\t},\n\t\t[selectedSku, skus]\n\t);\n\n\treturn { selectedSku, purchaseQuantity, handleSelectedSkuChange, handlePurchaseQuantityChange };\n}\n","import React, { useMemo } from 'react';\nimport * as RadioGroup from '@radix-ui/react-radio-group';\nimport * as Tooltip from '@radix-ui/react-tooltip';\nimport cn from 'classnames';\nimport { Radio } from '@faithlife/styled-ui';\nimport { Select } from '@faithlife/styled-ui/text-input';\nimport { StepperControl } from '@faithlife/commerce-components';\nimport { SubscriptionInfo, SubscriptionPeriodType, usePricing } from '../../../per-user-data/per-user-data-context';\nimport { CommerceWebThemeProvider } from '../../../../util/theme';\nimport { FormatGroup, PurchaseOption, PurchaseOptionType } from '../types';\nimport { GLE_MAX_QUANTITY } from '../selected-sku-and-quantity-util';\n\ninterface Sku {\n\tid: string;\n\tformatDisplayName: string;\n\tsubscriptionInfo?: SubscriptionInfo | null;\n\tisSubscription: boolean;\n\tisGroupLicenseEscrow: boolean;\n\tallowsMultipleQuantity: boolean;\n\tformatGroup: FormatGroup;\n}\n\n/**\n * Represents a single chip in the purchase format selector, after combining single and Group License Escrow (GLE) SKUs in one chip\n */\ninterface PurchaseSkuChip {\n\tchipId: string;\n\tformatDisplayName: string;\n\tskuId: string;\n\totherSkuIds: string[];\n\tsupportsQuantitySelection: boolean;\n}\n\nfunction buildPurchaseSkuChips(purchaseSkus: Sku[], isOwned = false): PurchaseSkuChip[] {\n\tconst logosEditionSkus = purchaseSkus.filter(s => s.formatGroup === 'logosEdition');\n\tconst ebookSkus = purchaseSkus.filter(s => s.formatGroup === 'ebook');\n\tconst otherSkus = purchaseSkus.filter(s => s.formatGroup === 'other' || !s.formatGroup);\n\n\tconst logosEditionChips = mapSkuGroupToChips(logosEditionSkus, isOwned);\n\tconst ebookChips = mapSkuGroupToChips(ebookSkus, isOwned);\n\tconst otherChips: PurchaseSkuChip[] = otherSkus.map(sku => ({\n\t\tchipId: sku.id,\n\t\tformatDisplayName: sku.formatDisplayName,\n\t\tskuId: sku.id,\n\t\totherSkuIds: [],\n\t\tsupportsQuantitySelection: sku.allowsMultipleQuantity,\n\t}));\n\n\tconst chips = [...logosEditionChips, ...ebookChips, ...otherChips];\n\n\treturn chips;\n\n\tfunction mapSkuGroupToChips(skus: Sku[], isOwned: boolean): PurchaseSkuChip[] {\n\t\tconst chips: PurchaseSkuChip[] = [];\n\n\t\t// there really shouldn't be more than one single-purchase and one GLE SKU, so we're focusing on that case\n\t\tconst singlePurchaseSkus = skus.filter(s => !s.isGroupLicenseEscrow);\n\t\tconst gleSkus = skus.filter(s => s.isGroupLicenseEscrow);\n\n\t\tconst representativeSku =\n\t\t\tsinglePurchaseSkus.length > 0 ? singlePurchaseSkus[0] : gleSkus.length > 0 ? gleSkus[0] : null;\n\t\tif (representativeSku === null) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst handledSkuIds = new Set<string>();\n\t\t// If the user owns the product, we want to show GLE SKUs as alternatives.\n\t\tconst matchingGroupSkus = !isOwned ? gleSkus.filter(gle => gle.id !== representativeSku.id) : [];\n\n\t\tchips.push({\n\t\t\tchipId: representativeSku.id,\n\t\t\tformatDisplayName: representativeSku.formatDisplayName,\n\t\t\tskuId: representativeSku.id,\n\t\t\totherSkuIds: matchingGroupSkus.map(gle => gle.id),\n\t\t\tsupportsQuantitySelection: representativeSku.allowsMultipleQuantity || gleSkus.length > 0,\n\t\t});\n\n\t\thandledSkuIds.add(representativeSku.id);\n\t\tmatchingGroupSkus.forEach(gle => handledSkuIds.add(gle.id));\n\n\t\t// push remaining single and GLE SKUs as standalone chips (if any)\n\t\tfor (const sku of [...singlePurchaseSkus, ...gleSkus]) {\n\t\t\tif (handledSkuIds.has(sku.id)) {\n\t\t\t\tcontinue; // already processed\n\t\t\t}\n\t\t\tchips.push({\n\t\t\t\tchipId: sku.id,\n\t\t\t\tformatDisplayName: sku.formatDisplayName,\n\t\t\t\tskuId: sku.id,\n\t\t\t\totherSkuIds: [],\n\t\t\t\tsupportsQuantitySelection: sku.isGroupLicenseEscrow || sku.allowsMultipleQuantity,\n\t\t\t});\n\t\t}\n\n\t\treturn chips;\n\t}\n}\n\ninterface SkuSelectorProps {\n\tproductId: string;\n\tskus: Sku[];\n\tpurchaseOptions: PurchaseOption[];\n\tselectedSkuId: string;\n\tisSalePriceVisible: boolean;\n\tpurchaseQuantity: number;\n\tonSelectedSkuChange?: (skuId: string, alternateSkuIds?: string[]) => void;\n\tonPurchaseQuantityChange?: (quantity: number) => void;\n\tisOwned?: boolean;\n}\n\nconst skuItemClassName = cn(\n\t'rounded-sm border border-primary bg-white p-0 text-primary-400 transition-colors',\n\t'focus-visible:outline-hidden focus-visible:ring-4 focus-visible:ring-primary/20',\n\t'data-[state=checked]:border-primary',\n\t'lg:p-1'\n);\n\nconst PurchaseSkuItemContent = ({\n\tformatDisplayName,\n\tsalePrice,\n\trestricted,\n}: {\n\tformatDisplayName: string;\n\tsalePrice?: string;\n\trestricted?: boolean;\n}) => (\n\t<div className=\"flex items-center gap-2 rounded-sm bg-grey-200 px-2 py-1\">\n\t\t<span className=\"break-all font-semibold\">{formatDisplayName}</span>\n\t\t{salePrice && <span style={restricted ? { color: 'var(--theme-colors-black-c100)' } : undefined}>{salePrice}</span>}\n\t</div>\n);\n\ninterface PurchaseOptionSectionDetails {\n\tkey: 'purchase' | 'subscription';\n\ttype: PurchaseOptionType;\n\tisSelected: boolean;\n\tonSelect: () => void;\n\tcontent: React.ReactNode;\n}\n\nconst PurchaseOptionSection = ({\n\tisSelected,\n\tshowRadio,\n\ttitle,\n\tcontent,\n\tonSelect,\n}: {\n\tisSelected: boolean;\n\tshowRadio: boolean;\n\ttitle?: React.ReactNode;\n\tcontent: React.ReactNode;\n\tonSelect: () => void;\n}) => {\n\tconst className = cn('flex flex-col gap-2 transition duration-200 ease-out', {\n\t\t'opacity-100 grayscale-0': isSelected || !showRadio,\n\t\t'opacity-70 grayscale hover:opacity-100 hover:grayscale-0': !isSelected && showRadio,\n\t});\n\n\treturn (\n\t\t<div className={className}>\n\t\t\t{showRadio && (\n\t\t\t\t<Radio\n\t\t\t\t\tisChecked={isSelected}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={onSelect}\n\t\t\t\t\ttitle={<span className=\"font-semibold\">{title}</span>}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t{content}\n\t\t</div>\n\t);\n};\n\nconst periodTypeOrder: SubscriptionPeriodType[] = [\n\tSubscriptionPeriodType.Day,\n\tSubscriptionPeriodType.Month,\n\tSubscriptionPeriodType.Year,\n];\n\nfunction comparePeriodTypes(a: SubscriptionPeriodType | undefined, b: SubscriptionPeriodType | undefined) {\n\tif (a === b) {\n\t\treturn 0;\n\t}\n\tif (a === undefined) {\n\t\treturn 1;\n\t}\n\tif (b === undefined) {\n\t\treturn -1;\n\t}\n\tconst aIndex = periodTypeOrder.indexOf(a);\n\tconst bIndex = periodTypeOrder.indexOf(b);\n\treturn aIndex - bIndex;\n}\n\n/**\n * Given the currently active SKU ID, find the chip that owns it.\n */\nfunction findChipForSkuId(chips: PurchaseSkuChip[], skuId: string): PurchaseSkuChip | null {\n\treturn (\n\t\tchips.find(c => {\n\t\t\treturn c.skuId === skuId || c.otherSkuIds.includes(skuId);\n\t\t}) ?? null\n\t);\n}\n\nconst QuantitySelector = ({\n\tquantity,\n\tonQuantityChange,\n\tdisabled,\n}: {\n\tquantity: number;\n\tonQuantityChange: (qty: number) => void;\n\tdisabled?: boolean;\n}) => {\n\treturn (\n\t\t<div className=\"flex items-center gap-2\">\n\t\t\t<StepperControl\n\t\t\t\tscale=\"sm\"\n\t\t\t\tmin={1}\n\t\t\t\tmax={GLE_MAX_QUANTITY}\n\t\t\t\tvalue={quantity}\n\t\t\t\tonValueChange={onQuantityChange}\n\t\t\t\tdisabled={disabled}\n\t\t\t/>\n\t\t</div>\n\t);\n};\n\nexport const SkuSelector = ({\n\tproductId,\n\tskus,\n\tpurchaseOptions,\n\tselectedSkuId,\n\tisSalePriceVisible,\n\tpurchaseQuantity,\n\tonPurchaseQuantityChange,\n\tonSelectedSkuChange,\n\tisOwned,\n}: SkuSelectorProps) => {\n\tconst { data: pricingData } = usePricing(productId);\n\tconst pricingBySkuId = pricingData?.skus;\n\n\tconst purchaseSkus = useMemo(() => skus.filter(sku => !sku.isSubscription), [skus]);\n\tconst subscriptionSkus = useMemo(() => {\n\t\tconst result = skus\n\t\t\t.filter(sku => sku.isSubscription)\n\t\t\t.map(sku => {\n\t\t\t\tconst userPricingData = pricingBySkuId?.[sku.id];\n\t\t\t\tconst subscriptionInfo = userPricingData?.subscriptionInfo ?? sku.subscriptionInfo ?? null;\n\t\t\t\treturn { ...sku, subscriptionInfo };\n\t\t\t});\n\t\tresult.sort((a, b) => {\n\t\t\tif (!a.subscriptionInfo || !b.subscriptionInfo) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\treturn comparePeriodTypes(a.subscriptionInfo.periodType, b.subscriptionInfo.periodType);\n\t\t});\n\t\treturn result;\n\t}, [skus, pricingBySkuId]);\n\n\tconst purchaseChips = useMemo(() => buildPurchaseSkuChips(purchaseSkus, isOwned), [purchaseSkus, isOwned]);\n\n\t// Chips that share a format display name (e.g. several \"Digital\" gift card amounts) are\n\t// indistinguishable without their price.\n\tconst ambiguousFormatDisplayNames = useMemo(() => {\n\t\tconst counts = new Map<string, number>();\n\t\tfor (const chip of purchaseChips) {\n\t\t\tcounts.set(chip.formatDisplayName, (counts.get(chip.formatDisplayName) ?? 0) + 1);\n\t\t}\n\t\treturn new Set([...counts].filter(([, count]) => count > 1).map(([name]) => name));\n\t}, [purchaseChips]);\n\n\tconst lastSelectedPurchaseSkuIdRef = React.useRef<string | null>(\n\t\tpurchaseChips.length > 0 ? purchaseChips[0].skuId : null\n\t);\n\tif (purchaseSkus.some(sku => sku.id === selectedSkuId)) {\n\t\tlastSelectedPurchaseSkuIdRef.current = selectedSkuId;\n\t}\n\tconst lastSelectedPurchaseSkuId = lastSelectedPurchaseSkuIdRef.current;\n\n\tconst lastSelectedSubscriptionSkuIdRef = React.useRef<string | null>(\n\t\tsubscriptionSkus.length > 0 ? subscriptionSkus[0].id : null\n\t);\n\tif (subscriptionSkus.some(sku => sku.id === selectedSkuId)) {\n\t\tlastSelectedSubscriptionSkuIdRef.current = selectedSkuId;\n\t}\n\tconst lastSelectedSubscriptionSkuId = lastSelectedSubscriptionSkuIdRef.current;\n\n\tconst selectedSkuPurchaseChip = useMemo(() => {\n\t\treturn findChipForSkuId(purchaseChips, selectedSkuId) ?? null;\n\t}, [purchaseChips, selectedSkuId]);\n\n\tconst lastSelectedSkuPurchaseChip = useMemo(() => {\n\t\treturn lastSelectedPurchaseSkuId !== null\n\t\t\t? (findChipForSkuId(purchaseChips, lastSelectedPurchaseSkuId) ?? null)\n\t\t\t: null;\n\t}, [purchaseChips, lastSelectedPurchaseSkuId]);\n\n\tconst shouldShowQuantitySelector = lastSelectedSkuPurchaseChip?.supportsQuantitySelection ?? false;\n\n\tconst handleChipClick = (chipId: string) => {\n\t\tif (!onSelectedSkuChange) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst chip = purchaseChips.find(c => c.chipId === chipId);\n\t\tif (!chip) {\n\t\t\treturn;\n\t\t}\n\n\t\tonSelectedSkuChange(chip.skuId, chip.otherSkuIds);\n\t};\n\n\tconst handleQuantityChange = (newQuantity: number) => {\n\t\tonPurchaseQuantityChange?.(newQuantity);\n\t};\n\n\tconst isPurchaseSkuSelected = purchaseSkus.some(sku => sku.id === selectedSkuId);\n\tconst isSubscriptionSkuSelected = subscriptionSkus.some(sku => sku.id === selectedSkuId);\n\n\tconst handleSubscriptionSkuChange = (skuId: string) => {\n\t\tif (subscriptionSkus.some(sku => sku.id === skuId)) {\n\t\t\tonSelectedSkuChange?.(skuId);\n\t\t}\n\t};\n\n\tconst getPurchaseSkuItemContent = (chip: PurchaseSkuChip): React.ReactNode => {\n\t\tif (!ambiguousFormatDisplayNames.has(chip.formatDisplayName)) {\n\t\t\treturn <PurchaseSkuItemContent formatDisplayName={chip.formatDisplayName} />;\n\t\t}\n\n\t\tconst displaySkuId = chip.otherSkuIds.find(id => id === lastSelectedPurchaseSkuId) ?? chip.skuId;\n\t\tconst salePrice = isSalePriceVisible ? pricingBySkuId?.[displaySkuId]?.prices?.salePrice?.displayAmount : undefined;\n\t\treturn (\n\t\t\t<PurchaseSkuItemContent\n\t\t\t\tformatDisplayName={chip.formatDisplayName}\n\t\t\t\tsalePrice={salePrice}\n\t\t\t\trestricted={pricingData?.isGeographicallyRestricted ?? false}\n\t\t\t/>\n\t\t);\n\t};\n\n\tlet purchaseSkuChipContent: React.ReactNode = null;\n\tif (purchaseChips.length === 1 && subscriptionSkus.length === 0) {\n\t\tconst chip = purchaseChips[0];\n\t\t// Single chip with no alternatives — render as a non-interactive display item\n\t\tpurchaseSkuChipContent = (\n\t\t\t<div className=\"flex flex-wrap gap-2\">\n\t\t\t\t<div className={cn(skuItemClassName, 'cursor-default')}>{getPurchaseSkuItemContent(chip)}</div>\n\t\t\t</div>\n\t\t);\n\t} else if (purchaseChips.length > 0) {\n\t\tpurchaseSkuChipContent = (\n\t\t\t<RadioGroup.Root\n\t\t\t\tclassName=\"flex flex-wrap gap-2\"\n\t\t\t\tvalue={selectedSkuPurchaseChip?.chipId ?? ''}\n\t\t\t\tonValueChange={handleChipClick}\n\t\t\t>\n\t\t\t\t{purchaseChips.map(chip => {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<RadioGroup.Item\n\t\t\t\t\t\t\tkey={chip.chipId}\n\t\t\t\t\t\t\tvalue={chip.chipId}\n\t\t\t\t\t\t\tclassName={cn(skuItemClassName, 'cursor-pointer border-transparent hover:border-primary')}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{getPurchaseSkuItemContent(chip)}\n\t\t\t\t\t\t</RadioGroup.Item>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</RadioGroup.Root>\n\t\t);\n\t}\n\tlet purchaseSkuContent: React.ReactNode = null;\n\tif (purchaseSkuChipContent) {\n\t\tpurchaseSkuContent = (\n\t\t\t<Tooltip.Provider>\n\t\t\t\t<div className=\"flex flex-col gap-6\">\n\t\t\t\t\t{purchaseSkuChipContent}\n\t\t\t\t\t{shouldShowQuantitySelector && (\n\t\t\t\t\t\t<QuantitySelector\n\t\t\t\t\t\t\tquantity={purchaseQuantity}\n\t\t\t\t\t\t\tonQuantityChange={handleQuantityChange}\n\t\t\t\t\t\t\tdisabled={selectedSkuId !== lastSelectedPurchaseSkuId}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</Tooltip.Provider>\n\t\t);\n\t}\n\n\tlet subscriptionSkuContent: React.ReactNode = null;\n\tif (subscriptionSkus.length > 0) {\n\t\tconst selectedSubscriptionSku = subscriptionSkus.find(sku => sku.id === lastSelectedSubscriptionSkuId);\n\n\t\tconst pricingForSelectedSubscriptionSku = selectedSubscriptionSku\n\t\t\t? pricingBySkuId?.[selectedSubscriptionSku.id]\n\t\t\t: undefined;\n\t\tconst subscriptionDisplayPrice = isSalePriceVisible\n\t\t\t? pricingForSelectedSubscriptionSku?.prices?.salePrice?.displayAmount && (\n\t\t\t\t\t<>{pricingForSelectedSubscriptionSku.prices.salePrice.displayAmount}</>\n\t\t\t\t)\n\t\t\t: undefined;\n\n\t\tconst selectValue = selectedSubscriptionSku && {\n\t\t\tvalue: lastSelectedSubscriptionSkuId,\n\t\t\tlabel: (\n\t\t\t\t<>\n\t\t\t\t\t<span className=\"font-semibold\">{selectedSubscriptionSku.subscriptionInfo?.periodDisplay ?? ''}</span>\n\t\t\t\t\t{!(selectedSubscriptionSku.subscriptionInfo?.shouldHidePrice ?? false) && subscriptionDisplayPrice && (\n\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t{' • '}\n\t\t\t\t\t\t\t{subscriptionDisplayPrice}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t),\n\t\t};\n\n\t\tconst options = subscriptionSkus.map(sku => {\n\t\t\tconst price = isSalePriceVisible ? pricingBySkuId?.[sku.id]?.prices?.salePrice?.displayAmount : undefined;\n\t\t\tconst name = sku.subscriptionInfo?.periodDisplay ?? '';\n\t\t\tconst shouldHidePrice = sku.subscriptionInfo?.shouldHidePrice ?? false;\n\t\t\treturn {\n\t\t\t\tvalue: sku.id,\n\t\t\t\tlabel: (\n\t\t\t\t\t<span className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<span className=\"font-semibold mr-auto\">{name}</span>\n\t\t\t\t\t\t{!shouldHidePrice && price && <span>{price}</span>}\n\t\t\t\t\t</span>\n\t\t\t\t),\n\t\t\t};\n\t\t});\n\n\t\tsubscriptionSkuContent = (\n\t\t\t<div className=\"max-w-sm\">\n\t\t\t\t<Select\n\t\t\t\t\toptions={options}\n\t\t\t\t\tvalue={selectValue}\n\t\t\t\t\tonChange={(option: { value: string }) => handleSubscriptionSkuChange(option.value)}\n\t\t\t\t\tisSearchable={false}\n\t\t\t\t\tonFocus={() => {\n\t\t\t\t\t\thandleSubscriptionSkuChange(lastSelectedSubscriptionSkuId ?? subscriptionSkus[0].id);\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tconst purchaseOptionSections: PurchaseOptionSectionDetails[] = [];\n\tif (purchaseSkuContent) {\n\t\tconst firstChip = purchaseChips[0];\n\t\tpurchaseOptionSections.push({\n\t\t\tkey: 'purchase',\n\t\t\ttype: 'payInFull',\n\t\t\tisSelected: isPurchaseSkuSelected,\n\t\t\tonSelect: () => firstChip && handleChipClick(firstChip.chipId),\n\t\t\tcontent: purchaseSkuContent,\n\t\t});\n\t}\n\tif (subscriptionSkuContent) {\n\t\tpurchaseOptionSections.push({\n\t\t\tkey: 'subscription',\n\t\t\ttype: 'subscription',\n\t\t\tisSelected: isSubscriptionSkuSelected,\n\t\t\tonSelect: () => handleSubscriptionSkuChange(lastSelectedSubscriptionSkuId ?? subscriptionSkus[0].id),\n\t\t\tcontent: subscriptionSkuContent,\n\t\t});\n\t}\n\n\tconst showRadioOptions = purchaseOptionSections.length > 1;\n\n\treturn (\n\t\t<CommerceWebThemeProvider>\n\t\t\t{purchaseOptionSections.map(purchaseOptionSection => {\n\t\t\t\tconst purchaseOption = purchaseOptions.find(option => option.type === purchaseOptionSection.type);\n\n\t\t\t\treturn (\n\t\t\t\t\t<PurchaseOptionSection\n\t\t\t\t\t\tkey={purchaseOptionSection.key}\n\t\t\t\t\t\tisSelected={purchaseOptionSection.isSelected}\n\t\t\t\t\t\tshowRadio={showRadioOptions}\n\t\t\t\t\t\ttitle={purchaseOption?.title}\n\t\t\t\t\t\tcontent={purchaseOptionSection.content}\n\t\t\t\t\t\tonSelect={purchaseOptionSection.onSelect}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t})}\n\t\t</CommerceWebThemeProvider>\n\t);\n};\n","import React from 'react';\nimport { useLocalization } from '../../../../localization';\nimport { AuthorsAndPublishers } from './authors-and-publishers';\n\ninterface Chip {\n\tname: string;\n\turl: string | null | undefined;\n}\n\ninterface MetadataRowProps {\n\tauthors: readonly Chip[];\n\tpublishers: readonly Chip[];\n\tpublicationPeriod: string | null | undefined;\n\tisbn: string | null | undefined;\n}\n\nexport const MetadataRow = ({ authors, publishers, publicationPeriod, isbn }: MetadataRowProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Details');\n\tconst publisherMetadata =\n\t\tpublicationPeriod || isbn ? (\n\t\t\t<>\n\t\t\t\t{publicationPeriod ? (\n\t\t\t\t\t<span aria-label={resources.PublicationPeriod} className=\"text-sm leading-5 text-black-200\">\n\t\t\t\t\t\t{publishers.length ? `, ${publicationPeriod}` : publicationPeriod}\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t\t{isbn ? (\n\t\t\t\t\t<span className=\"text-sm leading-5 text-black-200\">\n\t\t\t\t\t\t<span className=\"font-semibold\">{resources.IsbnLabel}</span>\n\t\t\t\t\t\t{isbn}\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t</>\n\t\t) : null;\n\n\treturn <AuthorsAndPublishers authors={authors} publishers={publishers} publisherMetadata={publisherMetadata} />;\n};\n","import React, { useEffect, useState } from 'react';\nimport { LinkButton, StarRating } from '@faithlife/commerce-components';\nimport { useLocalization } from '../../../../localization';\nimport { REVIEWS_ANCHOR_ID } from '../../reviews/reviews-anchor';\nimport { hasValidReviewData } from '../../../shared/ratings/review-data';\n\ntype ReviewSummaryVariant = 'default' | 'stickyAddToCart';\n\ninterface RatingSummary {\n\taverageRating: number | null | undefined;\n\tnumberOfReviews: number;\n}\n\ninterface ReviewSummaryProps {\n\tratingSummary: RatingSummary | null | undefined;\n\tvariant?: ReviewSummaryVariant;\n}\n\nexport const ReviewSummary = ({ ratingSummary, variant = 'default' }: ReviewSummaryProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Details');\n\tconst [headerHeight, setHeaderHeight] = useState(0);\n\n\tconst numberOfReviews = ratingSummary?.numberOfReviews ?? 0;\n\tconst averageRating = ratingSummary?.averageRating ?? 0;\n\tconst hasReviews = hasValidReviewData(averageRating, numberOfReviews);\n\n\tuseEffect(() => {\n\t\tconst getHeaderHeight = () => {\n\t\t\tconst header = document.querySelector('header');\n\n\t\t\treturn header ? header.getBoundingClientRect().height : 0;\n\t\t};\n\n\t\tsetHeaderHeight(getHeaderHeight());\n\n\t\tconst handleResize = () => setHeaderHeight(getHeaderHeight());\n\t\tconst handleLogosBannerClosed = () => setTimeout(() => setHeaderHeight(getHeaderHeight()), 0);\n\n\t\twindow.addEventListener('resize', handleResize);\n\t\twindow.addEventListener('logosBannerClosed', handleLogosBannerClosed);\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener('resize', handleResize);\n\t\t\twindow.removeEventListener('logosBannerClosed', handleLogosBannerClosed);\n\t\t};\n\t}, []);\n\n\tconst reviewsHref = `#${REVIEWS_ANCHOR_ID}`;\n\n\tconst handleScrollToReviews = (event: React.MouseEvent<HTMLAnchorElement>) => {\n\t\tconst reviewsElement = document.getElementById(REVIEWS_ANCHOR_ID);\n\n\t\tif (reviewsElement) {\n\t\t\tevent.preventDefault();\n\n\t\t\tconst rect = reviewsElement.getBoundingClientRect();\n\n\t\t\twindow.scrollTo({ top: rect.top + window.scrollY - headerHeight, behavior: 'smooth' });\n\n\t\t\thistory.pushState(null, '', reviewsHref);\n\t\t}\n\t};\n\n\tconst shouldDisplayLinkToReviews = variant !== 'stickyAddToCart';\n\n\tif (!hasReviews && !shouldDisplayLinkToReviews) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div className=\"flex items-center gap-1\">\n\t\t\t{hasReviews ? (\n\t\t\t\t<a\n\t\t\t\t\tclassName=\"inline-flex items-center transition-opacity hover:opacity-80 focus-visible:opacity-80 active:opacity-60 motion-reduce:transition-none\"\n\t\t\t\t\thref={reviewsHref}\n\t\t\t\t\tonClick={handleScrollToReviews}\n\t\t\t\t>\n\t\t\t\t\t<StarRating scale=\"md\" rating={averageRating} reviewCount={numberOfReviews} />\n\t\t\t\t</a>\n\t\t\t) : null}\n\t\t\t{shouldDisplayLinkToReviews && !hasReviews && (\n\t\t\t\t<LinkButton href={reviewsHref} onClick={handleScrollToReviews} scale=\"sm\">\n\t\t\t\t\t{resources.BeTheFirstToRateThis}\n\t\t\t\t</LinkButton>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n","import React, { useEffect, useRef, useState } from 'react';\nimport { LinkButton } from '@faithlife/commerce-components';\nimport { cn } from '../../../../util/cn';\nimport { useLocalization } from '../../../../localization';\nimport '../product-details.css';\n\ninterface ProductDescriptionProps {\n\tdescriptionHtml: string | null | undefined;\n}\n\nexport const ProductDescription = ({ descriptionHtml }: ProductDescriptionProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Details');\n\tconst [showFullDescription, setShowFullDescription] = useState(false);\n\tconst [isTruncatable, setIsTruncatable] = useState(false);\n\tconst contentRef = useRef<HTMLElement>(null);\n\n\tuseEffect(() => {\n\t\tif (contentRef.current && !showFullDescription) {\n\t\t\tsetIsTruncatable(contentRef.current.scrollHeight > contentRef.current.clientHeight);\n\t\t}\n\t}, [descriptionHtml, showFullDescription]);\n\n\tuseEffect(() => {\n\t\ttry {\n\t\t\tif (typeof window?.refTagger?.tag === 'function') {\n\t\t\t\twindow.refTagger.tag();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to run RefTagger tag():', error);\n\t\t}\n\t}, [descriptionHtml]);\n\n\tif (!descriptionHtml) {\n\t\treturn null;\n\t}\n\n\tconst toggleDescription = () => setShowFullDescription(prev => !prev);\n\tconst buttonLabel = showFullDescription ? resources.ReadLess : resources.ReadMore;\n\n\treturn (\n\t\t<section className=\"product-description\">\n\t\t\t<div className=\"bd-product-display-content\">\n\t\t\t\t<article\n\t\t\t\t\tref={contentRef}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'builder-text mt-4 transition-all duration-500 ease-in-out lg:mt-6 [&>p:first-child]:mt-0',\n\t\t\t\t\t\t!showFullDescription && 'line-clamp-5'\n\t\t\t\t\t)}\n\t\t\t\t\tdangerouslySetInnerHTML={{ __html: descriptionHtml }}\n\t\t\t\t\tid=\"product-description-content\"\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t{(isTruncatable || showFullDescription) && (\n\t\t\t\t<LinkButton\n\t\t\t\t\tas=\"button\"\n\t\t\t\t\taria-controls=\"product-description-content\"\n\t\t\t\t\taria-expanded={showFullDescription}\n\t\t\t\t\taria-label={resources.ProductDescriptionToggle.replace('%ACTION%', buttonLabel)}\n\t\t\t\t\tscale=\"sm\"\n\t\t\t\t\tonClick={toggleDescription}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t>\n\t\t\t\t\t{buttonLabel}\n\t\t\t\t</LinkButton>\n\t\t\t)}\n\t\t</section>\n\t);\n};\n","import React from 'react';\nimport { CommandSentence } from '@faithlife/command-sentence-control';\nimport { Typography } from '@faithlife/commerce-components';\nimport { useLocalization } from '../../../../localization';\nimport { usePricing } from '../../../per-user-data/per-user-data-context';\nimport { AddToWishListWithForm } from '../../../add-to-wish-list';\nimport { Prices } from '../prices';\nimport { PurchaseActions, getPurchaseActionState } from '../purchase-actions';\nimport { Gallery } from '../gallery';\nimport { LogosEditionCallout, hasResourceFormatCallout } from '../logos-edition-callout';\nimport { SeeInside } from '../see-inside';\nimport { PurchaseOption, StaticProduct, StaticSku } from '../types';\nimport { useProductInWishList } from '../../../add-to-wish-list/hooks';\nimport { PrepubProductStatusSummary } from './prepub-product-status-summary';\nimport { PreorderedProductLabel } from './preordered-product-label';\nimport { SkuSelector } from './sku-selector';\nimport { MetadataRow } from './metadata-row';\nimport { ReviewSummary } from './review-summary';\nimport { ProductDescription } from './product-description';\n\nexport interface DetailsProps {\n\tproduct: StaticProduct;\n\tselectedSku: StaticSku;\n\tskus: StaticSku[];\n\tpurchaseOptions: PurchaseOption[];\n\tpurchaseQuantity: number;\n\tonSelectedSkuChange?: (skuId: string, alternateSkuIds?: string[]) => void;\n\tonPurchaseQuantityChange?: (quantity: number) => void;\n\tlogosOrVerbum?: string;\n\tlogosEditionLearnMoreVideoUrl?: string | null;\n\tseeInsideIframeUrl?: string | null;\n\taddToCartButtonRef?: React.Ref<HTMLDivElement>;\n}\n\nexport const Details = ({\n\tproduct,\n\tselectedSku,\n\tskus,\n\tpurchaseOptions,\n\tpurchaseQuantity,\n\tonSelectedSkuChange,\n\tonPurchaseQuantityChange,\n\tlogosOrVerbum = 'Logos',\n\tlogosEditionLearnMoreVideoUrl,\n\tseeInsideIframeUrl,\n\taddToCartButtonRef,\n}: DetailsProps) => {\n\tconst detailsResources = useLocalization('CommerceWeb.Resources.Product.Details');\n\tconst pricingSidebarResources = useLocalization(\n\t\t'CommerceWeb.Resources.Product.DisplayTemplates.PricingSidebarViewModel'\n\t);\n\n\tconst { isLoading, data: pricingData } = usePricing(product.id);\n\n\tconst { hasTemporaryAccess, hasPermanentAccess, canShowOpenInLogos } = getPurchaseActionState({\n\t\tproduct,\n\t\tselectedSku,\n\t\tpricingData,\n\t});\n\tconst isGroupLicenseEscrow = selectedSku.isGroupLicenseEscrow ?? false;\n\tconst isOwned = hasPermanentAccess || hasTemporaryAccess;\n\n\tconst perUserSkuData = pricingData?.skus?.[selectedSku.id];\n\tconst hasPerUserSkuData = !isLoading && perUserSkuData !== null && perUserSkuData !== undefined;\n\tconst isSkuSellable = hasPerUserSkuData\n\t\t? (perUserSkuData.isSellable ?? selectedSku.isSellable)\n\t\t: selectedSku.isSellable;\n\tconst isSkuPurchasable = perUserSkuData?.isPurchasable ?? false;\n\n\tconst productWishlistData = useProductInWishList(\n\t\tproduct.id,\n\t\tselectedSku.id,\n\t\tisSkuPurchasable && !pricingData?.isPrepubProduct\n\t);\n\n\tlet explanation: React.ReactNode = null;\n\tlet isBlockedFromPurchase = false;\n\tif (!isLoading) {\n\t\tif (pricingData?.preorder) {\n\t\t\texplanation = <PreorderedProductLabel {...pricingData.preorder} />;\n\t\t} else if (isOwned && isSkuSellable) {\n\t\t\texplanation = hasPermanentAccess\n\t\t\t\t? isGroupLicenseEscrow\n\t\t\t\t\t? detailsResources.YouCanDistribute\n\t\t\t\t\t: detailsResources.YouAlreadyOwnThisProduct\n\t\t\t\t: detailsResources.YouHaveTemporaryAccess;\n\t\t} else if (pricingData?.isGeographicallyRestricted) {\n\t\t\texplanation = pricingSidebarResources.ProductNotAvailableInYourRegion;\n\t\t\tisBlockedFromPurchase = true;\n\t\t} else if (pricingData?.userCountryOrRegionIsTradeSanctioned) {\n\t\t\texplanation = (\n\t\t\t\t<CommandSentence template={pricingSidebarResources.UserCountryOfacSanctioned}>\n\t\t\t\t\t<CommandSentence.Field name=\"CURRENT_PRODUCT\">{product.name}</CommandSentence.Field>\n\t\t\t\t</CommandSentence>\n\t\t\t);\n\t\t\tisBlockedFromPurchase = true;\n\t\t} else if (pricingData?.isAcademicallyRestricted && !isSkuPurchasable) {\n\t\t\texplanation = (\n\t\t\t\t<span\n\t\t\t\t\tdangerouslySetInnerHTML={{\n\t\t\t\t\t\t__html: pricingSidebarResources.ProductOnlyAvailableForAcademicProgramMembers,\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t);\n\t\t\tisBlockedFromPurchase = true;\n\t\t} else if (!isSkuSellable) {\n\t\t\texplanation = pricingSidebarResources.UnavailableToPurchase;\n\t\t}\n\t}\n\treturn (\n\t\t<div className=\"flex flex-col lg:mb-0 lg:ml-0 gap-6\">\n\t\t\t<Typography className=\"text-primary-400 md:heading-h4\" tag=\"h1\" variant=\"headingH5\">\n\t\t\t\t{product.name}\n\t\t\t</Typography>\n\t\t\t<MetadataRow\n\t\t\t\tauthors={product.authors ?? []}\n\t\t\t\tpublishers={product.publishers ?? []}\n\t\t\t\tpublicationPeriod={product.publicationPeriod}\n\t\t\t\tisbn={product.isbn}\n\t\t\t/>\n\t\t\t<ReviewSummary ratingSummary={product.ratingSummary} />\n\t\t\t<div className=\"lg:hidden md:max-w-[343px]\">\n\t\t\t\t<Gallery imageUri={product.imageUri} productName={product.name} />\n\t\t\t\t{seeInsideIframeUrl && <SeeInside seeInsideIframeUrl={seeInsideIframeUrl} />}\n\t\t\t</div>\n\n\t\t\t{hasResourceFormatCallout(selectedSku.resourceFormat) && (\n\t\t\t\t<div className=\"md:hidden\">\n\t\t\t\t\t<LogosEditionCallout\n\t\t\t\t\t\tlogosOrVerbum={logosOrVerbum}\n\t\t\t\t\t\tlogosEditionLearnMoreVideoUrl={logosEditionLearnMoreVideoUrl}\n\t\t\t\t\t\tresourceFormat={selectedSku.resourceFormat}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{!pricingData?.hasPreorder && (\n\t\t\t\t<Prices\n\t\t\t\t\tprices={pricingData?.skus?.[selectedSku.id]?.prices ?? null}\n\t\t\t\t\tisRestricted={pricingData?.isGeographicallyRestricted ?? false}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t{pricingData?.prepubProductStatusSummary && (\n\t\t\t\t<PrepubProductStatusSummary {...pricingData.prepubProductStatusSummary} variant=\"pdp\" />\n\t\t\t)}\n\t\t\t<SkuSelector\n\t\t\t\tproductId={product.id}\n\t\t\t\tskus={skus}\n\t\t\t\tpurchaseOptions={purchaseOptions}\n\t\t\t\tselectedSkuId={selectedSku.id}\n\t\t\t\tisSalePriceVisible={!pricingData?.hasPreorder}\n\t\t\t\tpurchaseQuantity={purchaseQuantity}\n\t\t\t\tonSelectedSkuChange={onSelectedSkuChange}\n\t\t\t\tonPurchaseQuantityChange={onPurchaseQuantityChange}\n\t\t\t\tisOwned={isOwned}\n\t\t\t/>\n\t\t\t{explanation && (\n\t\t\t\t<Typography className=\"text-black-100\" tag=\"div\" variant=\"bodySmall\">\n\t\t\t\t\t{explanation}\n\t\t\t\t</Typography>\n\t\t\t)}\n\n\t\t\t{!isLoading && ((isSkuPurchasable && !isBlockedFromPurchase) || canShowOpenInLogos) ? (\n\t\t\t\t<PurchaseActions\n\t\t\t\t\tproduct={product}\n\t\t\t\t\tselectedSku={selectedSku}\n\t\t\t\t\tpricingData={pricingData}\n\t\t\t\t\tshowSubscriptionPromotion\n\t\t\t\t\tclassName=\"flex gap-2 items-center\"\n\t\t\t\t\tquantity={purchaseQuantity}\n\t\t\t\t\taddToCartButtonRef={addToCartButtonRef}\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t\t{productWishlistData !== null && (\n\t\t\t\t<AddToWishListWithForm {...productWishlistData} variant=\"link\" isOwned={isOwned} />\n\t\t\t)}\n\t\t\t<ProductDescription descriptionHtml={product.descriptionHtml} />\n\t\t</div>\n\t);\n};\n","import React, { ReactNode } from 'react';\nimport cn from 'classnames';\n\ninterface StickyAddToCartBarProps {\n\tid?: string;\n\tchildren: ReactNode;\n\tisVisible: boolean;\n}\n\nconst StickyAddToCartBar = ({ id, children, isVisible }: StickyAddToCartBarProps) => {\n\treturn (\n\t\t<div\n\t\t\tid={id}\n\t\t\taria-hidden={!isVisible}\n\t\t\tinert={!isVisible}\n\t\t\tclassName={cn(\n\t\t\t\t'fixed bottom-0 left-0 right-0 z-5 border-y border-grey bg-white p-sp16 lg:p-sp24 transition-transform duration-300 ease-in-out',\n\t\t\t\tisVisible ? 'translate-y-0' : 'translate-y-full'\n\t\t\t)}\n\t\t>\n\t\t\t{children}\n\t\t</div>\n\t);\n};\n\nexport default StickyAddToCartBar;\n","import React from 'react';\nimport { Typography } from '@faithlife/commerce-components';\nimport { ProductPricingData } from '../../../per-user-data/per-user-data-context';\nimport { Prices } from '../prices';\nimport { PurchaseActions } from '../purchase-actions';\nimport { ReviewSummary } from '../right-column/review-summary';\n\nexport interface StickyAddToCartProduct {\n\tid: string;\n\tname: string;\n\tresourceId?: string;\n\tisCollection: boolean;\n\tratingSummary?: { averageRating: number | null | undefined; numberOfReviews: number } | null;\n}\n\nexport interface StickyAddToCartSelectedSku {\n\tid: string;\n\tisGroupLicenseEscrow?: boolean;\n\tisSubscription?: boolean;\n\tallowsMultipleQuantity?: boolean;\n}\n\ninterface StickyAddToCartContentProps {\n\tproduct: StickyAddToCartProduct;\n\tselectedSku: StickyAddToCartSelectedSku;\n\tpurchaseQuantity: number;\n\tisLoading: boolean;\n\tpricingData?: ProductPricingData | null;\n\tcanShowAddToCart: boolean;\n\tshouldRenderButtons: boolean;\n}\n\n/**\n * Inner content for the sticky add-to-cart bar.\n *  - Left (hidden on mobile): product title + star rating summary\n *  - Right: pricing + action buttons\n */\nexport const StickyAddToCartContent = ({\n\tproduct,\n\tselectedSku,\n\tpurchaseQuantity,\n\tisLoading,\n\tpricingData,\n\tcanShowAddToCart,\n\tshouldRenderButtons,\n}: StickyAddToCartContentProps) => {\n\tconst shouldRenderActionSection = !isLoading && shouldRenderButtons;\n\n\treturn (\n\t\t<div className=\"mx-auto flex max-w-[1440px] flex-row items-center justify-between gap-sp30\">\n\t\t\t{/* Left section — hidden on mobile, title + rating */}\n\t\t\t<div className=\"hidden min-w-0 items-center gap-sp16 md:flex\">\n\t\t\t\t<Typography className=\"min-w-0 truncate text-primary-400\" tag=\"h5\" variant=\"headingH5\">\n\t\t\t\t\t{product.name}\n\t\t\t\t</Typography>\n\t\t\t\t<ReviewSummary ratingSummary={product.ratingSummary} variant=\"stickyAddToCart\" />\n\t\t\t</div>\n\n\t\t\t{/* Right section — pricing + action buttons */}\n\t\t\t{shouldRenderActionSection && (\n\t\t\t\t<div className=\"flex w-full min-w-0 items-center gap-sp8 md:w-auto md:shrink-0\">\n\t\t\t\t\t<div className=\"min-w-0 flex-1\">\n\t\t\t\t\t\t<PurchaseActions\n\t\t\t\t\t\t\tproduct={product}\n\t\t\t\t\t\t\tselectedSku={selectedSku}\n\t\t\t\t\t\t\tpricingData={pricingData}\n\t\t\t\t\t\t\tclassName=\"flex items-center gap-sp8 [&>button]:min-w-0 [&>button]:flex-1 [&>button]:overflow-hidden [&>button]:whitespace-nowrap md:[&>button]:flex-none max-[374px]:[&>button:nth-child(2)]:hidden\"\n\t\t\t\t\t\t\tquantity={purchaseQuantity}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t\t{canShowAddToCart ? (\n\t\t\t\t\t\t<span className=\"shrink-0\">\n\t\t\t\t\t\t\t<Prices\n\t\t\t\t\t\t\t\tprices={pricingData?.skus?.[selectedSku.id]?.prices ?? null}\n\t\t\t\t\t\t\t\tisRestricted={false}\n\t\t\t\t\t\t\t\tvariant=\"salePriceOnly\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n","import React from 'react';\nimport { usePricing } from '../../../per-user-data/per-user-data-context';\nimport { getPurchaseActionState } from '../purchase-actions';\nimport StickyAddToCartBar from './sticky-add-to-cart-bar';\nimport {\n\tStickyAddToCartContent,\n\tStickyAddToCartProduct,\n\tStickyAddToCartSelectedSku,\n} from './sticky-add-to-cart-content';\n\ninterface StickyAddToCartProps {\n\tid?: string;\n\tisVisible: boolean;\n\tproduct: StickyAddToCartProduct;\n\tselectedSku: StickyAddToCartSelectedSku;\n\tpurchaseQuantity: number;\n}\n\nconst StickyAddToCart = ({ id, isVisible, product, selectedSku, purchaseQuantity }: StickyAddToCartProps) => {\n\tconst { isLoading, data: pricingData } = usePricing(product.id);\n\tconst { canShowAddToCart, shouldRenderButtons } = getPurchaseActionState({\n\t\tproduct,\n\t\tselectedSku,\n\t\tpricingData,\n\t});\n\n\tconst shouldRenderActionSection = !isLoading && isVisible && shouldRenderButtons;\n\n\treturn (\n\t\t<StickyAddToCartBar id={id} isVisible={shouldRenderActionSection}>\n\t\t\t<StickyAddToCartContent\n\t\t\t\tproduct={product}\n\t\t\t\tselectedSku={selectedSku}\n\t\t\t\tpurchaseQuantity={purchaseQuantity}\n\t\t\t\tisLoading={isLoading}\n\t\t\t\tpricingData={pricingData}\n\t\t\t\tcanShowAddToCart={canShowAddToCart}\n\t\t\t\tshouldRenderButtons={shouldRenderButtons}\n\t\t\t/>\n\t\t</StickyAddToCartBar>\n\t);\n};\n\nexport default StickyAddToCart;\n","import React from 'react';\nimport { registerAdzone } from '@faithlife/commerce-components';\n\nimport RenderBuilderContent from '../../builder/render-builder-content';\nimport { SectionContentViewModel } from '../../../builder';\n\nregisterAdzone();\n\ninterface AdzoneBlockProps {\n\tadzone: SectionContentViewModel;\n}\n\nconst AdzoneBlock = ({ adzone }: AdzoneBlockProps) => (\n\t<>{adzone.contentSourceKind === 'builderIo' && <RenderBuilderContent {...adzone.builderIo} />}</>\n);\n\nexport default AdzoneBlock;\n","import React from 'react';\nimport { TimeSensitiveCallout } from '@faithlife/commerce-components';\n\ninterface TimeSensitiveCalloutBlockProps {\n\thtml?: string | null;\n}\n\nexport const TimeSensitiveCalloutBlock = ({ html }: TimeSensitiveCalloutBlockProps) => {\n\tif (!html) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div className=\"mx-auto my-4 w-full max-w-[1440px]\">\n\t\t\t<TimeSensitiveCallout>\n\t\t\t\t<div dangerouslySetInnerHTML={{ __html: html }} />\n\t\t\t</TimeSensitiveCallout>\n\t\t</div>\n\t);\n};\n","import React, { useEffect, useState } from 'react';\nimport Cookies from 'js-cookie';\nimport { CommandSentence } from '@faithlife/command-sentence-control';\nimport { CloseButton, Typography } from '@faithlife/commerce-components';\nimport { useLocalization } from '../../../localization';\nimport PlatformExplainerHeaderDesktop from './platform-explainer-header-desktop.svg';\nimport PlatformExplainerHeaderMobile from './platform-explainer-header-mobile.svg';\n\nexport const PlatformExplainerHeader = ({ logosOrVerbum }: { logosOrVerbum: string }) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Header');\n\tconst [hasCheckedDismissedCookie, setHasCheckedDismissedCookie] = useState(false);\n\tconst [isDismissed, setIsDismissed] = useState(true);\n\n\tuseEffect(() => {\n\t\tsetIsDismissed(Cookies.get('isPlatformExplainerDismissed') !== undefined);\n\t\tsetHasCheckedDismissedCookie(true);\n\t}, []);\n\n\tconst closeComponent = () => {\n\t\tCookies.set('isPlatformExplainerDismissed', 'true', { secure: true, path: '/product', expires: 7 });\n\t\tsetIsDismissed(true);\n\t};\n\n\tif (!hasCheckedDismissedCookie || isDismissed) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div className=\"mb-4 w-full bg-primary-100\">\n\t\t\t<div className=\"relative mx-auto flex max-w-[1440px] justify-between px-4 py-4 md:px-8 md:py-6\">\n\t\t\t\t<div className=\"flex items-center gap-4 md:mx-auto md:max-w-[696px] md:gap-6\">\n\t\t\t\t\t<div className=\"flex-none\">\n\t\t\t\t\t\t<img className=\"block w-[70px] md:hidden\" src={PlatformExplainerHeaderMobile} alt=\"\" />\n\t\t\t\t\t\t<img className=\"hidden h-[87px] w-auto md:block\" src={PlatformExplainerHeaderDesktop} alt=\"\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex flex-col gap-1 text-primary-400 md:gap-2\">\n\t\t\t\t\t\t<Typography className=\"m-0 w-[calc(100%-12px)] md:hidden\" variant=\"headingH6\">\n\t\t\t\t\t\t\t{resources.AnEbookAndSoMuchMore}\n\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t<Typography className=\"m-0 hidden md:block\" variant=\"headingH4\">\n\t\t\t\t\t\t\t{resources.AnEbookAndSoMuchMore}\n\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t<Typography className=\"inline md:hidden\" variant=\"bodySmall\">\n\t\t\t\t\t\t\t<CommandSentence Container=\"span\" template={resources.DiscoverConnectionsWithLogos}>\n\t\t\t\t\t\t\t\t<CommandSentence.Field name=\"LOGOSORVERBUM\">{logosOrVerbum}</CommandSentence.Field>\n\t\t\t\t\t\t\t</CommandSentence>\n\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t<Typography className=\"hidden md:inline lg:text-lg lg:leading-[135%]\" variant=\"bodySmall\">\n\t\t\t\t\t\t\t<CommandSentence Container=\"span\" template={resources.DiscoverConnectionsWithLogos}>\n\t\t\t\t\t\t\t\t<CommandSentence.Field name=\"LOGOSORVERBUM\">{logosOrVerbum}</CommandSentence.Field>\n\t\t\t\t\t\t\t</CommandSentence>\n\t\t\t\t\t\t</Typography>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<CloseButton variant=\"tertiary\" onClick={closeComponent} />\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import React, { Fragment } from 'react';\n\ninterface BreadcrumbsProps {\n\tcrumbs: {\n\t\turl?: string;\n\t\ttext: string;\n\t}[];\n}\n\nexport const Breadcrumbs = ({ crumbs }: BreadcrumbsProps) => (\n\t<div className=\"mx-auto w-full max-w-[1440px] p-4 md:px-6\">\n\t\t{crumbs.map((crumb, index) => {\n\t\t\tconst nextCrumb = crumbs[index + 1];\n\t\t\tconst isCurrentPageCrumb = index === crumbs.length - 1 && !crumb.url;\n\t\t\tconst isCurrentPageSeparator = index === crumbs.length - 2 && nextCrumb && !nextCrumb.url;\n\n\t\t\treturn (\n\t\t\t\t<Fragment key={`${crumb.url}-${crumb.text}`}>\n\t\t\t\t\t{crumb.url ? (\n\t\t\t\t\t\t<a className=\"text-gray-400\" href={crumb.url}>\n\t\t\t\t\t\t\t{crumb.text}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<span className={`${isCurrentPageCrumb ? 'hidden md:inline ' : ''}text-primary-400`}>{crumb.text}</span>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{index < crumbs.length - 1 && (\n\t\t\t\t\t\t<span className={`${isCurrentPageSeparator ? 'hidden md:inline ' : ''}mx-2 text-gray-400`}>{'>'}</span>\n\t\t\t\t\t)}\n\t\t\t\t</Fragment>\n\t\t\t);\n\t\t})}\n\t</div>\n);\n","import React from 'react';\nimport { useCurrentUser, usePricing } from '../../../per-user-data/per-user-data-context';\nimport Pencil from './svgs/edit_pencil_white.svg';\n\ninterface BusinessDeskEditLinkProps {\n\tproductId: string;\n}\n\nconst c_title = 'Edit Product';\n\nexport const BusinessDeskEditLink = ({ productId }: BusinessDeskEditLinkProps) => {\n\tconst { userInfo } = useCurrentUser();\n\tconst { data } = usePricing(productId);\n\n\tconst businessDeskEditUri = data?.businessDeskEditUri;\n\n\tif (!businessDeskEditUri || !userInfo.isEmployee) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<a\n\t\t\tclassName=\"absolute right-[15px] top-0 z-10 hidden sm:inline-block\"\n\t\t\thref={businessDeskEditUri}\n\t\t\ttitle={c_title}\n\t\t\ttarget=\"_blank\"\n\t\t\trel=\"noopener noreferrer\"\n\t\t>\n\t\t\t<img\n\t\t\t\tclassName=\"size-5 rounded-[3px] bg-[#c1c1c1cc] p-1 [background-origin:content-box]\"\n\t\t\t\tsrc={Pencil}\n\t\t\t\talt={c_title}\n\t\t\t/>\n\t\t</a>\n\t);\n};\n","import { g as getDocument, a as getWindow } from '../shared/ssr-window.esm.mjs';\nimport { d as elementParents, f as elementOffset } from '../shared/utils.mjs';\n\n/* eslint-disable consistent-return */\nfunction Keyboard({\n  swiper,\n  extendParams,\n  on,\n  emit\n}) {\n  const document = getDocument();\n  const window = getWindow();\n  swiper.keyboard = {\n    enabled: false\n  };\n  extendParams({\n    keyboard: {\n      enabled: false,\n      onlyInViewport: true,\n      pageUpDown: true,\n      speed: undefined\n    }\n  });\n  function handle(event) {\n    if (!swiper.enabled) return;\n    const {\n      rtlTranslate: rtl\n    } = swiper;\n    let e = event;\n    if (e.originalEvent) e = e.originalEvent; // jquery fix\n    const kc = e.keyCode || e.charCode;\n    const pageUpDown = swiper.params.keyboard.pageUpDown;\n    const isPageUp = pageUpDown && kc === 33;\n    const isPageDown = pageUpDown && kc === 34;\n    const isArrowLeft = kc === 37;\n    const isArrowRight = kc === 39;\n    const isArrowUp = kc === 38;\n    const isArrowDown = kc === 40;\n    // Directions locks\n    if (!swiper.allowSlideNext && (swiper.isHorizontal() && isArrowRight || swiper.isVertical() && isArrowDown || isPageDown)) {\n      return false;\n    }\n    if (!swiper.allowSlidePrev && (swiper.isHorizontal() && isArrowLeft || swiper.isVertical() && isArrowUp || isPageUp)) {\n      return false;\n    }\n    if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) {\n      return undefined;\n    }\n    if (document.activeElement && (document.activeElement.isContentEditable || document.activeElement.nodeName && (document.activeElement.nodeName.toLowerCase() === 'input' || document.activeElement.nodeName.toLowerCase() === 'textarea'))) {\n      return undefined;\n    }\n    if (swiper.params.keyboard.onlyInViewport && (isPageUp || isPageDown || isArrowLeft || isArrowRight || isArrowUp || isArrowDown)) {\n      let inView = false;\n      // Check that swiper should be inside of visible area of window\n      if (elementParents(swiper.el, `.${swiper.params.slideClass}, swiper-slide`).length > 0 && elementParents(swiper.el, `.${swiper.params.slideActiveClass}`).length === 0) {\n        return undefined;\n      }\n      const el = swiper.el;\n      const swiperWidth = el.clientWidth;\n      const swiperHeight = el.clientHeight;\n      const windowWidth = window.innerWidth;\n      const windowHeight = window.innerHeight;\n      const swiperOffset = elementOffset(el);\n      if (rtl) swiperOffset.left -= el.scrollLeft;\n      const swiperCoord = [[swiperOffset.left, swiperOffset.top], [swiperOffset.left + swiperWidth, swiperOffset.top], [swiperOffset.left, swiperOffset.top + swiperHeight], [swiperOffset.left + swiperWidth, swiperOffset.top + swiperHeight]];\n      for (let i = 0; i < swiperCoord.length; i += 1) {\n        const point = swiperCoord[i];\n        if (point[0] >= 0 && point[0] <= windowWidth && point[1] >= 0 && point[1] <= windowHeight) {\n          if (point[0] === 0 && point[1] === 0) continue; // eslint-disable-line\n          inView = true;\n        }\n      }\n      if (!inView) return undefined;\n    }\n    const speed = swiper.params.keyboard.speed;\n    if (swiper.isHorizontal()) {\n      if (isPageUp || isPageDown || isArrowLeft || isArrowRight) {\n        if (e.preventDefault) e.preventDefault();else e.returnValue = false;\n      }\n      if ((isPageDown || isArrowRight) && !rtl || (isPageUp || isArrowLeft) && rtl) swiper.slideNext(speed);\n      if ((isPageUp || isArrowLeft) && !rtl || (isPageDown || isArrowRight) && rtl) swiper.slidePrev(speed);\n    } else {\n      if (isPageUp || isPageDown || isArrowUp || isArrowDown) {\n        if (e.preventDefault) e.preventDefault();else e.returnValue = false;\n      }\n      if (isPageDown || isArrowDown) swiper.slideNext(speed);\n      if (isPageUp || isArrowUp) swiper.slidePrev(speed);\n    }\n    emit('keyPress', kc);\n    return undefined;\n  }\n  function enable() {\n    if (swiper.keyboard.enabled) return;\n    document.addEventListener('keydown', handle);\n    swiper.keyboard.enabled = true;\n  }\n  function disable() {\n    if (!swiper.keyboard.enabled) return;\n    document.removeEventListener('keydown', handle);\n    swiper.keyboard.enabled = false;\n  }\n  on('init', () => {\n    if (swiper.params.keyboard.enabled) {\n      enable();\n    }\n  });\n  on('destroy', () => {\n    if (swiper.keyboard.enabled) {\n      disable();\n    }\n  });\n  Object.assign(swiper.keyboard, {\n    enable,\n    disable\n  });\n}\n\nexport { Keyboard as default };\n","import React, { useState } from 'react';\nimport * as DialogPrimitive from '@radix-ui/react-dialog';\nimport { VisuallyHidden } from '@radix-ui/react-visually-hidden';\nimport { X } from 'lucide-react';\nimport { Keyboard, Scrollbar } from 'swiper/modules';\nimport { Swiper, SwiperSlide } from 'swiper/react';\nimport { useLocalization } from '../../../../localization';\nimport { Image } from '../../../shared/enhanced-image-tag/image';\n\ninterface SamplePagesProps {\n\timageUrls: readonly string[];\n}\n\nexport const SamplePages = ({ imageUrls }: SamplePagesProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Details');\n\tconst [initialSlide, setInitialSlide] = useState(0);\n\tconst [isOpen, setIsOpen] = useState(false);\n\n\tif (imageUrls.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<div>\n\t\t\t<div>\n\t\t\t\t<Swiper\n\t\t\t\t\tkeyboard\n\t\t\t\t\tmodules={[Scrollbar, Keyboard]}\n\t\t\t\t\tscrollbar={{\n\t\t\t\t\t\tel: '.swiper-scrollbar',\n\t\t\t\t\t\tdraggable: true,\n\t\t\t\t\t\tdragClass: 'scrollbar-sample-pages',\n\t\t\t\t\t\tdragSize: 50,\n\t\t\t\t\t}}\n\t\t\t\t\tslidesPerView=\"auto\"\n\t\t\t\t\tspaceBetween={8}\n\t\t\t\t>\n\t\t\t\t\t{imageUrls.map((imageSrc, index) => (\n\t\t\t\t\t\t<SwiperSlide className=\"!w-[68px] border border-gray-300\" key={imageSrc}>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tclassName=\"block h-full w-full\"\n\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\tsetIsOpen(true);\n\t\t\t\t\t\t\t\t\tsetInitialSlide(index);\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Image\n\t\t\t\t\t\t\t\t\talt={resources.SamplePagesThumbnailAlt}\n\t\t\t\t\t\t\t\t\tclassName=\"object-cover\"\n\t\t\t\t\t\t\t\t\theight={91}\n\t\t\t\t\t\t\t\t\tbelowTheFold\n\t\t\t\t\t\t\t\t\tfetchPriority=\"low\"\n\t\t\t\t\t\t\t\t\tsrc={imageSrc}\n\t\t\t\t\t\t\t\t\twidth={68}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</SwiperSlide>\n\t\t\t\t\t))}\n\t\t\t\t\t<div className=\"swiper-scrollbar mt-2 h-[11px] w-full bg-primary-100 p-[3px]\" />\n\t\t\t\t</Swiper>\n\t\t\t</div>\n\t\t\t<DialogPrimitive.Root onOpenChange={setIsOpen} open={isOpen}>\n\t\t\t\t<DialogPrimitive.Portal>\n\t\t\t\t\t<DialogPrimitive.Overlay className=\"fixed inset-0 z-[50] bg-gray-900/60\" onClick={() => setIsOpen(false)} />\n\t\t\t\t\t<DialogPrimitive.Content\n\t\t\t\t\t\taria-describedby={undefined}\n\t\t\t\t\t\tclassName=\"fixed left-1/2 top-1/2 z-[100] flex h-dvh w-screen -translate-x-1/2 -translate-y-1/2 transform flex-col overflow-hidden bg-white sm:h-[92dvh] sm:w-[92vw] sm:max-w-[720px] sm:rounded-sm sm:shadow-xl\"\n\t\t\t\t\t\tonPointerDownOutside={e => e.preventDefault()}\n\t\t\t\t\t>\n\t\t\t\t\t\t<VisuallyHidden>\n\t\t\t\t\t\t\t<DialogPrimitive.Title>{resources.SamplePagesViewer}</DialogPrimitive.Title>\n\t\t\t\t\t\t</VisuallyHidden>\n\t\t\t\t\t\t<div className=\"flex shrink-0 justify-end border-b border-gray-200 p-2\">\n\t\t\t\t\t\t\t<DialogPrimitive.Close asChild>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\taria-label={resources.Close}\n\t\t\t\t\t\t\t\t\tclassName=\"rounded-full p-2 text-gray-600 hover:bg-gray-100\"\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<X />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</DialogPrimitive.Close>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<Swiper\n\t\t\t\t\t\t\tclassName=\"min-h-0 w-full flex-1 bg-gray-50\"\n\t\t\t\t\t\t\tinitialSlide={initialSlide}\n\t\t\t\t\t\t\tkeyboard\n\t\t\t\t\t\t\tmodules={[Keyboard]}\n\t\t\t\t\t\t\tonSlideChange={swiper => setInitialSlide(swiper.activeIndex)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{imageUrls.map(imageSrc => (\n\t\t\t\t\t\t\t\t<SwiperSlide className=\"flex h-full items-center justify-center p-4\" key={imageSrc}>\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\talt={resources.SamplePagesSlideImage}\n\t\t\t\t\t\t\t\t\t\tclassName=\"max-h-full max-w-full object-contain shadow-md\"\n\t\t\t\t\t\t\t\t\t\tsrc={imageSrc}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</SwiperSlide>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</Swiper>\n\t\t\t\t\t</DialogPrimitive.Content>\n\t\t\t\t</DialogPrimitive.Portal>\n\t\t\t</DialogPrimitive.Root>\n\t\t</div>\n\t);\n};\n","import React from 'react';\nimport { useLocalization } from '../../../../localization';\nimport { Gallery } from '../gallery';\nimport { LogosEditionCallout, hasResourceFormatCallout } from '../logos-edition-callout';\nimport { SeeInside } from '../see-inside';\nimport { SamplePages } from './sample-pages';\n\ninterface LeftColumnProduct {\n\tid: string;\n\tname: string;\n\timageUri?: string | null;\n\tsamplePageImageUrls?: readonly string[] | null;\n\tallowsSeeInside?: boolean;\n}\n\ninterface LeftColumnSelectedSku {\n\tresourceFormat?: string | null;\n}\n\ninterface LeftColumnProps {\n\tproduct: LeftColumnProduct;\n\tselectedSku?: LeftColumnSelectedSku | null;\n\tlogosOrVerbum?: string;\n\tlogosEditionLearnMoreVideoUrl?: string | null;\n\tseeInsideIframeUrl?: string | null;\n}\n\nexport const LeftColumn = ({\n\tproduct,\n\tselectedSku,\n\tlogosOrVerbum = 'Logos',\n\tlogosEditionLearnMoreVideoUrl,\n\tseeInsideIframeUrl,\n}: LeftColumnProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Details');\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\"hidden lg:block\">\n\t\t\t\t<Gallery imageUri={product.imageUri} productName={product.name} />\n\t\t\t</div>\n\t\t\t{seeInsideIframeUrl && (\n\t\t\t\t<div className=\"hidden lg:block\">\n\t\t\t\t\t<SeeInside seeInsideIframeUrl={seeInsideIframeUrl} />\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{selectedSku && hasResourceFormatCallout(selectedSku.resourceFormat) && (\n\t\t\t\t<div className=\"mt-sp24 hidden md:block\">\n\t\t\t\t\t<LogosEditionCallout\n\t\t\t\t\t\tlogosOrVerbum={logosOrVerbum}\n\t\t\t\t\t\tlogosEditionLearnMoreVideoUrl={logosEditionLearnMoreVideoUrl}\n\t\t\t\t\t\tresourceFormat={selectedSku.resourceFormat}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{product.samplePageImageUrls && product.samplePageImageUrls.length > 0 ? (\n\t\t\t\t<div className=\"md:mt-6\">\n\t\t\t\t\t<p className=\"mb-2 text-sm capitalize text-black-100\">{resources.SamplePages}</p>\n\t\t\t\t\t<SamplePages imageUrls={product.samplePageImageUrls} />\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t</>\n\t);\n};\n","import React from 'react';\nimport { Typography } from '@faithlife/commerce-components';\nimport { useLocalization } from '../../../localization';\nimport { usePricing } from '../../per-user-data/per-user-data-context';\nimport { useUnownedResources } from './hooks/use-unowned-resources';\n\ninterface LibraryGreetingProps {\n\tproductId: string;\n\tproductName: string;\n\tuserName: string;\n}\n\nconst ShimmerInline = ({ width }: { width: string }) => (\n\t<span className={`inline-block ${width} h-[1em] animate-pulse rounded bg-primary-200 align-middle`} />\n);\n\nexport const LibraryGreeting = ({ productId, productName, userName }: LibraryGreetingProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Details');\n\tconst { isLoading: isPricingLoading, data: pricingData } = usePricing(productId);\n\tconst { isLoading: isUnownedLoading, data: unownedData } = useUnownedResources(productId);\n\n\tif (isUnownedLoading) {\n\t\treturn null;\n\t}\n\tif (!unownedData || unownedData.count === 0) {\n\t\treturn null;\n\t}\n\n\tconst greetingText = resources.LibraryGreeting.replace('%USER_NAME%', userName);\n\n\tconst primarySkuPrices = pricingData?.primarySku?.prices;\n\tconst priceDisplay = primarySkuPrices?.salePrice?.displayAmount;\n\n\treturn (\n\t\t<>\n\t\t\t<hr className=\"hidden lg:block border-grey lg:mx-sp24\" />\n\t\t\t<section className=\"mx-4 border border-black-20 rounded-b border-t-[6px] border-t-primary-400 px-6 py-5 text-center md:mx-6 lg:mx-6 max-lg:mt-sp24 lg:mt-sp32\">\n\t\t\t\t<Typography tag=\"h2\" variant=\"headingH5\" className=\"mb-3\">\n\t\t\t\t\t{greetingText}\n\t\t\t\t</Typography>\n\t\t\t\t<Typography variant=\"bodySmall\" className=\"text-black-70\">\n\t\t\t\t\t{resources.LibraryResourcesYouDontOwn?.replace('%LIBRARY_NAME%', productName).replace(\n\t\t\t\t\t\t'%UNOWNED_RESOURCE_COUNT%',\n\t\t\t\t\t\tString(unownedData.count)\n\t\t\t\t\t)}{' '}\n\t\t\t\t\t{isPricingLoading\n\t\t\t\t\t\t? resources.LibraryAddByGetting.replace('%LIBRARY_NAME%', productName)\n\t\t\t\t\t\t\t\t.split('%PRICE%')\n\t\t\t\t\t\t\t\t.map((part, i, arr) => (\n\t\t\t\t\t\t\t\t\t<React.Fragment key={i}>\n\t\t\t\t\t\t\t\t\t\t{part}\n\t\t\t\t\t\t\t\t\t\t{i < arr.length - 1 && <ShimmerInline width=\"w-16\" />}\n\t\t\t\t\t\t\t\t\t</React.Fragment>\n\t\t\t\t\t\t\t\t))\n\t\t\t\t\t\t: priceDisplay &&\n\t\t\t\t\t\t\tresources.LibraryAddByGetting.replace('%LIBRARY_NAME%', productName)\n\t\t\t\t\t\t\t\t.split('%PRICE%')\n\t\t\t\t\t\t\t\t.map((part, i, arr) => (\n\t\t\t\t\t\t\t\t\t<React.Fragment key={i}>\n\t\t\t\t\t\t\t\t\t\t{part}\n\t\t\t\t\t\t\t\t\t\t{i < arr.length - 1 && <strong>{priceDisplay}</strong>}\n\t\t\t\t\t\t\t\t\t</React.Fragment>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t</Typography>\n\t\t\t</section>\n\t\t</>\n\t);\n};\n","import { useEffect, useState } from 'react';\n\ninterface UnownedResourcesInfo {\n\tcount: number;\n\tvalueIfPurchasedSeparately: string;\n\tvalueIfPurchasedSeparatelyLocalized: string | null;\n}\n\ninterface UnownedResourcesResponse {\n\tinfos: Record<string, UnownedResourcesInfo>;\n}\n\nexport function useUnownedResources(productId: string) {\n\tconst [data, setData] = useState<UnownedResourcesInfo | null>(null);\n\tconst [isLoading, setIsLoading] = useState(true);\n\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\n\t\tfetch(`/product/unownedresourcesinfos?productIds=${encodeURIComponent(productId)}`, {\n\t\t\theaders: { 'X-Requested-With': 'XMLHttpRequest' },\n\t\t})\n\t\t\t.then(response => {\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new Error(`Failed to fetch unowned resources: ${response.status}`);\n\t\t\t\t}\n\t\t\t\treturn response.json() as Promise<UnownedResourcesResponse>;\n\t\t\t})\n\t\t\t.then(result => {\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tsetData(result.infos[productId] ?? null);\n\t\t\t\t\tsetIsLoading(false);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tif (!cancelled) {\n\t\t\t\t\tsetIsLoading(false);\n\t\t\t\t}\n\t\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [productId]);\n\n\treturn { data, isLoading };\n}\n","import React, { useMemo } from 'react';\nimport {\n\tEventsTrackingContextProvider,\n\tEventsTrackingContextProviderProps,\n} from '../../events-tracking/events-tracking-context';\nimport BuilderComponentsContextProvider from '../../builder/provider';\nimport {\n\tPerUserDataContextProvider,\n\tProductPriceAmount,\n\tProductPriceBreakdownLine,\n\tProductPricingData,\n\tProductPricingSkuData,\n} from '../../per-user-data/per-user-data-context';\nimport { useCurrentUser } from '../../per-user-data/per-user-data-context';\nimport { SectionContentViewModel } from '../../../builder';\nimport { useLocalization } from '../../../localization/use-localization';\nimport { BuyInCollection } from '../recommendations/buy-in-collection';\nimport { ContainingSubscriptions } from '../recommendations/containing-subscriptions';\nimport { CustomersAlsoBought } from '../recommendations/customers-also-bought';\nimport { FeaturedProductsSection } from '../featured-products';\nimport Reviews from '../reviews';\nimport type { ReviewsViewModel } from '../reviews/types';\nimport ProductContentSections from '../product-content-sections';\nimport { DisplayTemplate, ProductDetailsMetadata, AuthorBio } from '../product-content-sections/types';\nimport { useSeeInsideUrl } from './hooks/use-see-inside-url';\nimport { Details } from './right-column';\nimport { StickyAddToCart } from './sticky-add-to-cart';\nimport AdzoneBlock from './adzone-block';\nimport { TimeSensitiveCalloutBlock } from './time-sensitive-callout-block';\nimport { PlatformExplainerHeader } from './platform-explainer';\nimport { Breadcrumbs } from './breadcrumbs';\nimport { BusinessDeskEditLink } from './businessdesk-edit-link';\nimport { LeftColumn } from './left-column';\nimport { LibraryGreeting } from './library-greeting';\nimport { PurchaseOption, StaticProduct, User, StaticSku, SkuPriceAmount, SkuPriceBreakdownLine } from './types';\nimport { useSelectedSkuAndPurchaseQuantity } from './selected-sku-and-quantity-util';\nimport { useStickyAddToCartHandler } from './sticky-add-to-cart/use-sticky-add-to-cart-handler';\n\nfunction mapSkuData(sku: StaticSku, localizedCurrencyCode: string | undefined): ProductPricingSkuData {\n\tconst { salePrice, anchorPrice, anchorSavings, discountSavings } = sku.price ?? {};\n\n\treturn {\n\t\tskuId: sku.id,\n\t\tisSellable: sku.isSellable,\n\t\tisOwned: false,\n\t\tisInCart: false,\n\t\thasBeenPreordered: false,\n\t\tprices: salePrice\n\t\t\t? {\n\t\t\t\t\tsalePrice: mapLocalizedPrice(salePrice, localizedCurrencyCode),\n\t\t\t\t\tanchorPrice: anchorPrice ? mapLocalizedPrice(anchorPrice, localizedCurrencyCode) : null,\n\t\t\t\t\tanchorSavings: anchorSavings ? mapLocalizedPrice(anchorSavings, localizedCurrencyCode) : null,\n\t\t\t\t\tdiscountSavings: discountSavings ? mapLocalizedPrice(discountSavings, localizedCurrencyCode) : null,\n\t\t\t\t\tdiscounts: sku.price?.discounts ?? null,\n\t\t\t\t\tbreakdownTriggerLabel: sku.price?.breakdownTriggerLabel ?? null,\n\t\t\t\t\tbreakdownLines: mapBreakdownLines(sku.price?.breakdownLines, localizedCurrencyCode),\n\t\t\t\t\tanchorPriceLines: mapAnchorPriceLines(sku.price?.anchorPriceLines, localizedCurrencyCode),\n\t\t\t\t\tsavingsDescription: sku.price?.savingsDescription ?? null,\n\t\t\t\t}\n\t\t\t: null,\n\t\tdeliveryMethod: null,\n\t\tsubscriptionInfo: sku.subscriptionInfo ?? null,\n\t\troutes: {},\n\t};\n}\n\nfunction mapBreakdownLines(\n\tbreakdownLines: SkuPriceBreakdownLine[] | null | undefined,\n\tlocalizedCurrencyCode: string | undefined\n): ProductPriceBreakdownLine[] | null {\n\tif (!breakdownLines || breakdownLines.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn breakdownLines.map(line => ({\n\t\tlabel: line.label,\n\t\tamount: mapLocalizedPrice(line.amount, localizedCurrencyCode),\n\t\tisDeduction: line.isDeduction,\n\t\tdisplayInUsd: line.displayInUsd,\n\t\thref: line.href ?? null,\n\t}));\n}\n\nfunction mapLocalizedPrice(price: SkuPriceAmount, localizedCurrencyCode: string | undefined): ProductPriceAmount {\n\treturn {\n\t\tamount: price.amount,\n\t\tdisplayAmount: localizedCurrencyCode\n\t\t\t? (price.displayAmountByCurrency?.['USD'] ?? price.displayAmount)\n\t\t\t: price.displayAmount,\n\t\tdisplayAmountCurrencyCode: price.displayAmountCurrencyCode ?? null,\n\t\tlocalizedDisplayAmount: localizedCurrencyCode\n\t\t\t? (price.displayAmountByCurrency?.[localizedCurrencyCode] ?? null)\n\t\t\t: (price.localizedDisplayAmount ?? null),\n\t\tcurrencyCode: price.currencyCode,\n\t\tdisplayAmountByCurrency: price.displayAmountByCurrency ?? null,\n\t};\n}\n\nfunction mapAnchorPriceLines(\n\tanchorPriceLines:\n\t\t| { label: string; displayAmount?: string | null; displayAmountByCurrency?: Record<string, string> | null }[]\n\t\t| null\n\t\t| undefined,\n\tlocalizedCurrencyCode: string | undefined\n): { label: string; displayAmount?: string | null; localizedDisplayAmount?: string | null }[] | null {\n\tif (!anchorPriceLines || anchorPriceLines.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn anchorPriceLines.map(line => ({\n\t\tlabel: line.label,\n\t\tdisplayAmount: localizedCurrencyCode\n\t\t\t? (line.displayAmountByCurrency?.['USD'] ?? line.displayAmount)\n\t\t\t: line.displayAmount,\n\t\tlocalizedDisplayAmount: localizedCurrencyCode\n\t\t\t? (line.displayAmountByCurrency?.[localizedCurrencyCode] ?? null)\n\t\t\t: null,\n\t}));\n}\n\nfunction mapSkuPricesToProductPricingData(\n\tproductId: string,\n\tskus: StaticSku[],\n\tlocalizedCurrencyCode: string | undefined,\n\tisPrepubProduct = false\n): ProductPricingData {\n\tconst skusRecord: Record<string, ProductPricingSkuData> = {};\n\tfor (const sku of skus) {\n\t\tskusRecord[sku.id] = mapSkuData(sku, localizedCurrencyCode);\n\t}\n\n\tconst primarySku = skus.length > 0 ? (skusRecord[skus[0].id] ?? null) : null;\n\n\treturn {\n\t\tproductId,\n\t\taccessKind: 'Purchase',\n\t\tisOwned: false,\n\t\tpreorder: null,\n\t\thasPreorder: false,\n\t\tisPrepubProduct,\n\t\tprepubProductStatusSummary: null,\n\t\tisGeographicallyRestricted: false,\n\t\tisAcademicallyRestricted: false,\n\t\tuserCountryOrRegionIsTradeSanctioned: false,\n\t\tprimarySku,\n\t\tskus: skusRecord,\n\t};\n}\n\nexport interface ProductDetailsPageCoreProps {\n\tproduct: StaticProduct;\n\tskus: StaticSku[];\n\tpurchaseOptions: PurchaseOption[];\n\tdisplayTemplate?: DisplayTemplate | null;\n\tproductDetailsMetadata?: ProductDetailsMetadata | null;\n\tauthorBio?: AuthorBio | null;\n\tadzone?: SectionContentViewModel | null;\n\tuser: User;\n\tshowUserGreeting?: boolean;\n\tcontainingProductsUrl?: string | null;\n\tcontainingSubscriptionsUrl?: string | null;\n\tcustomersAlsoBoughtUrl?: string | null;\n\treviews?: ReviewsViewModel | null;\n\tfeaturedProductsUrl?: string | null;\n\tlogosOrVerbum?: string | null;\n\tlogosEditionLearnMoreVideoUrl?: string | null;\n}\n\nexport const ProductDetailsPageCore = ({\n\tproduct,\n\tskus,\n\tpurchaseOptions,\n\tdisplayTemplate,\n\tproductDetailsMetadata,\n\tauthorBio,\n\tadzone,\n\tuser,\n\tshowUserGreeting,\n\tcontainingProductsUrl,\n\tcontainingSubscriptionsUrl,\n\tcustomersAlsoBoughtUrl,\n\treviews,\n\tfeaturedProductsUrl,\n\tlogosOrVerbum,\n\tlogosEditionLearnMoreVideoUrl,\n}: ProductDetailsPageCoreProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Product.Details');\n\n\tconst { selectedSku, purchaseQuantity, handleSelectedSkuChange, handlePurchaseQuantityChange } =\n\t\tuseSelectedSkuAndPurchaseQuantity(skus);\n\n\tconst skuIds = useMemo(() => skus.map(s => s.id), [skus]);\n\n\tconst { seeInsideIframeUrl } = useSeeInsideUrl(product.id, product.allowsSeeInside);\n\n\tconst { intersectionTargetRef: addToCartButtonRef, isStickyAddToCartVisible } = useStickyAddToCartHandler();\n\tconst { isSignedIn, isLoading: isCurrentUserLoading } = useCurrentUser();\n\n\treturn (\n\t\t<>\n\t\t\t{!isCurrentUserLoading && !isSignedIn && product.sourceToken === 'libronix' && (\n\t\t\t\t<PlatformExplainerHeader logosOrVerbum={logosOrVerbum ?? 'Logos'} />\n\t\t\t)}\n\t\t\t<Breadcrumbs crumbs={[{ url: '/search', text: resources.Products }, { text: product.name }]} />\n\t\t\t<TimeSensitiveCalloutBlock html={displayTemplate?.content?.TimeSensitiveCallOut?.content} />\n\t\t\t<div className=\"tw-preflight relative mx-auto mb-11 flex w-full max-w-[1440px] flex-col lg:grid lg:grid-cols-2 lg:gap-8 xl:gap-15\">\n\t\t\t\t<BusinessDeskEditLink productId={product.id} />\n\t\t\t\t<div className=\"order-2 mx-4 mt-4 md:mt-0 md:mb-4 lg:order-1 lg:mb-0 lg:ml-6 lg:mr-0\">\n\t\t\t\t\t<LeftColumn\n\t\t\t\t\t\tproduct={product}\n\t\t\t\t\t\tlogosOrVerbum={logosOrVerbum ?? 'Logos'}\n\t\t\t\t\t\tlogosEditionLearnMoreVideoUrl={logosEditionLearnMoreVideoUrl}\n\t\t\t\t\t\tselectedSku={selectedSku}\n\t\t\t\t\t\tseeInsideIframeUrl={seeInsideIframeUrl}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"order-1 mx-4 mb-4 md:mb-6 lg:order-2 lg:mb-0 lg:ml-0 lg:mr-sp24\">\n\t\t\t\t\t<Details\n\t\t\t\t\t\tproduct={product}\n\t\t\t\t\t\tskus={skus}\n\t\t\t\t\t\tpurchaseOptions={purchaseOptions}\n\t\t\t\t\t\tselectedSku={selectedSku}\n\t\t\t\t\t\tpurchaseQuantity={purchaseQuantity}\n\t\t\t\t\t\tonSelectedSkuChange={handleSelectedSkuChange}\n\t\t\t\t\t\tonPurchaseQuantityChange={handlePurchaseQuantityChange}\n\t\t\t\t\t\tlogosOrVerbum={logosOrVerbum ?? 'Logos'}\n\t\t\t\t\t\tlogosEditionLearnMoreVideoUrl={logosEditionLearnMoreVideoUrl}\n\t\t\t\t\t\tseeInsideIframeUrl={seeInsideIframeUrl}\n\t\t\t\t\t\taddToCartButtonRef={addToCartButtonRef}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t{showUserGreeting && user.displayName && (\n\t\t\t\t\t<div className=\"lg:col-span-2 order-3 empty:hidden\">\n\t\t\t\t\t\t<LibraryGreeting productId={product.id} productName={product.name} userName={user.displayName} />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t{containingProductsUrl && (\n\t\t\t\t\t<div className=\"lg:col-span-2 order-3 empty:hidden\">\n\t\t\t\t\t\t<BuyInCollection containingProductsUrl={containingProductsUrl} />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t{containingSubscriptionsUrl && (\n\t\t\t\t\t<div className=\"lg:col-span-2 order-3 empty:hidden\">\n\t\t\t\t\t\t<ContainingSubscriptions containingSubscriptionsUrl={containingSubscriptionsUrl} />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t{featuredProductsUrl && (\n\t\t\t\t\t<div className=\"lg:col-span-2 order-3 empty:hidden\">\n\t\t\t\t\t\t<FeaturedProductsSection featuredProductsUrl={featuredProductsUrl} />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t<section className=\"order-4 flex flex-col gap-sp16 lg:gap-sp32 lg:col-span-2 lg:flex-col-reverse max-lg:mt-sp24 empty:hidden\">\n\t\t\t\t\t{adzone && (\n\t\t\t\t\t\t<div className=\"min-[990px]:max-lg:mx-sp16 lg:mx-sp24\">\n\t\t\t\t\t\t\t<AdzoneBlock adzone={adzone} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t\t{displayTemplate && (\n\t\t\t\t\t\t<ProductContentSections\n\t\t\t\t\t\t\tdisplayTemplate={displayTemplate}\n\t\t\t\t\t\t\tproductId={product.id}\n\t\t\t\t\t\t\tproductDetailsMetadata={productDetailsMetadata}\n\t\t\t\t\t\t\tauthorBio={authorBio}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{(!!adzone || !!displayTemplate) && <hr className=\"hidden lg:block border-grey lg:mx-sp24\" />}\n\t\t\t\t</section>\n\t\t\t\t{customersAlsoBoughtUrl && skus.length > 0 && (\n\t\t\t\t\t<div className=\"lg:col-span-2 order-5 empty:hidden\">\n\t\t\t\t\t\t<CustomersAlsoBought customersAlsoBoughtUrl={customersAlsoBoughtUrl} skuIds={skuIds} />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t{/* Reviews section: loaded entirely client-side after page render */}\n\t\t\t<div className=\"mx-auto max-w-[1440px] p-sp16 lg:p-sp24\">{reviews && <Reviews reviews={reviews} />}</div>\n\n\t\t\t<StickyAddToCart\n\t\t\t\tid=\"pdp-sticky-add-to-cart-banner\"\n\t\t\t\tisVisible={isStickyAddToCartVisible}\n\t\t\t\tproduct={product}\n\t\t\t\tselectedSku={selectedSku}\n\t\t\t\tpurchaseQuantity={purchaseQuantity}\n\t\t\t/>\n\t\t</>\n\t);\n};\n\ninterface ProductDetailsPageProps {\n\tproduct: StaticProduct;\n\tskus: StaticSku[];\n\tpurchaseOptions: PurchaseOption[];\n\talgoliaEventsTrackingSettings: Omit<EventsTrackingContextProviderProps, 'children' | 'queryId'>;\n\tqueryId?: string | null;\n\tdisplayTemplate?: DisplayTemplate | null;\n\tproductDetailsMetadata?: ProductDetailsMetadata | null;\n\tauthorBio?: AuthorBio | null;\n\tadzone?: SectionContentViewModel | null;\n\tuser: User;\n\tshowUserGreeting?: boolean;\n\tcontainingProductsUrl?: string | null;\n\tcontainingSubscriptionsUrl?: string | null;\n\tcustomersAlsoBoughtUrl?: string | null;\n\treviews?: ReviewsViewModel | null;\n\tfeaturedProductsUrl?: string | null;\n\tlogosOrVerbum?: string | null;\n\tlogosEditionLearnMoreVideoUrl?: string | null;\n}\n\nconst ProductDetailsPage = (props: ProductDetailsPageProps) => {\n\tconst { preferredCurrency } = useCurrentUser();\n\n\t// On SSR, preferredCurrency defaults to 'USD' (no localized prices yet).\n\t// Once the client mounts and useCurrentUser resolves, the localized currency\n\t// code is used to populate localizedDisplayAmount from pricesByCurrency.\n\tconst localizedCurrencyCode = preferredCurrency !== 'USD' ? preferredCurrency : undefined;\n\n\tconst initialPricingData = useMemo(\n\t\t() => [\n\t\t\tmapSkuPricesToProductPricingData(\n\t\t\t\tprops.product.id,\n\t\t\t\tprops.skus,\n\t\t\t\tlocalizedCurrencyCode,\n\t\t\t\tprops.product.isPrepubProduct\n\t\t\t),\n\t\t],\n\t\t[props.product.id, props.product.isPrepubProduct, props.skus, localizedCurrencyCode]\n\t);\n\n\treturn (\n\t\t<EventsTrackingContextProvider {...props.algoliaEventsTrackingSettings} queryId={props.queryId}>\n\t\t\t<PerUserDataContextProvider initialPricingData={initialPricingData}>\n\t\t\t\t<BuilderComponentsContextProvider staticProductData={[]}>\n\t\t\t\t\t<ProductDetailsPageCore {...props} />\n\t\t\t\t</BuilderComponentsContextProvider>\n\t\t\t</PerUserDataContextProvider>\n\t\t</EventsTrackingContextProvider>\n\t);\n};\n\nexport default ProductDetailsPage;\n","import { useEffect, useState } from 'react';\n\ninterface SeeInsideResponse {\n\tseeInsideIframeUrl: string | null;\n}\n\nasync function fetchSeeInsideUrl(productId: string): Promise<string | null> {\n\ttry {\n\t\tconst response = await fetch(`/api/product/${encodeURIComponent(productId)}/seeinside`);\n\t\tif (!response.ok) {\n\t\t\treturn null;\n\t\t}\n\t\tconst data: SeeInsideResponse = await response.json();\n\t\treturn data.seeInsideIframeUrl ?? null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function useSeeInsideUrl(\n\tproductId?: string,\n\tenabled = true\n): {\n\tseeInsideIframeUrl: string | null;\n\tisLoading: boolean;\n} {\n\tconst [seeInsideIframeUrl, setSeeInsideIframeUrl] = useState<string | null>(null);\n\tconst [isLoading, setIsLoading] = useState(false);\n\n\tuseEffect(() => {\n\t\tif (!productId || !enabled) {\n\t\t\tsetSeeInsideIframeUrl(null);\n\t\t\tsetIsLoading(false);\n\t\t\treturn;\n\t\t}\n\n\t\tlet cancelled = false;\n\t\tsetIsLoading(true);\n\n\t\tfetchSeeInsideUrl(productId).then(url => {\n\t\t\tif (!cancelled) {\n\t\t\t\tsetSeeInsideIframeUrl(url);\n\t\t\t\tsetIsLoading(false);\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [productId, enabled]);\n\n\treturn { seeInsideIframeUrl, isLoading };\n}\n","import { useCallback, useEffect, useState } from 'react';\n\n/**\n * Sticky bottom bar behavior:\n * - Show the sticky add-to-cart bar when the main add-to-cart button is not visible in the viewport.\n */\nexport const useStickyAddToCartHandler = () => {\n\tconst [isStickyAddToCartVisible, setIsStickyAddToCartVisible] = useState(false);\n\tconst [intersectionTarget, setIntersectionTarget] = useState<HTMLElement | null>(null);\n\n\tconst intersectionTargetRef: React.Ref<HTMLElement> = useCallback((element: HTMLElement | null) => {\n\t\tsetIntersectionTarget(element);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (!intersectionTarget) {\n\t\t\tsetIsStickyAddToCartVisible(false);\n\t\t\treturn;\n\t\t}\n\n\t\tconst intersectionObserverCallback = (entries: IntersectionObserverEntry[]) => {\n\t\t\tconst entry = entries[0];\n\t\t\tif (entry.isIntersecting) {\n\t\t\t\tsetIsStickyAddToCartVisible(false);\n\t\t\t} else {\n\t\t\t\tsetIsStickyAddToCartVisible(true);\n\t\t\t}\n\t\t};\n\n\t\tconst observerOptions = {\n\t\t\troot: null,\n\t\t\trootMargin: '0px',\n\t\t\tthreshold: 0.33,\n\t\t};\n\t\tconst observer = new IntersectionObserver(intersectionObserverCallback, observerOptions);\n\t\tobserver.observe(intersectionTarget);\n\t\treturn () => observer.disconnect();\n\t}, [intersectionTarget]);\n\n\treturn { intersectionTargetRef, isStickyAddToCartVisible };\n};\n","import { useLocalization } from '../../localization';\n\nconst priceFormatGettersByBillingMode = {\n\tMonthly: {\n\t\tgetLocalizedPriceFormat: resources => `(${resources.MonthlyPriceFormat})`,\n\t\tgetPriceFormat: resources => resources.MonthlyPriceFormat,\n\t},\n\tAnnually: {\n\t\tgetLocalizedPriceFormat: resources => `(${resources.AnnualPriceFormat})`,\n\t\tgetPriceFormat: resources => resources.MonthlyPriceFormat,\n\t},\n};\n\nconst freeTrialPeriodUnitTextGettersByUnit = {\n\tday: (freeTrialPeriodLength, resources) =>\n\t\tfreeTrialPeriodLength === 1 ? resources.DayPeriodUnit : resources.DaysPeriodUnit,\n\tmonth: (freeTrialPeriodLength, resources) =>\n\t\tfreeTrialPeriodLength === 1 ? resources.MonthPeriodUnit : resources.MonthsPeriodUnit,\n\tyear: (freeTrialPeriodLength, resources) =>\n\t\tfreeTrialPeriodLength === 1 ? resources.YearPeriodUnit : resources.YearsPeriodUnit,\n};\n\nconst useResourceFormatsAndTexts = ({\n\tlocale,\n\tbillingMode,\n\tfreeTrialPeriodUnit,\n\tfreeTrialPeriodLength,\n\tavailableLogosTieredSubscriptionLevels,\n\tsubscriptionResources: customSubscriptionResources,\n}) => {\n\tconst defaultSubscriptionResources = useLocalization('CommerceWeb.Resources.Product.ContainingSubscriptions');\n\tconst subscriptionResources = customSubscriptionResources ?? defaultSubscriptionResources;\n\tconst subscriptionPlansResources = useLocalization('CommerceWeb.Resources.Configure.SubscriptionPlans');\n\n\tif (!subscriptionResources || !subscriptionPlansResources) {\n\t\treturn null;\n\t}\n\n\tconst { getLocalizedPriceFormat, getPriceFormat } = priceFormatGettersByBillingMode[billingMode];\n\tconst getFreeTrialPeriodUnitText = freeTrialPeriodUnitTextGettersByUnit[freeTrialPeriodUnit?.toLowerCase()];\n\n\tconst availableSubscriptionLevelsFormatter = new Intl.ListFormat(locale, { style: 'long', type: 'conjunction' });\n\n\treturn {\n\t\tlocalizedPriceFormat: getLocalizedPriceFormat(subscriptionPlansResources),\n\t\tpriceFormat: getPriceFormat(subscriptionPlansResources),\n\t\tfreeTrialPeriodUnitText: getFreeTrialPeriodUnitText?.(freeTrialPeriodLength, subscriptionResources),\n\t\tlocalizedAvailableSubscriptionLevelListText: availableSubscriptionLevelsFormatter.format(\n\t\t\tavailableLogosTieredSubscriptionLevels?.map(level => subscriptionResources[`${level}Level`])\n\t\t),\n\t\tsubscriptionsText:\n\t\t\tavailableLogosTieredSubscriptionLevels?.length > 1\n\t\t\t\t? subscriptionResources.Subscriptions\n\t\t\t\t: subscriptionResources.Subscription,\n\t};\n};\n\nexport default useResourceFormatsAndTexts;\n","/*! js-cookie v3.0.8 | MIT */\nfunction assign (target) {\n  for (var i = 1; i < arguments.length; i++) {\n    var source = arguments[i];\n    for (var key in source) {\n      if (key === '__proto__') continue\n      target[key] = source[key];\n    }\n  }\n  return target\n}\n\nvar defaultConverter = {\n  read: function (value) {\n    if (value[0] === '\"') {\n      value = value.slice(1, -1);\n    }\n    return value.replace(/(%[\\dA-F]{2})+/gi, decodeURIComponent)\n  },\n  write: function (value) {\n    return encodeURIComponent(value).replace(\n      /%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,\n      decodeURIComponent\n    )\n  }\n};\n\nfunction init(converter, defaultAttributes) {\n  function set(name, value, attributes) {\n    if (typeof document === 'undefined') {\n      return\n    }\n\n    attributes = assign({}, defaultAttributes, attributes);\n\n    if (typeof attributes.expires === 'number') {\n      attributes.expires = new Date(Date.now() + attributes.expires * 864e5);\n    }\n    if (attributes.expires) {\n      attributes.expires = attributes.expires.toUTCString();\n    }\n\n    name = encodeURIComponent(name)\n      .replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)\n      .replace(/[()]/g, escape);\n\n    var stringifiedAttributes = '';\n    for (var attributeName in attributes) {\n      if (!attributes[attributeName]) {\n        continue\n      }\n\n      stringifiedAttributes += '; ' + attributeName;\n\n      if (attributes[attributeName] === true) {\n        continue\n      }\n\n      // Considers RFC 6265 section 5.2:\n      // ...\n      // 3.  If the remaining unparsed-attributes contains a %x3B (\";\")\n      //     character:\n      // Consume the characters of the unparsed-attributes up to,\n      // not including, the first %x3B (\";\") character.\n      // ...\n      stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];\n    }\n\n    return (document.cookie =\n      name + '=' + converter.write(value, name) + stringifiedAttributes)\n  }\n\n  function get(name) {\n    if (typeof document === 'undefined' || (arguments.length && !name)) {\n      return\n    }\n\n    // To prevent the for loop in the first place assign an empty array\n    // in case there are no cookies at all.\n    var cookies = document.cookie ? document.cookie.split('; ') : [];\n    var jar = {};\n    for (var i = 0; i < cookies.length; i++) {\n      var parts = cookies[i].split('=');\n      var value = parts.slice(1).join('=');\n\n      try {\n        var found = decodeURIComponent(parts[0]);\n        if (!(found in jar)) jar[found] = converter.read(value, found);\n        if (name === found) {\n          break\n        }\n      } catch (_e) {\n        // Do nothing...\n      }\n    }\n\n    return name ? jar[name] : jar\n  }\n\n  return Object.create(\n    {\n      set: set,\n      get: get,\n      remove: function (name, attributes) {\n        set(\n          name,\n          '',\n          assign({}, attributes, {\n            expires: -1\n          })\n        );\n      },\n      withAttributes: function (attributes) {\n        return init(this.converter, assign({}, this.attributes, attributes))\n      },\n      withConverter: function (converter) {\n        return init(assign({}, this.converter, converter), this.attributes)\n      }\n    },\n    {\n      attributes: { value: Object.freeze(defaultAttributes) },\n      converter: { value: Object.freeze(converter) }\n    }\n  )\n}\n\nvar api = init(defaultConverter, { path: '/' });\n\nexport { api as default };\n","/**\n * @license lucide-react v1.27.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n  [\n    \"path\",\n    {\n      d: \"M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5\",\n      key: \"mvr1a0\"\n    }\n  ]\n];\nconst Heart = createLucideIcon(\"heart\", __iconNode);\n\nexport { __iconNode, Heart as default };\n//# sourceMappingURL=heart.mjs.map\n","/**\n * @license lucide-react v1.27.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n  [\"path\", { d: \"M18 6 6 18\", key: \"1bl5f8\" }],\n  [\"path\", { d: \"m6 6 12 12\", key: \"d8bk6v\" }]\n];\nconst X = createLucideIcon(\"x\", __iconNode);\n\nexport { __iconNode, X as default };\n//# sourceMappingURL=x.mjs.map\n"],"names":["module","exports","ProductsClient","getContainingProductsAsync","containingProductsUrl","response","fetch","get","url","json","getHasContainingProductsAsync","hasContainingProductsUrl","getContainingSubscriptionsAsync","containingSubscriptionsUrl","getProductsCustomersAlsoBoughtAsync","customersAlsoBoughtUrl","skuIds","params","getTooltipAsync","getProductDownloadsAsync","downloadsUrl","getFeaturedProducts","featuredProductIdsUrl","error","status","featuredProducts","getQuickCompare","quickCompareUrl","getUnownedResourcesInfos","unownedResourcesInfosBaseUrl","productIds","join","infos","getShortBlurbsForProductIds","getShortBlurbsUrl","postWithBody","body","getSubscriptionPromotionsForSkuIds","getSubscriptionPromotionsUrl","useInView","threshold","rootMargin","ref","useRef","isInView","setIsInView","useState","useEffect","element","current","observer","IntersectionObserver","entry","isIntersecting","disconnect","observe","RecommendationsProductIdsContext","React","RecommendationsContext","products","children","staticProductData","initialOwnership","useMemo","dataMap","ids","ownership","forEach","product","index","catalogData","id","match","exec","extractProductId","productPageUrl","averageRating","ratings","reviewCount","numberOfRatings","shouldDisplayRatings","shouldDisplayStars","hasValidReviewData","name","primarySkuId","undefined","imageUri","imageUrl","productPageUri","author","skus","salePrice","currentPrice","salePriceCurrency","currentPriceCurrency","anchorPrice","isDiscounted","regularPrice","localizedSalePrice","currentPriceLocalized","priceVariant","rating","mapToProductData","push","productId","isOwned","isInCart","Provider","value","RecommendationsResourcesProvider","RecommendationsCartProvider","StaticProductDataProvider","InitialSkuOwnershipProvider","RecommendationsProductProvider","StaticWishlistDataProvider","errorContext","StaticWishlistProvider","ProductCardSkeleton","className","SkeletonCarousel","CarouselContent","CarouselProduct","showArrows","scale","RecommendationsCarousel","data","isLoading","heading","subHeading","length","ContentSection","sectionHeadline","headlineBody","headlineClassName","BuyInCollection","resources","useLocalization","setData","setIsLoading","fetchData","useCallback","async","containingProducts","BuyInCollectionTitle","YouCanSave","ContainingSubscriptions","containingSubscriptions","ContainingSubscriptionsCard","formatsAndTexts","useResourceFormatsAndTexts","locale","billingMode","freeTrialPeriodUnit","freeTrialPeriodLength","availableLogosTieredSubscriptionLevels","subscriptionResources","title","AccessThisTitleWithAFreeTrialToLogosOrVerbum","replace","logosOrVerbum","AccessThisTitleWithASubscriptionToLogosOrVerbum","priceText","priceFormat","startingAtMonthlyPrice","availableInText","AvailableInSubscriptions","localizedAvailableSubscriptionLevelListText","subscriptionsText","subscribeUrl","routes","ConfigurationWizardSubscriptions","StartingAt","href","Subscribe","fill","height","viewBox","width","xmlns","d","stroke","CustomersAlsoBought","CustomersAlsoBoughtTitle","FeaturedProducts","primaryProduct","secondaryProducts","src","alt","role","authorDisplayString","blurb","RegularPrice","map","key","FeaturedProductsSkeleton","FeaturedProductsSection","featuredProductsUrl","result","ResourceHighlights","ReviewsClient","getReviews","requestUrl","reviews","getAdditionalReviews","offset","getRatings","getReview","deleteReview","delete","createReview","userId","reviewText","addReactionToReview","post","removeReactionFromReview","flagReview","followPage","unfollowPage","RatingSelector","selectedRating","onSelectedRatingChange","previewRating","setPreviewRating","ratingDescriptions","HatedIt","DidntLikeIt","ItsOkay","LikedIt","LovedIt","activeRating","handleMouseEnter","point","handleMouseLeave","handleClick","_desc","isFilled","starClassName","type","onMouseEnter","onMouseLeave","onClick","StarFilledIcon","size","StarIcon","TextArea","forwardRef","props","_extends","cn","displayName","ReviewEditor","user","isUserLoggedIn","currentUserReview","onReviewSubmit","onDeleteReview","navigate","useLocation","setSelectedRating","setReviewText","textareaRef","trimmedReviewText","trim","focus","handleSubmitReview","CreateReviewUrl","handleDeleteClick","handleSignInClick","SignInUrl","Typography","variant","CommandSentence","Container","template","AlreadyReviewed","Field","localeDate","LoadingSpinner","small","Button","Delete","ReviewThisProduct","StarRating","onChange","e","target","placeholder","ShareYourThoughtsHere","rows","PleaseFollowOur","ReviewGuidelinesLink","rel","ReviewGuidelines","AllPostedReviews","TermsOfServiceLink","TermsOfService","CanSeeThis","Everyone","disabled","SubmitReview","SignIn","ReviewHeader","reviewsTemplate","BasedOnSingleReview","BasedOnReviews","CustomerReviews","RatingOutOfMax","toFixed","String","classesByScale","sm","lg","LinkButton","ReviewItem","review","text","reviewRoutes","canDelete","DeleteReviewUrl","canFlag","FlagReviewUrl","handleFlagClick","SingleRating","Flag","ReviewsList","sortModes","SortModeSelector","sortMode","onSortModeChanged","sortModeLabels","latest","LatestFirst","earliest","EarliestFirst","ByRating","DropdownMenu","DropdownMenuTrigger","asChild","DropdownButton","DropdownMenuContent","DropdownMenuRadioGroup","onValueChange","mode","DropdownMenuRadioItem","Divider","REVIEWS_ANCHOR_ID","REVIEW_LIMIT_INCREMENT","product_reviews","Reviews","reviewsProps","setSortMode","reviewLimit","setReviewLimit","allReviews","setAllReviews","serverMayHaveMoreReviews","setServerMayHaveMoreReviews","setRatings","sortedReviews","sort","a","b","sortReviews","da","createdDate","db","slice","find","r","cancelled","loadedReviews","GetReviewsUrl","loadInitialReviews","refreshRatings","newRatings","GetRatingsUrl","refreshReviews","newReviews","handleDeleteReview","prev","filter","canReadMore","canReadLess","isLoadingMore","setIsLoadingMore","handleReadMoreClick","additionalReviews","concat","handleReadLessClick","LoadingReviews","WriteAReview","loading","ReadMore","ReadLess","c_amberVideoEmbedRegex","DisplayContent","html","rewritten","breakpointQuery","container","runContentScripts","scripts","Array","from","querySelectorAll","oldScript","newScript","document","createElement","attribute","attributes","setAttribute","hasAttribute","parentNode","replaceChild","executeScriptTagsInContainer","window","refTagger","tag","console","matchMedia","mediaQuery","handleChange","addEventListener","removeEventListener","addListener","removeListener","useExecuteContentScripts","dangerouslySetInnerHTML","__html","c_wistiaPlaylistScriptSrc","c_wistiaSingleScriptSrc","scriptAlreadyPresent","Boolean","querySelector","EmbeddedVideo","videoUrl","allowAutoplay","isWistiaUrl","includes","playlistMatch","wistiaPlaylistId","allowAttributeEntries","allowAttribute","wistiaPlaylistsScript","onload","playlistDetailsScript","appendChild","script","style","frameBorder","scrolling","allowFullScreen","allow","EmbeddedVideoSection","joinNodes","nodes","separator","flatMap","node","renderNamedLinks","items","item","searchUrl","formatSubject","subject","ProductDetailsMetadata","productDetailsMetadata","label","Title","authors","Authors","Author","edition","Edition","series","Series","volume","Volume","publishers","Publishers","Publisher","printPublicationYear","PrintPublicationDate","electronicPublicationYear","LogosReleaseDate","pageCount","Pages","era","Era","languages","Languages","Language","resourceCount","Resources","format","Format","formatType","subjects","Subjects","Subject","isbns","Isbns","Isbn","isbn","resourceId","ResourceId","resourceType","ResourceType","version","MetadataLastUpdated","row","AuthorBioSection","authorBio","SharedAuthorBio","bio","showMore","showLess","c_default","kind","c_singleVolume","c_collection","containedResourcesTitleKey","c_library","c_mobileEdSingleResource","c_mobileEdBundle","getSectionsForTemplate","AccordionHtmlTitle","c_noProductComponents","isRefetching","useNoProductComponents","product_content_sections","ProductContentSections","displayTemplate","useProductComponents","useContainedResourcesContext","isSignedIn","useCurrentUser","detailsResources","authorBioResources","templateKind","templateFetchesContainedResources","some","descriptor","productComponents","hasContainedResources","sections","isProductOwned","isOwnedByUser","descriptors","containedResourcesTitle","pendingAccordion","accordionGroupIndex","flushAccordion","Accordion","section","sectionIndex","AccordionItem","AccordionTrigger","AccordionContent","CoursesIncluded","ResourcesIncluded","productDetailsSection","content","ProductDetails","productDetailsContent","aboutName","authorSection","authorContent","hasContainedSection","c_innerConstraint","ContainedResources","defaultHideOwned","formatName","lastName","firstName","split","linkClassName","AttributeChips","chips","labelClassName","trailingContent","isMobile","useScreensize","open","setOpen","visibleChipCount","visibleChips","overflowChips","chip","i","AndMoreTooltip","Popover","onOpenChange","MoreTooltipText","ChevronDown","AuthorsAndPublishers","publisherMetadata","By","SalePricePopover","prices","triggerLabel","breakdownTriggerLabel","lines","breakdownLines","finalAmount","displayAmount","localizedDisplayAmount","SeePricingBreakdown","sideOffset","align","line","amount","displayInUsd","resolveAmount","isDeduction","Prices","isRestricted","discounts","discount","description","nonStackingDiscounts","shouldStack","stackingDiscounts","salePriceTemplate","renderDiscountPills","anchorPriceLines","savingsDescription","discountSavings","singularPeriodUnitResourceKey","day","month","year","pluralPeriodUnitResourceKey","SubscriptionPromotion","promotion","checked","freeTrialInfo","percentOff","subscribableProductTitle","TitleFormat","ProLevel","checkboxLabel","Fragment","AddFreeTrial","periodLength","periodUnit","getPeriodUnitText","SubscribeNow","savingsTemplate","StartFreeTrialForSavings","SubscribeForSavings","Checkbox","typography","LearnMore","as","QuantityUpdateButton","cartItemId","cartUpdateUrl","quantity","addToCartButtonResources","errorResources","isUpdating","setIsUpdating","isUpdatingRef","handleUpdate","eventAggregator","newCart","CartClient","updateCartAsync","quantityByCartItemId","order","analyticsTelemetry","dataLayer","dispatchEvent","CustomEvent","detail","cart","NotificationUtility","notify","errorOccurredDuringCartUpdate","updatingQuantity","updateQuantity","getPurchaseActionState","selectedSku","pricingData","hasTemporaryAccess","accessKind","hasPermanentAccess","isGeographicallyRestricted","isSellable","isPurchasable","canShowAddToCart","isGroupLicenseEscrow","openInLogosUrl","openInLogosBaseUrl","encodeURIComponent","canShowOpenInLogos","shouldRenderButtons","PurchaseActions","showGeoRestrictionMessage","showSubscriptionPromotion","addToCartButtonRef","openInLogosResources","subscriptionPromotion","useSubscriptionPromotion","isSubscriptionPromotionChecked","setIsSubscriptionPromotionChecked","subscribableProductOptionId","shouldAddSubscriptionToCart","supportsMultipleQuantity","isSubscription","allowsMultipleQuantity","selectedSkuPricingData","effectiveQuantity","cartQuantityUpdate","cartItems","identifier","IdentifierTypes","SKU","SPOID","showPromotion","AddToCartButton","buttonTextOverride","isPrepubProduct","preorder","OpenInLogosLinkText","Gallery","productName","Image","fetchPriority","targetAspectRatio","sizes","mobile","desktop","largeDesktop","ComingSoon","ResourceFormats","CollapsibleCallout","collapsedContent","expandText","collapseText","isExpanded","setIsExpanded","panelClass","X","VideoPopover","isModalOpen","onClose","Modal","isOpen","background","Header","padding","actions","UtilityButton","color","resourceGroupKey","calloutResourceFormats","hasResourceFormatCallout","resourceFormat","CalloutSummary","isEbook","isVerbum","EbooksCalloutSummary","Ebooks","LogosEditionsCalloutSummary","VerbumEditions","LogosEditions","EditionBadge","isReaderEdition","Ebook","VerbumEdition","LogosEdition","ReaderEdition","ResearchEdition","CalloutHeader","isLogosEditionCollection","ThisCollectionContainsLogosEditions","ThisResource","TwoTypesOfLogosEditionsHeading","TwoTypesOfLogosEditions","CalloutBody","EbooksCallout","LogosEditionsCallout","ResearchEditionsCallout","ResearchEditions","ReaderEditionsCallout","ReaderEditions","LearnMoreVideoButton","isVideoShown","setIsVideoShown","PlayIcon","LogosEditionCallout","logosEditionLearnMoreVideoUrl","isLogosEdition","toLowerCase","Close","__defProp","Object","defineProperty","__name","configurable","DIALOG_NAME","createDialogContext","createDialogScope","react_context_dist","A","DialogProvider","useDialogContext","Dialog","__scopeDialog","openProp","defaultOpen","modal","triggerRef","react","contentRef","react_use_controllable_state_dist","prop","defaultProp","caller","titleCount","setTitleCount","descriptionCount","setDescriptionCount","jsx_runtime","jsx","scope","contentId","react_id_dist","B","titleId","descriptionId","titlePresent","descriptionPresent","onOpenToggle","prevOpen","DialogTrigger","forwardedRef","triggerProps","context","composedTriggerRef","react_compose_refs_dist","s","react_primitive_dist","sG","button","getState","primitive_dist","mK","PORTAL_NAME","PortalProvider","usePortalContext","forceMount","DialogPortal","Children","child","react_presence_dist","C","present","react_portal_dist","Z","OVERLAY_NAME","DialogOverlay","portalContext","overlayProps","DialogOverlayImpl","Slot","react_slot_dist","TL","registerDismissableSurface","react_dismissable_layer_dist","e0","composedRefs","Combination","allowPinchZoom","shards","div","pointerEvents","CONTENT_NAME","DialogContent","contentProps","DialogContentModal","DialogContentNonModal","es2015","Eq","DialogContentImpl","trapFocus","disableOutsidePointerEvents","onCloseAutoFocus","event","preventDefault","onPointerDownOutside","originalEvent","ctrlLeftClick","ctrlKey","onFocusOutside","hasInteractedOutsideRef","hasPointerDownOutsideRef","defaultPrevented","onInteractOutside","targetIsTrigger","contains","onOpenAutoFocus","react_focus_guards_dist","Oh","react_focus_scope_dist","n","loop","trapped","onMountAutoFocus","onUnmountAutoFocus","qW","deferPointerDownOutside","onDismiss","DialogTitle","titleProps","react_use_layout_effect_dist","N","count","h2","DialogClose","closeProps","SeeInside","seeInsideIframeUrl","DialogPrimitive","VisuallyHidden","PreorderedProductLabel","orderDate","YouPreorderedOn","PreorderManagementPage","reconcilePurchaseQuantityWithSku","currentQuantity","Math","max","skuItemClassName","PurchaseSkuItemContent","formatDisplayName","restricted","PurchaseOptionSection","isSelected","showRadio","onSelect","Radio","isChecked","periodTypeOrder","SubscriptionPeriodType","Day","Month","Year","findChipForSkuId","skuId","c","otherSkuIds","QuantitySelector","onQuantityChange","StepperControl","min","GLE_MAX_QUANTITY","SkuSelector","purchaseOptions","selectedSkuId","isSalePriceVisible","purchaseQuantity","onPurchaseQuantityChange","onSelectedSkuChange","usePricing","pricingBySkuId","purchaseSkus","sku","subscriptionSkus","userPricingData","subscriptionInfo","indexOf","comparePeriodTypes","periodType","purchaseChips","logosEditionSkus","formatGroup","ebookSkus","otherSkus","mapSkuGroupToChips","chipId","supportsQuantitySelection","singlePurchaseSkus","gleSkus","representativeSku","handledSkuIds","Set","matchingGroupSkus","gle","add","has","buildPurchaseSkuChips","ambiguousFormatDisplayNames","counts","Map","set","lastSelectedPurchaseSkuIdRef","lastSelectedPurchaseSkuId","lastSelectedSubscriptionSkuIdRef","lastSelectedSubscriptionSkuId","selectedSkuPurchaseChip","lastSelectedSkuPurchaseChip","shouldShowQuantitySelector","handleChipClick","isPurchaseSkuSelected","isSubscriptionSkuSelected","handleSubscriptionSkuChange","getPurchaseSkuItemContent","displaySkuId","purchaseSkuChipContent","RadioGroup","purchaseSkuContent","Tooltip","newQuantity","subscriptionSkuContent","selectedSubscriptionSku","pricingForSelectedSubscriptionSku","subscriptionDisplayPrice","selectValue","periodDisplay","shouldHidePrice","options","price","Select","option","isSearchable","onFocus","purchaseOptionSections","firstChip","showRadioOptions","CommerceWebThemeProvider","purchaseOptionSection","purchaseOption","MetadataRow","publicationPeriod","PublicationPeriod","IsbnLabel","ReviewSummary","ratingSummary","headerHeight","setHeaderHeight","numberOfReviews","hasReviews","getHeaderHeight","header","getBoundingClientRect","handleResize","handleLogosBannerClosed","setTimeout","reviewsHref","handleScrollToReviews","reviewsElement","getElementById","rect","scrollTo","top","scrollY","behavior","history","pushState","shouldDisplayLinkToReviews","BeTheFirstToRateThis","ProductDescription","descriptionHtml","showFullDescription","setShowFullDescription","isTruncatable","setIsTruncatable","scrollHeight","clientHeight","buttonLabel","ProductDescriptionToggle","toggleDescription","Details","pricingSidebarResources","perUserSkuData","isSkuSellable","isSkuPurchasable","productWishlistData","useProductInWishList","explanation","isBlockedFromPurchase","YouCanDistribute","YouAlreadyOwnThisProduct","YouHaveTemporaryAccess","ProductNotAvailableInYourRegion","userCountryOrRegionIsTradeSanctioned","UserCountryOfacSanctioned","isAcademicallyRestricted","ProductOnlyAvailableForAcademicProgramMembers","UnavailableToPurchase","hasPreorder","prepubProductStatusSummary","PrepubProductStatusSummary","AddToWishListWithForm","sticky_add_to_cart_bar","StickyAddToCartBar","isVisible","inert","StickyAddToCartContent","shouldRenderActionSection","sticky_add_to_cart","StickyAddToCart","registerAdzone","adzone_block","AdzoneBlock","adzone","contentSourceKind","RenderBuilderContent","builderIo","TimeSensitiveCalloutBlock","TimeSensitiveCallout","PlatformExplainerHeader","hasCheckedDismissedCookie","setHasCheckedDismissedCookie","isDismissed","setIsDismissed","Cookies","PlatformExplainerHeaderMobile","PlatformExplainerHeaderDesktop","AnEbookAndSoMuchMore","DiscoverConnectionsWithLogos","CloseButton","closeComponent","secure","path","expires","Breadcrumbs","crumbs","crumb","nextCrumb","isCurrentPageCrumb","isCurrentPageSeparator","c_title","BusinessDeskEditLink","userInfo","businessDeskEditUri","isEmployee","Pencil","Keyboard","swiper","extendParams","on","emit","ssr_window_esm","g","handle","enabled","rtlTranslate","rtl","kc","keyCode","charCode","pageUpDown","keyboard","isPageUp","isPageDown","isArrowLeft","isArrowRight","isArrowUp","isArrowDown","allowSlideNext","isHorizontal","isVertical","allowSlidePrev","shiftKey","altKey","metaKey","activeElement","isContentEditable","nodeName","onlyInViewport","inView","utils","el","slideClass","slideActiveClass","swiperWidth","clientWidth","swiperHeight","windowWidth","innerWidth","windowHeight","innerHeight","swiperOffset","f","left","scrollLeft","swiperCoord","speed","returnValue","slideNext","slidePrev","enable","disable","assign","SamplePages","imageUrls","initialSlide","setInitialSlide","setIsOpen","Swiper","modules","Scrollbar","scrollbar","draggable","dragClass","dragSize","slidesPerView","spaceBetween","imageSrc","SwiperSlide","SamplePagesThumbnailAlt","belowTheFold","SamplePagesViewer","onSlideChange","activeIndex","SamplePagesSlideImage","LeftColumn","samplePageImageUrls","ShimmerInline","LibraryGreeting","userName","isPricingLoading","isUnownedLoading","unownedData","headers","then","ok","Error","catch","useUnownedResources","greetingText","primarySkuPrices","primarySku","priceDisplay","LibraryResourcesYouDontOwn","LibraryAddByGetting","part","arr","mapSkuData","localizedCurrencyCode","anchorSavings","hasBeenPreordered","mapLocalizedPrice","mapBreakdownLines","mapAnchorPriceLines","deliveryMethod","displayAmountByCurrency","displayAmountCurrencyCode","currencyCode","mapSkuPricesToProductPricingData","skusRecord","ProductDetailsPageCore","showUserGreeting","handleSelectedSkuChange","handlePurchaseQuantityChange","setSelectedSku","setPurchaseQuantity","alternateSkuIds","allSkusToCheck","matchingSku","nextSelectedSku","prevQuantity","clampedQuantity","useSelectedSkuAndPurchaseQuantity","setSeeInsideIframeUrl","fetchSeeInsideUrl","useSeeInsideUrl","allowsSeeInside","intersectionTargetRef","isStickyAddToCartVisible","useStickyAddToCartHandler","setIsStickyAddToCartVisible","intersectionTarget","setIntersectionTarget","entries","root","isCurrentUserLoading","sourceToken","Products","TimeSensitiveCallOut","product_details_page","preferredCurrency","initialPricingData","EventsTrackingContextProvider","algoliaEventsTrackingSettings","queryId","PerUserDataContextProvider","BuilderComponentsContextProvider","priceFormatGettersByBillingMode","Monthly","getLocalizedPriceFormat","MonthlyPriceFormat","getPriceFormat","Annually","AnnualPriceFormat","freeTrialPeriodUnitTextGettersByUnit","DayPeriodUnit","DaysPeriodUnit","MonthPeriodUnit","MonthsPeriodUnit","YearPeriodUnit","YearsPeriodUnit","customSubscriptionResources","defaultSubscriptionResources","subscriptionPlansResources","getFreeTrialPeriodUnitText","availableSubscriptionLevelsFormatter","Intl","ListFormat","localizedPriceFormat","freeTrialPeriodUnitText","level","Subscriptions","Subscription","arguments","source","api","init","converter","defaultAttributes","Date","now","toUTCString","decodeURIComponent","escape","stringifiedAttributes","attributeName","cookie","write","create","cookies","jar","parts","found","read","_e","remove","withAttributes","this","withConverter","freeze","Heart"],"sourceRoot":""}