站点详情页(跳转前展示目标站点 TDK 信息)
icon

CGTrader - 3D Models And 3D Printing Marketplace

www.cgtrader.com
Explore 2M+ 3D models online for print, game, VR/AR & design projects. Download, customize, or hire 3D experts - all on CGTrader.
关键词:176977842455249" property="fb:app_id" />.btn{padding:.5rem 1.5rem;font-size:1rem;line-height:1.5;border-radius:3px;display:inline-block;text-align:center;text-decoration:none;white-space:nowrap;vertical-align:middle;border:0 solid transparent}.btn-primary{color:#fff;background-color:#41a48f}.btn-sm{padding:.25rem 1rem;font-size:.875rem;line-height:1.5;border-radius:2px}.notice{font-size:.875rem;position:fixed;bottom:42px;left:0;z-index:448;width:100%;background-color:#3f444c;padding:20px 30px;color:#fff;text-align:left}.notice .btn{display:block;width:100px;margin:15px auto 0}.notice .notice-content{position:relative}.notice .close-notice{position:absolute;top:-5px;right:-15px}@media (min-width: 576px){.notice{bottom:0;padding:10px 25px;text-align:center}.notice .btn{display:inline-block;margin:0 0 0 15px}.notice .close-notice{top:0;right:-10px}}.link--darker{color:#19bcc9}.timer-strip{background-color:#159ca9;padding:1.25rem;text-align:center;color:#fff;letter-spacing:.5px}.timer-strip.is-secondary-color{background:linear-gradient(90.05deg, #a91e4c 0, #cc2795 52.4%, #a91e4a 100%)}.timer-strip .timer-row{line-height:2}.timer-strip .timer-strip__item{display:inline-flex;height:24px;vertical-align:middle;line-height:24px;font-size:16px;font-weight:600}.timer-strip .timer-strip__item:first-child{padding-left:0}.timer-strip .timer-strip__item .big-text{font-size:2.5rem;line-height:24px;letter-spacing:1px;font-weight:600}@media (min-width: 968px){.timer-strip .timer-strip__item .big-text{font-weight:800}}.timer-strip .timer-strip__item--info{font-size:16px}@media (min-width: 640px){.timer-strip .timer-strip__item--info{font-size:20px}}.timer-strip--top-bar{width:100%;height:42px;z-index:500;text-decoration:none}.timer-strip--top-bar .timer-strip{font-size:1rem;padding:7px 0}.timer-strip--top-bar .timer-strip .timer-row{display:flex;align-items:center;justify-content:center;gap:32px;line-height:24px}@media (max-width: 340px){.timer-strip--top-bar .timer-strip .timer-row{gap:0;justify-content:space-between;padding-inline:5px}}.timer-strip--top-bar .timer-strip .big-text{font-size:1.0625rem;line-height:24px}.timer-strip--top-bar .timer-strip .timer-strip__item--text{font-weight:600;font-size:16px}.timer-strip--top-bar .timer-strip .timer-strip__item--content{display:none}@media (min-width: 968px){.timer-strip--top-bar .timer-strip .timer-strip__item--content{display:inline-flex}}.timer-strip--top-bar .timer-strip .timer-strip__item--button{height:28px;color:#097b95;background-color:#fff;border:none}.timer-strip--top-bar .timer-strip .timer-strip__item--time{display:none;background:rgba(255,255,255,0.16);border-radius:2px;padding:0 10px}@media (min-width: 640px){.timer-strip--top-bar .timer-strip .timer-strip__item--time{display:inline-flex;border:none}}.timer-strip--top-bar .timer-strip .timer-strip__item--info{font-weight:600}.timer-strip{background-color:#159ca9;padding:1.25rem;text-align:center;color:#fff;letter-spacing:.5px}.timer-strip.is-secondary-color{background:linear-gradient(90.05deg, #a91e4c 0, #cc2795 52.4%, #a91e4a 100%)}.timer-strip .timer-row{line-height:2}.timer-strip .timer-strip__item{display:inline-flex;height:24px;vertical-align:middle;line-height:24px;font-size:16px;font-weight:600}.timer-strip .timer-strip__item:first-child{padding-left:0}.timer-strip .timer-strip__item .big-text{font-size:2.5rem;line-height:24px;letter-spacing:1px;font-weight:600}@media (min-width: 968px){.timer-strip .timer-strip__item .big-text{font-weight:800}}.timer-strip .timer-strip__item--info{font-size:16px}@media (min-width: 640px){.timer-strip .timer-strip__item--info{font-size:20px}}.timer-strip--top-bar{width:100%;height:42px;z-index:500;text-decoration:none}.timer-strip--top-bar .timer-strip{font-size:1rem;padding:7px 0}.timer-strip--top-bar .timer-strip .timer-row{display:flex;align-items:center;justify-content:center;gap:32px;line-height:24px}@media (max-width: 340px){.timer-strip--top-bar .timer-strip .timer-row{gap:0;justify-content:space-between;padding-inline:5px}}.timer-strip--top-bar .timer-strip .big-text{font-size:1.0625rem;line-height:24px}.timer-strip--top-bar .timer-strip .timer-strip__item--text{font-weight:600;font-size:16px}.timer-strip--top-bar .timer-strip .timer-strip__item--content{display:none}@media (min-width: 968px){.timer-strip--top-bar .timer-strip .timer-strip__item--content{display:inline-flex}}.timer-strip--top-bar .timer-strip .timer-strip__item--button{height:28px;color:#097b95;background-color:#fff;border:none}.timer-strip--top-bar .timer-strip .timer-strip__item--time{display:none;background:rgba(255,255,255,0.16);border-radius:2px;padding:0 10px}@media (min-width: 640px){.timer-strip--top-bar .timer-strip .timer-strip__item--time{display:inline-flex;border:none}}.timer-strip--top-bar .timer-strip .timer-strip__item--info{font-weight:600}.chatbot-button{display:flex;justify-content:center;align-items:center;position:fixed;bottom:3rem;right:1rem;width:50px;height:50px;border-radius:25px;background-color:#46a9b4;box-shadow:rgba(0,0,0,0.2) 0 4px 8px 0;z-index:2147483645;left:unset;transform:scale(1)}@media (min-width: 576px){.chatbot-button{bottom:1rem}}html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}h1{margin:.67em 0;font-size:2em}a{background-color:transparent}strong{font-weight:bolder}img{border-style:none}button,input{margin:0;font-family:inherit;font-size:100%;line-height:1.15}button,input{overflow:visible}button{text-transform:none}button{-webkit-appearance:button}button::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring{outline:1px dotted ButtonText}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}.is-hidden{display:none !important}body{display:flex;position:relative;right:0;background:#f4f6f7;font-size:16px;line-height:22px;flex-direction:column;overflow-x:hidden}body,h1,h2,h3,input{font-family:"Source Sans Pro",Helvetica,sans-serif}h1{font-size:36px}h2{font-size:27px}h3{font-size:24px}h1,h2,h3{margin-bottom:20px;font-weight:300}p{margin:0 0 20px}a{color:#19bcc9}img{max-width:100%}html{box-sizing:border-box}*,::after,::before{box-sizing:inherit}body{margin:0;background-color:rgba(30,39,50,0.02);color:#1e2732;font-family:"Source Sans Pro",Helvetica,Arial,sans-serif;font-size:16px;font-weight:400;line-height:24px}img{max-width:100%}input{font-family:inherit}.container-fixed{width:100%;padding-right:20px;padding-left:20px;margin-right:auto;margin-left:auto}@media (min-width: 640px){.container-fixed{padding-right:40px;padding-left:40px}}@media (min-width: 960px){.container-fixed{max-width:840px}}@media (min-width: 1280px){.container-fixed{max-width:1104px}}@media (min-width: 1600px){.container-fixed{max-width:1392px}}@media (min-width: 1920px){.container-fixed{max-width:1680px}}.cgt-heading-h2{font-size:28px;line-height:36px;margin:0;color:#1e2732;letter-spacing:normal;font-style:normal;font-weight:600}.cgt-heading-h3{font-size:24px;line-height:32px;margin:0;color:#1e2732;letter-spacing:normal;font-style:normal;font-weight:600}.cgt-heading-h4{font-size:20px;line-height:28px;margin:0;color:#1e2732;letter-spacing:normal;font-style:normal;font-weight:600}.cgt-heading-h5{font-size:20px;line-height:28px;margin:0;color:#1e2732;letter-spacing:normal;font-style:normal;font-weight:600;font-weight:600}.cgt-heading-h6{font-size:16px;line-height:24px;margin:0;color:#1e2732;letter-spacing:normal;font-style:normal;font-weight:600}@media (min-width: 964px){.cgt-heading-h2{font-size:40px;line-height:48px}.cgt-heading-h3{font-size:32px;line-height:44px}.cgt-heading-h4{font-size:24px;line-height:32px}}.cgt-text-default{color:#1e2732;font-style:normal;font-weight:400;font-size:16px;line-height:24px}.cgt-avatar--24{color:#1e2732;font-style:normal;font-size:12px;font-weight:600;line-height:16px}.cgt-icon--default{width:40px;height:40px}.cgt-icon--dark .fillable{fill:rgba(30,39,50,0.6)}.cgt-icon__icon{display:flex;margin-right:4px;border-radius:50%;justify-content:center;align-items:center}.cgt-icon--not-spaced{margin-right:0}.cgt-button{display:inline-block;height:40px;margin:0;border:0;border-radius:6px;padding:8px 12px;font-size:16px;font-weight:600;text-align:center;text-decoration:none;text-transform:none;font-family:inherit;align-items:center;line-height:24px}.cgt-button>svg{display:inline-block;font-size:20px;line-height:24px;transform-origin:calc(50% + 4px) 50%;vertical-align:middle}.cgt-button>svg+span{vertical-align:middle}.cgt-button>span{display:inline-block;padding:0 12px}.cgt-button--primary{border:1px solid #19bcc9;background-color:#19bcc9;color:#fff}.cgt-button--secondary{border:1px solid rgba(30,39,50,0.12);background-color:transparent;color:rgba(30,39,50,0.8)}.cgt-button--ghost{border:1px solid transparent;background-color:transparent;color:rgba(30,39,50,0.8)}.cgt-button *>svg,.cgt-button>div{width:auto;margin-right:0}.cgt-button *>.fillable{fill:currentColor !important}.cgt-button--small{height:32px;padding:4px 8px;font-size:14px;line-height:20px}.cgt-button--small>svg{font-size:20px;line-height:20px}.cgt-button--small>span{padding:0 8px}.cgt-button--with-icon{position:relative;line-height:initial}.cgt-button--with-icon{display:flex}.cgt-button--only-icon{position:relative;padding:8px;align-items:baseline;line-height:initial}.cgt-button--only-icon:not(.cgt-button--width-expand){width:40px}.cgt-button--only-icon *>svg,.cgt-button--only-icon>div{height:100%}.cgt-avatar{display:flex;position:relative;overflow:hidden;border-radius:50%;background-repeat:no-repeat;background-size:cover;text-transform:uppercase;align-items:center;justify-content:center;vertical-align:middle;-webkit-font-smoothing:antialiased}.cgt-avatar--24{width:24px;height:24px}.cgt-avatar--color{color:#fff !important;box-shadow:inset 0 0 0 1px rgba(30,39,50,0.12)}.cgt-avatar__image{position:absolute;top:50%;left:0;width:100%;height:100%;object-fit:cover;transform:translateY(-50%)}.cgt-slider-wrapper.with-slider-on-top .cgt-slider__left-input{grid-area:left-input;justify-self:start;width:84px}.cgt-slider-wrapper.with-slider-on-top .cgt-slider--dual{grid-area:slider;margin-bottom:24px;width:calc(100% - 16px)}.cgt-slider-wrapper.with-slider-on-top .cgt-slider__right-input{grid-area:right-input;justify-self:end;width:84px}.cgt-text-input{display:flex;align-items:center;position:relative;border-radius:6px;background-color:#fff;line-height:24px;box-shadow:inset 0 0 0 1px rgba(30,39,50,0.12)}.cgt-text-input>*{font-size:16px}.cgt-text-input input{flex-grow:1;max-width:100%;border:none;outline:0;color:#1e2732;font-family:"Source Sans Pro",Helvetica,Arial,sans-serif;font-style:normal;appearance:none;order:4;background-color:unset}.cgt-text-input .trail-button{order:8}.cgt-text-input--medium{height:40px;padding:8px 8px}.app-nav{margin:0;padding:0;list-style:none}.uppercased-text{text-transform:uppercase}.app-nav{display:none;position:absolute;left:4px;z-index:500;width:calc(100% - 8px);overflow:auto;border-radius:6px;background-color:#fff;box-shadow:0 4px 4px rgba(30,39,50,0.04),0 1px 8px rgba(30,39,50,0.04),0 2px 4px rgba(30,39,50,0.04),0 0 0 4px rgba(30,39,50,0.04),inset 0 0 0 1px rgba(30,39,50,0.12);flex-direction:row;align-items:flex-start;flex-flow:column;gap:0}@media (min-width: 960px){.app-nav{max-width:624px}}@media (min-width: 1280px){.app-nav{height:100%}}.app-nav__item{width:100%}.app-nav__item-name{font-size:16px;line-height:24px;margin:0;color:#1e2732;letter-spacing:normal;font-style:normal;font-weight:600}.app-nav__item-link{padding:8px 6px;min-height:56px;white-space:nowrap;color:#1e2732}.app-nav__item{position:relative;justify-content:center;align-items:center;width:100%}.app-nav__item:last-of-type{border-bottom:0}@media (min-width: 640px){.app-nav{left:8px;width:auto;flex-flow:row;flex-wrap:wrap;gap:0;width:320px;box-shadow:0 4px 16px rgba(30,39,50,0.04), 0 6px 8px rgba(30,39,50,0.04), 0 8px 12px rgba(30,39,50,0.04), 0 0 0 8px rgba(30,39,50,0.04), inset 0 0 0 1px rgba(30,39,50,0.12)}}@media (min-width: 960px){.app-nav__item-link{min-height:auto}}@media (min-width: 960px){.app-nav.new_navbar_ui{display:flex;position:relative;top:auto !important;left:auto;width:auto;max-width:none;overflow:visible;border-radius:none;background:0 0;flex-flow:row;box-shadow:none}.app-nav.new_navbar_ui .app-nav__trigger-mobile{display:none}.app-nav.new_navbar_ui .app-nav__item{display:flex;width:auto;height:100%;border-bottom:none}.app-nav.new_navbar_ui #navigation-community,.app-nav.new_navbar_ui #navigation-jobs{display:none}}@media (min-width: 1280px){.app-nav.new_navbar_ui #navigation-community,.app-nav.new_navbar_ui #navigation-jobs{display:flex}}[class*=" icon-"]:before{font-family:fontello;font-style:normal;font-weight:400;speak:never;display:inline-block;text-decoration:inherit;width:1em;margin-right:.2em;text-align:center;font-variant:normal;text-transform:none;line-height:1em;margin-left:.2em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.custom-icon--light{color:rgba(30,39,50,0.6)}.icon-arrow-right:before{content:'\e808'}.custom-font-icon{width:24px;height:24px}.custom-font-icon::before{margin:0;font-size:24px}.popover{display:none;opacity:0;position:fixed;right:4px;bottom:8px;left:4px;background-color:#fff;border-radius:6px;box-shadow:0 0 0 4px rgba(30,39,50,0.04),0 2px 4px 0 rgba(30,39,50,0.04),0 1px 8px 0 rgba(30,39,50,0.04),0 4px 4px 0 rgba(30,39,50,0.04),inset 0 0 0 1px rgba(30,39,50,0.12);z-index:451}@media (min-width: 640px){.popover{left:auto;bottom:auto;width:400px;right:8px}}.popover-content{overflow-y:auto;overflow-x:visible;color:#3f444c}.wayfinder-container{height:80px}.wayfinder-container.with-bar{height:122px}.wayfinder-container.with-bar .wayfinder{display:flex;flex-flow:column;justify-content:flex-end}@media (min-width: 640px){.wayfinder-container{height:96px}.wayfinder-container.with-bar{height:138px}}@media (min-width: 960px){.wayfinder-container{height:48px}.wayfinder-container.with-bar{height:90px}}@media (min-width: 1280px){.wayfinder-container{height:56px}.wayfinder-container.with-bar{height:98px}}.wayfinder{position:fixed;top:0;left:0;z-index:453;width:100%;background-color:#fff;height:80px}.wayfinder .app-nav{top:calc(80px + 8px);max-height:calc(100dvh - 88px)}@media (max-width: 1279.98px){.wayfinder .app-nav{top:calc(80px + 2px);max-height:calc(100dvh - 82px)}}.wayfinder__image-search-wrapper{position:relative}.wayfinder.with-bar{height:122px}.wayfinder.with-bar .app-nav{top:calc(122px + 8px);max-height:calc(100dvh - 130px)}@media (max-width: 1279.98px){.wayfinder.with-bar .app-nav{top:calc(122px + 2px);max-height:calc(100dvh - 124px)}}.wayfinder.with-bar .mobile-curtains{top:122px}.wayfinder.with-bar .wayfinder__container{height:calc(100% - 40px)}.wayfinder__container{display:flex;width:100%;height:100%;flex-wrap:wrap;background-color:#fff}.wayfinder__item,.wayfinder__logo{height:50%;display:flex;justify-content:center;align-items:center}.wayfinder__logo{width:36px}.wayfinder__search{position:relative;order:9;width:100%;height:50%;border:1px solid rgba(30,39,50,0.12);display:flex;justify-content:center;align-items:center}.wayfinder__search .cgt-button{height:calc(100% - 8px);margin-right:4px}.wayfinder__form{width:100%;height:100%;display:flex;display:flex;justify-content:center;align-items:center}.wayfinder__search-input{width:100%;height:100%;padding:8px 12px;border:none;font-size:16px}.wayfinder__search-button{width:52px !important}.wayfinder__search-button svg{width:24px;height:24px}.wayfinder__action-icon-svg .fillable{fill:rgba(30,39,50,0.8)}.wayfinder .hamburger{z-index:1;margin-left:0;margin-top:0;width:48px;min-width:48px;height:50%;display:flex;justify-content:center;align-items:center;border:1px solid rgba(30,39,50,0.12);border-bottom:none}.wayfinder .hamburger .hamburger-box,.wayfinder .hamburger .hamburger-inner{z-index:0}.wayfinder .hamburger .hamburger-box{position:relative;display:inline-block;width:18px;height:12px}.wayfinder .hamburger .hamburger-box .hamburger-inner{top:50%;display:block;margin-top:-2px}.wayfinder .hamburger .hamburger-box .hamburger-inner,.wayfinder .hamburger .hamburger-box .hamburger-inner:after,.wayfinder .hamburger .hamburger-box .hamburger-inner:before{position:absolute;width:18px;height:2px;border-radius:1px;background-color:rgba(30,39,50,0.8)}.wayfinder .hamburger .hamburger-box .hamburger-inner:after,.wayfinder .hamburger .hamburger-box .hamburger-inner:before{display:block;content:''}.wayfinder .hamburger .hamburger-box .hamburger-inner:after{bottom:-5px}.wayfinder .hamburger .hamburger-box .hamburger-inner:before{top:-5px}.wayfinder .cgt-button.cgt-button--rectangular{height:100%;border-radius:0}.wayfinder .mobile-curtains{position:fixed;display:none;opacity:0;top:80px;right:0;left:0;bottom:0;background-color:rgba(0,0,0,0.5);mix-blend-mode:normal;backdrop-filter:blur(2px);width:100%;z-index:450;animation:showCurtains .5s}@keyframes showCurtains{from{opacity:0}to{opacity:100%}}.wayfinder__actions{display:flex;flex-flow:row;height:50%;flex-grow:1;justify-content:flex-end;align-items:center}.wayfinder__actions-list{height:100%;margin:0;padding:0;list-style:none;display:flex;flex-flow:row;justify-content:center;align-items:center}.wayfinder__action{height:100%}.wayfinder__action-link,.wayfinder__image-search{width:100%;height:100%;padding:0 12px;display:flex;justify-content:center;align-items:center}.wayfinder__image-search{border-right:1px solid rgba(30,39,50,0.12);max-width:47px}.wayfinder__action-icon{position:relative;display:block}.wayfinder__action-icon .cgt-icon{width:100%}.wayfinder__user-section{padding:4px;gap:4px;height:100%;height:100%;display:flex;justify-content:center;align-items:center}.wayfinder__user-section .cgt-button{height:100%}.wayfinder__user-section .cgt-button{padding:8px;white-space:nowrap;display:flex}.wayfinder__user-section .cgt-button span{padding:0 8px}.wayfinder__user-section .cgt-button.blue-button{background-color:#0c1015;border-color:#0c1015}.wayfinder .app-nav .app-nav__item .cgt-button:not(.actions-bar__link){border-top:none}@media (min-width: 390px){.wayfinder__logo--signed-out{width:auto;margin-left:6px}}@media (min-width: 640px){.wayfinder{height:96px}.wayfinder .mobile-curtains{top:96px}.wayfinder .app-nav{top:calc(96px + 8px);max-height:calc(100dvh - 104px)}.wayfinder.with-bar{height:138px}.wayfinder.with-bar .mobile-curtains{top:138px}.wayfinder.with-bar .app-nav{top:calc(138px + 8px);max-height:calc(100dvh - 146px)}.wayfinder__logo{margin:0 12px;width:auto;min-width:100px}.wayfinder__action-link,.wayfinder__image-search{padding:0 16px}.wayfinder__user-section .cgt-button{padding:12px;white-space:nowrap;display:flex}.wayfinder__user-section .cgt-button span{padding:0 12px}.wayfinder__search-button{width:72px !important}}@media (min-width: 960px){.wayfinder{height:48px}.wayfinder .wayfinder__container{border-bottom:1px solid rgba(30,39,50,0.12)}.wayfinder .mobile-curtains{top:48px}.wayfinder .app-nav{top:calc(48px + 8px);max-height:calc(100dvh - 56px)}.wayfinder.with-bar{height:90px}.wayfinder.with-bar .mobile-curtains{top:90px}.wayfinder.with-bar .app-nav{top:calc(90px + 8px);max-height:calc(100dvh - 98px)}.wayfinder__logo{width:auto;margin:0 16px}.wayfinder__container{flex-wrap:nowrap}.wayfinder__actions,.wayfinder__item,.wayfinder__logo{height:100%}.wayfinder__search{order:0;height:100%;border-top:none;border-bottom:none}.wayfinder .app-nav .app-nav__item .cgt-button:not(.actions-bar__link){border-top:none;border-bottom:none;border-left:none}}@media (min-width: 1280px){.wayfinder{height:56px}.wayfinder .mobile-curtains{display:none;top:56px}.wayfinder .app-nav{top:calc(56px + 8px);max-height:calc(100dvh - 64px)}.wayfinder.with-bar{height:98px}.wayfinder.with-bar .mobile-curtains{top:98px}.wayfinder.with-bar .app-nav{top:calc(98px + 8px);max-height:calc(100dvh - 106px)}.wayfinder .hamburger{display:none}.wayfinder__logo{margin:0 20px}.wayfinder__action-link,.wayfinder__image-search{padding:0 20px}.wayfinder__image-search{max-width:none}.wayfinder__search-button{width:88px !important}}@media (max-width: 1279.98px){.wayfinder-container.wayfinder-container--without-mobile-search{height:40px}.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder{height:48px}.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder .app-nav{top:calc(40px + 10px);max-height:calc(100dvh - 50px)}.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder .mobile-curtains{top:48px}.wayfinder-container.wayfinder-container--without-mobile-search.with-bar{height:82px}.wayfinder-container.wayfinder-container--without-mobile-search.with-bar .wayfinder{height:90px}.wayfinder-container.wayfinder-container--without-mobile-search.with-bar .wayfinder .wayfinder__container{height:calc(100% - 42px)}.wayfinder-container.wayfinder-container--without-mobile-search.with-bar .wayfinder .app-nav{top:calc(82px + 10px);max-height:calc(100dvh - 92px)}.wayfinder-container.wayfinder-container--without-mobile-search.with-bar .wayfinder .mobile-curtains{top:90px}.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder__search{display:none}.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder .wayfinder__container>.hamburger,.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder .wayfinder__container>.wayfinder__actions,.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder .wayfinder__container>.wayfinder__logo{height:100% !important}}@media (min-width: 960px){.wayfinder-container.wayfinder-container--without-mobile-search{height:48px}.wayfinder-container.wayfinder-container--without-mobile-search.with-bar{height:90px}.wayfinder-container.wayfinder-container--without-mobile-search.with-bar .wayfinder{height:90px}.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder__search{display:flex}.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder__item,.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder__logo{height:50%}.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder__actions{height:50%}}@media (min-width: 1280px){.wayfinder-container.wayfinder-container--without-mobile-search{height:56px}.wayfinder-container.wayfinder-container--without-mobile-search.with-bar{height:98px}.wayfinder-container.wayfinder-container--without-mobile-search.with-bar .wayfinder{height:98px}.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder .wayfinder__container>.hamburger,.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder .wayfinder__container>.wayfinder__actions,.wayfinder-container.wayfinder-container--without-mobile-search .wayfinder .wayfinder__container>.wayfinder__logo{height:100% !important}}.wayfinder__action-link{flex-direction:row;align-items:center;text-decoration:none;gap:8px}.btn{display:inline-block;border:0 solid transparent;border-radius:3px;padding:.5rem 1.5rem;font-size:1rem;line-height:1.5;text-align:center;text-decoration:none;white-space:nowrap;vertical-align:middle}.btn-primary{background-color:#159ca9;color:#fff}.btn-sm{padding:.25rem 1rem;font-size:.875rem;line-height:24px;border-radius:2px;border-radius:4px}.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-exclamation-triangle:before{content:"\f071"}.fa-times:before{content:"\f00d"}.fa-unlock-alt:before{content:"\f13e"}.far{font-family:"Font Awesome 5 Pro";font-weight:400}.fas{font-family:"Font Awesome 5 Pro Solid";font-weight:900}[class*=" icon-"]:before{font-family:fontello;font-style:normal;font-weight:400;speak:never;display:inline-block;text-decoration:inherit;width:1em;margin-right:.2em;text-align:center;font-variant:normal;text-transform:none;line-height:1em;margin-left:.2em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.custom-icon--light{color:rgba(30,39,50,0.6)}.icon-arrow-right:before{content:'\e808'}.custom-font-icon{width:24px;height:24px}.custom-font-icon::before{margin:0;font-size:24px}.responsive-footer__logo{width:80px;height:20px;margin-bottom:32px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAAAyCAQAAACzWFxqAAAABGdBTUEAALGPC%2FxhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA%2F4ePzL8AAAvdSURBVHja7ZtnlJXFGYBnKSsgIGUpAi5FECliQSygCYaDAUQQggcRkyBEPRqIJRgTMIAGYxCVBNAjNhSMoihwVlSiiXiIgiAEAfeEIgtIZynLwrZ7v3mf%2FNhbZr5yy7KEP3e%2BP3v2m2%2FK%2B8zM2%2BYqlSk%2BhfrObXqu7JQdehaDqZORyLkG8iRmmZiRyDkuzisgkQd4PiORc1z0SxaQmRmJZID8n87m8youC99Ef37ClYUNMkDONY668g9CEUWp2UyrDJBzCyRHjhGfJlyVAXJugTSVQ3EgorkiAyQDJAMkA%2BTMBZdNSzrRhbbUT6F2TRrTilY0pnZSpX7QAtI5rVE1oRtdyQkcRTM60oMedKYVddNot05ZbsVlXEYbalYNCOeTS%2FfQ5XSmZTIZ%2BH7foKIL3Wnh96oZv%2BQd8uWYlEmFFMsuWc6EstxAEd3Jm7JRDsgJOSEHZLN8wHSm6SfiD1OZoqfqqfoJ%2FQTPyOn4REX0vFitKXSNtZrFAGbzDov0q85YspVSivb6FfZJiAoO8i5NrVF05j4WykY5LKXiiCPlclx2sJxHkwOnH6%2FxXzkpYQlzgvV6Cq3TAVJ6Eb%2BWPNkpxRIWR8rlmGzhDYZTL6C%2F63iWt%2FW7ej4PVi52cphJAeUSppAVtLPWr36MH%2FApUqifcu8VaukJFJB2EeOx%2Fv9%2BfL3IAePFFUqFb3KNa2ikZg2Gs0JKAjsrZq4NzyzlF8tSn%2FHtc8YqxQvJgdBY%2F5kjAT1%2FywifL7JYa9QZrBTd2Wx%2Bpp%2BMV27LSrfATMHJ%2B9Qymr5APgiqXZUHZD1ZkbYbyX7iwLpzvZzAquuMrdyfkueF7AH%2BTeWa9winl%2Bz2%2BxZAz9SvJwMSulK%2BDe4bQM8yJRYB8o1h9g%2BkA7vsmekN0aq58h2JBVZe3iHWcG1Zgs9KPyMgm6InOI1kXxSIhBgpu9z7St%2BrlFL6MW%2BffgKWj92CUaqsvexJJEwplYRA6MmBxBIA4K8eIOsM0GNkjXtmsiMS0JDPExwmlVUl1DOm8h7AHv4xNpMvJ9OHYvSyxtgh%2B2LthKK7xfpmnFJK8QY%2Bo%2FU9GIe4BFND8oLm6wXrBUJz2eaSQJHky2Y5aPYN4NwRCES8SwLku0oBP%2BRmK%2FtZpufphbJWQtGBhnpFmm0oO42Bl%2BvJtKYW2bRnuoSNDiSxoFyvZ8SGbQLBV%2Bi3K6UUrxIdbRmr9J%2B4Pdw33Ds8gIlstOcji13B9Vt8cBTIfwIPMTeQedb4ivk9bcmmVnGOM5wt1rvtNAjcIT4z03MqvYO91jBEz6B5TG324i0BJMylkf8NNBvVD1tDnWKgOsRg%2BlrPEDlumr3O3dwQeXpzvj%2BQWO3TvKUnMZfNcriii1JKMTGydJ6mu9uM5BNrjLtNk4QsWeECtoMhNKAGDRnCBpIACV0h5Zjjutnqu7Vr94wKAhKrEZZlerJ%2BjrUco69SyvmVS7FM96RrhvO9rI3a9nqaMZydtoFXnCOHY2%2FFGegSVH2XH9LVV916gIDkc000XkzLyF8X6rf1FC70beNqCRk9lZV3MqyrTlJqrdN95ZeYvetFJASi55JQWowkYHd6gQD7o1KiZkkrspRS5noByfdzqmhUHHPI9GvGVJe4a8YVFehpVfHU3UBAvqd9mq5WPSkw9UHoWuOdawE697jdYv12sA6hQdzIACm2PAeXlSiAFBh73wUEOBpdaIYrKEesLfZY0skuNET%2Bdw%2BQr4y3T585EOB0uE%2Favm%2BWrLfauNFY4ZZJKz9wgY%2FnvTrI7OV6EWMOX%2Fn1Ll%2BYu5NOgTtEOyM9H4evRywhXZM0zjPbqL%2FG7SzJAUNZPVotQB6vSvhHvrba%2BJGByhK2Xug7x7lBQGwLU7%2Fp2%2FcHlsLuE6TU9Wt%2B07%2FDWi9Ho%2Bo8AZD7jS8qwv2s1h62JnJLdQBJvj%2FI4qJwX2eM%2FgPPMJd5zGOeHBF%2FIOfHDzMB9EPpBReZZa3xg7Ia1yOr5ajV94AgINzl1%2FXvsO2NpGE5LqHEWAF7GFTpeFGPezltCPwwzaoFyI8TjuZSprJGihKZ2BaQ5lJotu4MSw%2BIrfKTB4iAQYFAxvhtr%2BUWkO9SiVbyksua3ijvs0S22m6Rfq5q4ffUgdCYWRQnjxJYQC6Sk1br%2FdIDIh%2BSpusbHpAekI1WlZSAnGwiGwj0ciPi3uY9%2FKoXCK352idckWyHtJVTVuv90zyylqeyQ6wAZ7u0gDiLrCo7gwLHlihaycbEIT0p8BN2dQIhWz7zxBdKZJdskvWyXtbL6QAgrcxQJTi3pwlkqTXzH%2BTT4IdPWcrgYE%2FdF4ieYB0%2FRclvglBXVuITVIsVh%2FfK2lc9Y5gikFEuHGv5RXlH6lOTLLLIknX%2BVlZRY%2FZbB%2BsjaeqQN6w3L6VnjKeyQ4ZZE5Nw36RW1iOGUD%2FRz7BNKgBE5CSbmEOfM0vhpgbEpfuWx92vyPsAINSSLckNV%2F1iIJDpVr8fVjuQih4StgY4I6kPvC0eHA9dpRT1KrryI%2FrSk9zEGsgGgnB1VYEcqS%2B7jZZC9PQACwCiFHmWSAvcKJUqy5XtQUCc0dbXu7xfnyEQt13OPj9PhEHMqtQudI8CBCkht6qXHPz8lNSBcKEVpjzizQvK2iAg%2BknXYTfa1XaO6ad7dEhXqTBalmj2stqAKMXrru4X7TjPjp3q6RKGyvVMbzNroN%2BhI9kqK9VkPnus3Ti7ykBamlfu5JR7YfBTigJ3SD%2BXPbjLjJTRgS8TBRepbQdlZEvQtQulyLZ%2FWZIikHA%2FxDWAz%2Bh%2FsgnZ1C1rr%2B9nS0RXD1JKKTrFg8%2BV4TXJl3WySv4pefIeC%2FSLTGVURVd8IFHDZS6f4u7TLWhENx6NJ5FSAlLP5W9Pst7eyckgs1cp6sv3LiRbuY1m1Kcd49mbLPwe16GRr1d7D0zqcS3T2SIrTUc71R1SU%2F7lTdjIfsmX7VJs2FC3RWp%2FltwSlzL%2BzV3xazWxvhZ4TNVC2S%2FlwOdpKvVlVkvlTOMSGhbncAML4tE5PyBK6ck%2B8z0su8ycZ3BOnabuTLiUksdEfsYg51bn5%2Fpx3pVtoitTwWVt0waiFD2t6zm%2Bzl7c46SHHCC11OwSmrhsujuDsoaykRppmb0jfLyQvXIo8rdr7DYQmsZznvY4rKRsYMbQGSGSwqIEpCR%2BEyENIEo549CJLzkgdItbZhwgpbCBfIStjxqa%2BTSr%2FXSB1JZP%2FRdRNOwdDy%2B6gSjlDKQi4Y2R53mORJccJqVyfwCkmDZVAqIUYwm4pBDJ9v4tdiukjn6ZkKR6wWCcW91Kme%2FdkJV%2BCR4Bgjwjcv0v4lCZ%2BBnGEkOkHqjOGEoDZlvOJKX0X4yvn%2FXp%2FT6OJ72ChKwzFyRZ2FmasYltoCtlGRU%2BAha%2BJBYTfa8m8y0762UGMNQZyWhnrH6QObLDo%2FJquPoZzA5vL%2FpBQ%2BnutF71ChxxC16n3DteyaN7pZaJlet8vr6JDT6z%2FbISnp7me33N9OC66vlyIkEUq0DP4WKXlfWFVWNEcsP0Kv1H%2BYStHJJjckS2ywqm0dtUztxtWTcveCOwstiqcTyaA7fU4j0sZpPskf2yU9boec4tJjYu5xE9U8%2FWz%2FM4N3tNA3vEPCWr2CPHpUgOyQbmRI8nujFZz9KzeZpRlRdSvbaQM1oWy1YKpYhC8lngDI26tuTwADOZrZ9lQnCOiHaM1fPla9ktR6VIiqRQCljNAn7LjTT0qX8x45mhZ%2BtZehrDUv65NXVoSkuaeT%2BgruRjZk98fpaG4fuDlJlXCOzLqDSgUSrBzBRG3LCkVWkbmrp3Y2qzPd2CNjS3va90r0vTgja0pnk6nnt1TLyXmVHWC3zrdI77siCnaKsy5awBGW45hUt964y36mzbWzcjt7NWnFstu6IETzbBGcJRy5KYk5Ha2dwhHU2jFXD4iN8wIHRd6Br6M56PRVv74xRdMlI7m0Cy4ldc3B6917cHPT4js7ONpIPs8L827flPyH0vK1POEhLygn8REitr%2FK8PZMrZgXKzXih77B8cxMIF%2B1nEUH9XLFPOJpQL6MVd%2Bi0pkVIpkRKpkFXOOPoUN83Ipurlf1R%2B3oIpwIIsAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE5LTAyLTI2VDEwOjU1OjM5KzAwOjAwNm0mnQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxOS0wMi0yNlQxMDo1NTozOSswMDowMEcwniEAAAAASUVORK5CYII%3D) no-repeat;background-size:auto auto;background-size:80px 20px}.responsive-footer__logo a{display:block;overflow:hidden;text-indent:-119988px;text-align:left}@media (min-width: 968px){.responsive-footer__logo--mobile{display:none}}.locale-selector .popover-container .popover{top:auto;bottom:20px;left:50%;right:auto;transform:translate(-50%, 0)}.locale-selector--dropdown{padding:6px 10px;background-color:#fff}.locale-selector--dropdown--link{display:block;min-width:10em;margin:3px 0;color:#131518}.locale-selector .flag{margin:0 4px 0 0}.site-admin-control-warning{font-size:.875rem;position:fixed;bottom:0;display:block;width:100%;padding:12px 30px;background-color:#b3475d;color:#fff;line-height:24px;z-index:449}.site-admin-control-warning a{color:#fff;text-decoration:none}.site-admin-control-warning .u-float-left{float:left}.site-admin-control-warning .u-float-right{float:right}.notice .btn{display:inline-block;padding:.25rem 1rem}.new-search{overflow:hidden;border-radius:6px;background-color:#fff;max-width:720px;height:48px}.new-search__wrap{position:relative}.new-search__input{height:48px !important}.new-search__wrap--with-image .wayfinder__image-search-wrapper{position:absolute !important}.new-search__wrap.new-search__wrap--with-image .new-search{padding-left:47px}@media (min-width: 1240px){.new-search__wrap.new-search__wrap--with-image .new-search{padding-left:65px}}.new-search__wrap--with-image .new-search__input{box-shadow:none}@media (max-width: 640px){.new-search__wrap--with-image{position:relative}.new-search__wrap--with-image .wayfinder__image-search-wrapper{width:calc(100% - 8px)}}.home-hero{position:relative;display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:400px;color:#fff;background-color:rgba(0,0,0,0.4)}.home-hero__background{position:absolute;top:0;left:0;width:100%;height:100%;z-index:0}.home-hero__background-image{width:100%;height:100%;object-fit:cover;position:absolute;top:0;left:0}.home-hero__content{position:relative;z-index:3;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;max-width:1200px;padding:0 20px;text-align:center}.home-hero__title{margin-bottom:24px;font-size:48px;font-weight:600;line-height:1.2;text-align:center;color:#fff;margin-top:0}@media (max-width: 992px){.home-hero__title{font-size:2.5rem}}@media (max-width: 576px){.home-hero__title{font-size:38px}}.home-hero__search{width:100%;max-width:720px}.home-hero__author-badge{display:flex;align-items:center;gap:6px;background:rgba(0,0,0,0.1);padding:4px 8px;border-radius:999px;backdrop-filter:blur(40px);-webkit-backdrop-filter:blur(40px);position:absolute;right:24px;bottom:10px;z-index:2;text-decoration:none;color:#fff}.home-hero__author-badge:visited{color:#fff}.home-hero__author-text{font-size:12px;font-weight:400;line-height:1.32;letter-spacing:-2%;opacity:.85}.home-hero__author-name{font-size:12px;font-weight:600;line-height:1.32;letter-spacing:-2%;margin-left:2px}.subscription-banner__container{display:flex;flex-direction:column;position:relative;background:linear-gradient(135deg, #ede7f6 0, #e8eaf6 50%, #e3f2fd 100%);border-radius:12px;overflow:hidden;max-width:576px;margin:0 auto}.subscription-banner__content{position:relative;z-index:1;display:flex;flex-direction:column;text-align:center;align-items:center;padding:32px 20px;gap:16px}.subscription-banner__tags{display:flex;flex-wrap:wrap;justify-content:center;gap:4px;padding:0;margin:0;max-width:505px}.subscription-banner__tag{display:inline-flex;align-items:center;padding:4px 12px;background-color:rgba(255,255,255,0.32);border-radius:24px;font-size:18px;font-weight:400;color:#676b6f}@media (min-width: 960px){.subscription-banner__tag{font-size:14px}}.subscription-banner__cta{width:288px}.subscription-banner__subtext{font-size:13px;font-weight:600;color:#666;margin:0}@media (min-width: 960px){.subscription-banner__subtext{font-size:14px}}.subscription-banner__visual{display:none;position:relative;overflow:visible;width:100%;max-width:none;min-height:260px}.subscription-banner__wave{position:absolute;top:0;left:0;width:100%;height:100%;z-index:0}.subscription-banner__wave-image{width:100%;height:100%;object-fit:cover}.subscription-banner__butterfly{position:absolute;left:auto;right:60px;top:-25px;width:252px;transform:scale(1.1);z-index:4}.subscription-banner__bird{display:none}.subscription-banner__value-card{display:none;position:absolute;top:auto;left:80px;bottom:120px;padding:24px 16px;background:rgba(255,255,255,0.56);border-radius:12px;transform:rotate(8.75deg);text-align:center;z-index:3;color:#35424f;box-shadow:0 1px 2px 0 rgba(255,255,255,0.8) inset,0 -1px 1px 0 rgba(48,47,45,0.06) inset;backdrop-filter:blur(8px);-webkit-mask-image:radial-gradient(circle 10px at 50% 0%, transparent 10px, black 10px),radial-gradient(circle 10px at 50% 100%, transparent 10px, black 10px);mask-image:radial-gradient(circle 10px at 50% 0%, transparent 10px, black 10px),radial-gradient(circle 10px at 50% 100%, transparent 10px, black 10px);-webkit-mask-size:100% 51%;mask-size:100% 51%;-webkit-mask-position:top,bottom;mask-position:top,bottom;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;font-size:20px;font-weight:400}.subscription-banner__value-bottom,.subscription-banner__value-top{margin:0;font-size:20px;font-weight:400;color:#35424f;line-height:1.2}.subscription-banner__value-amount{font-size:22px;font-weight:800;background:linear-gradient(135deg, #19bcc9 0, #ad9dfc 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;line-height:1.2;display:inline}.subscription-banner__value-price{font-size:24px;font-weight:700;color:#159ca9;line-height:1.2}.subscription-banner__value-period{font-weight:400;color:#159ca9}.subscription-banner__flower{display:none}.subscription-banner__everyday-pill{display:none;position:absolute;top:auto;left:162px;bottom:86px;transform:rotate(-5deg);padding:6px 14px;border-radius:32px;font-size:16px;font-weight:400;white-space:nowrap;z-index:3;color:#686c70;background-color:#fff;backdrop-filter:blur(12px);box-shadow:0 1px 2px 0 rgba(255,255,255,0.8) inset,0 -1px 1px 0 rgba(48,47,45,0.06) inset,1px 1px 12px 0 rgba(0,0,0,0.1)}@media (min-width: 577px){.subscription-banner__everyday-pill,.subscription-banner__value-card,.subscription-banner__visual{display:block}}@media (min-width: 1280px){.subscription-banner__container{flex-direction:row;align-items:center;max-width:unset;margin:unset}.subscription-banner__content{flex:1 1 60%;text-align:left;align-items:flex-start;padding:40px;gap:20px}.subscription-banner__tags{justify-content:flex-start;max-width:unset}.subscription-banner__visual{display:block;flex:0 0 35%;max-width:35%;width:auto;min-height:368px;overflow:hidden}.subscription-banner__butterfly{left:275px;right:auto;top:130px;width:270px;transform:translate(-50%, -50%) scale(1.1)}.subscription-banner__value-card{display:block;top:160px;left:730px;bottom:auto;padding:24px 12px}.subscription-banner__value-amount{font-size:28px}.subscription-banner__flower{display:block;position:absolute;right:-25px;bottom:-20px;width:163px;z-index:1}.subscription-banner__everyday-pill{display:block;top:270px;left:770px;bottom:auto;padding:8px 20px;font-size:18px}}@media (min-width: 1600px){.subscription-banner__content{padding:48px 56px;gap:24px}.subscription-banner__visual{flex:0 0 40%;max-width:40%;min-height:368px}.subscription-banner__butterfly{left:280px;top:164px;width:369px}.subscription-banner__bird{display:block;position:absolute;right:0;top:0;width:141px;height:141px;filter:blur(3px);z-index:1}.subscription-banner__value-card{top:105px;left:667px;padding:32px 20px;transform:rotate(4.5deg)}.subscription-banner__value-bottom,.subscription-banner__value-top{font-size:26px}.subscription-banner__value-price{font-size:30px}.subscription-banner__flower{position:absolute;right:-25px;bottom:0;width:210px;z-index:1;scale:1}.subscription-banner__everyday-pill{top:250px;left:730px;font-size:22px}}.filter-item__count,.promo-card__badge{background-color:rgba(0,0,0,0.05);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);font-size:12px;font-weight:600;padding:2px 6px;border-radius:6px;letter-spacing:-2%}.model-filter__layout{display:grid;width:100%;gap:8px;grid-template-columns:1fr;grid-template-rows:auto}@media (min-width: 1025px){.model-filter__layout{grid-template-columns:repeat(3, 1fr);grid-template-rows:repeat(3, 1fr)}}@media (min-width: 1025px){.model-filter__type-section{grid-row:span 3}}@media (min-width: 1025px){.model-filter__format-section{grid-column:span 2;grid-row:span 2}}@media (min-width: 1025px){.model-filter__promo-section{grid-column:2/span 2;grid-row:3/span 1}}.filter-panel{background-color:#f7f7f8;padding:24px;border-radius:8px;height:100%}.filter-items{display:flex;flex-direction:column;gap:0 12px}@media (min-width: 768px){.filter-items--formats,.filter-items--types{display:grid;grid-template-columns:1fr 1fr}}@media (min-width: 768px) and (min-width: 1025px){.filter-items--types{display:flex;flex-direction:column}}.filter-item{display:flex;justify-content:space-between;align-items:center;padding:12px;border-bottom:1px solid rgba(39,44,48,0.12);text-decoration:none;color:inherit}.filter-item__content{display:flex;align-items:center;gap:12px}.filter-item__name{font-weight:600;font-size:16px;color:#333}.filter-item__meta{display:flex;align-items:center;gap:8px;justify-content:flex-end;text-align:right}.filter-item__ext{color:#6c757d;font-size:13px}.type-filter-item{position:relative}.type-filter-item .filter-item__icon-container{display:flex;align-items:center;justify-content:center;width:24px;height:24px;margin-right:4px}.type-filter-item .filter-item__icon-wrapper{display:flex;align-items:center;justify-content:center;opacity:0}.type-filter-item .filter-item__icon-wrapper svg path{transform:translateX(-8px);opacity:0}.type-filter-item .filter-item__icon-wrapper svg circle{opacity:1}.promo-cards{display:flex;flex-direction:column;gap:8px;align-items:center;justify-content:center;width:100%;height:100%;min-height:168px}@media (min-width: 768px){.promo-cards{flex-direction:row}}.promo-card{padding:16px;display:flex;align-items:center;justify-content:center;border-radius:8px;position:relative;width:100%;height:168px}@media (min-width: 768px){.promo-card{flex:1;height:100%}}.promo-card--sale{background-color:#f5eff0}.promo-card--free{background-color:#f4f3ec}.promo-card__content{position:absolute;width:100%;font-size:16px;font-weight:600;display:flex;align-items:center;justify-content:space-between;bottom:0;left:0;height:60px;padding-left:16px;gap:8px;padding:16px}.promo-card__content--title{display:flex;align-items:center;flex-direction:row;gap:8px}.promo-card__arrow-wrapper{display:flex;align-items:center;justify-content:center}.promo-card__arrow-wrapper svg circle{opacity:0}.promo-card__arrow-wrapper svg path{transform:translateX(-8px)}.circled-arrow--responsive{width:16px;height:16px}@media (min-width: 768px){.circled-arrow--responsive{width:24px;height:24px}}.card-button-mobile{display:flex;flex:1}.card-button-mobile a{width:100%;text-align:center}@media (min-width: 576px){.card-button-mobile{display:none}}.modelry-button{background-color:#3c73f6;border:1px solid transparent;justify-content:center}.three-d-jobs-button{background-color:#19bcc9;border:1px solid transparent;justify-content:center}.asset-collection{margin:0 auto}.asset-collection__description{margin-bottom:32px;margin-top:8px}@media (min-width: 420px){.asset-collection__description{margin-bottom:40px}}.asset-collection__trending{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:32px}@media (min-width: 420px){.asset-collection__trending{margin-bottom:40px}}.asset-collection__actions{display:flex;flex-direction:column;align-items:center;gap:16px;margin-top:20px}@media (min-width: 768px){.asset-collection__actions{margin-top:30px}}.category-grid{display:grid;grid-template-columns:repeat(12, 1fr);gap:10px;width:100%}@media (max-width: 991px){.category-grid{grid-template-columns:repeat(6, 1fr);gap:16px}}@media (max-width: 767px){.category-grid{grid-template-columns:repeat(2, 1fr);gap:12px}}.category-grid__item{grid-column:span 3;grid-row:span 1;position:relative;padding-bottom:80.03%}.category-grid__item--wide{grid-column:span 6;padding-bottom:40.015%}.category-grid__item--tall{grid-row:span 2;padding-bottom:140.06%}@media (max-width: 991px){.category-grid__item{grid-column:span 3}.category-grid__item--wide{grid-column:span 6}}@media (max-width: 767px){.category-grid__item{grid-column:span 1}.category-grid__item--wide{grid-column:span 2}.category-grid__item--tall{grid-row:span 2;padding-bottom:140.06%}}.category-grid .category-grid__item>.category-card{position:absolute;top:0;left:0;right:0;bottom:0;padding-top:0;height:100%}.print-ready-models{background-color:#f7f7f8;border-radius:16px;margin:0 10px;padding:56px 16px}@media (min-width: 768px) and (max-width: 991px){.print-ready-models{padding:64px 32px}}@media (min-width: 992px){.print-ready-models{padding:64px 48px}}@media (min-width: 1440px){.print-ready-models{padding:64px 136px}}@media (min-width: 1600px){.print-ready-models{max-width:1600px;margin:0 auto}}.asset-collection__subcategories{margin:0 15px}@media (min-width: 768px){.asset-collection__subcategories{margin:0 45px}}.asset-collection__subcategories--hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}.subcategories-table{margin-top:40px;margin-bottom:40px;border:1px solid rgba(39,44,48,0.12);border-radius:8px;overflow:hidden}.subcategories-table__row{display:grid;grid-template-columns:repeat(4, 1fr)}@media (max-width: 991px){.subcategories-table__row{grid-template-columns:repeat(2, 1fr)}}@media (max-width: 767px){.subcategories-table__row{grid-template-columns:1fr}}.subcategories-table__column{padding:24px;position:relative;border-right:0.5px solid rgba(39,44,48,0.12);border-bottom:0.5px solid rgba(39,44,48,0.12)}.subcategories-table__header{display:flex;justify-content:flex-start;gap:8px;align-items:center;margin-bottom:16px}.subcategories-table__title{font-size:16px;font-weight:600;color:#272c30;margin:0;text-decoration:none}.subcategories-table__count{font-size:12px;color:rgba(39,44,48,0.6);background:rgba(39,44,48,0.06);padding:2px 6px;border-radius:6px}.subcategories-table__list{list-style:none;padding:0;margin:0}.subcategories-table__item{margin-bottom:16px}.subcategories-table__item:last-child{margin-bottom:0}.subcategories-table__link{font-size:14px;color:rgba(39,44,48,0.8);text-decoration:none;display:block}@media (max-width: 992px){.category-grid.print-models-3d .category-grid__item:nth-child(7){order:7}.category-grid.print-models-3d .category-grid__item:nth-child(8){order:8}.category-grid.print-models-3d .category-grid__item:nth-child(9){order:6}}.trending-buttons{display:flex;flex-direction:row;align-items:center;flex-wrap:wrap;gap:8px}.home-hero__trending-buttons-container{display:flex;flex-direction:row;align-items:center;justify-content:center;margin-top:16px}@media (min-width: 768px){.home-hero__trending-buttons-container{width:calc(100% + 50px);margin-left:-25px}}.home-hero .trending-buttons{justify-content:center}.home-hero .trending-buttons .home-hero__trending-button:nth-child(n+8){display:none}@media (min-width: 768px){.home-hero .trending-buttons .home-hero__trending-button:nth-child(n+8){display:flex}}.home-hero__trending-button{color:#fff;background-color:rgba(255,255,255,0.2);border:1px solid rgba(255,255,255,0.12);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px)}.trending-models__header{display:flex;flex-direction:column;gap:16px}@media (min-width: 768px){.trending-models__header{flex-direction:row;align-items:flex-start;justify-content:space-between;gap:24px}}.trending-models__title-group{display:flex;flex-direction:column;gap:8px}.trending-models__description{max-width:600px}.trending-models__list{display:none;gap:12px}@media (min-width: 420px){.trending-models__list{display:flex;flex-wrap:wrap}}.browse-all-desktop{display:none;margin-left:auto}@media (min-width: 768px){.browse-all-desktop{display:inline-flex}}.browse-all-mobile{display:flex;justify-content:center;width:100%}@media (min-width: 768px){.browse-all-mobile{display:none}}.featured-designers-container{display:flex;flex-direction:column;gap:24px;padding:24px 16px;background-color:#f7f7f8;border-radius:16px;margin:16px}@media (min-width: 768px){.featured-designers-container{padding:32px;gap:32px;margin:24px}}@media (min-width: 1024px){.featured-designers-container{padding:48px 64px;gap:40px}}@media (min-width: 1440px){.featured-designers-container{width:100%;max-width:1280px;margin:40px auto}}.u-mr10{margin-right:10px}.text-white{color:#fff}#notifications-container{top:96px;position:fixed;margin:10px 0 0;right:10px;z-index:1001}#notifications-container.with-bar{top:136px}.category-card{position:relative;width:100%;padding-top:70.03%;height:0;z-index:1}.category-card__main{position:absolute;width:100%;height:100%;top:0;left:0;border-radius:8px;background-color:#272c301f;border:1px solid rgba(39,44,48,0.12);box-shadow:0 4px 15px rgba(0,0,0,0.1);z-index:3;overflow:hidden}.category-card__image{position:absolute;border-radius:8px;top:0;left:0;width:100%;height:100%;object-fit:cover;z-index:1}.category-card::before{content:'';position:absolute;width:95%;height:95%;top:-2.5%;left:2.5%;background-color:#eff0f0;border-radius:8px;z-index:2;border:0.5px solid rgba(39,44,48,0.12)}.category-card--no-before::before{content:none}.category-card__overlay{position:absolute;bottom:0;left:0;width:100%;min-height:64px;background:linear-gradient(to top, rgba(0,0,0,0.5), rgba(0,0,0,0));display:flex;justify-content:space-between;align-items:center;padding:0 16px;z-index:4}.category-card__info-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px}.category-card__icon-wrapper{display:flex;align-items:center;justify-content:center;opacity:0;transform:translateX(-10px)}.category-card__badge{min-width:37px;height:20px;display:flex;align-items:center;justify-content:center;background-color:rgba(255,255,255,0.2);color:#fff;font-size:12px;font-weight:600;padding:2px 6px;border-radius:6px;backdrop-filter:blur(16px)}@media (max-width: 1279.98px){.category-card{padding-top:70%}.category-card::before{height:95%}}@media (max-width: 639.98px){.category-card{padding-top:65.9%}.category-card::before{height:95%;border-radius:6px}.category-card__badge{font-size:10px;padding:0 6px;border-radius:6px;opacity:.8}.category-card__overlay{min-height:50px}}.new-home-section{padding:56px 16px}@media (min-width: 768px) and (max-width: 991px){.new-home-section{padding:64px 40px}}@media (min-width: 992px){.new-home-section{padding:64px}}@media (min-width: 1440px){.new-home-section{padding:64px 160px}}@media (min-width: 1600px){.new-home-section{max-width:1600px;margin:0 auto}}.__react_component_tooltip:not(.show){visibility:hidden;opacity:0;display:none}.cgt-tooltip:not(.show){visibility:hidden;opacity:0;display:none}.timer-strip.is-secondary-color{background:linear-gradient(90.05deg, #A91E4C 0%, #CC2795 52.4%, #A91E4A 100%)}.timer-strip.blue-gradient{background:linear-gradient(90.05deg, #3E8AED 0%, #1769D3 52.4%, #3E8AED 100%)}.timer-strip.black-gradient{background:linear-gradient(90deg, #131920 0%, #073F89 48.08%, #131920 100%)}.timer-strip.timer-strip--subscription{background:linear-gradient(90deg, rgba(158,48,165,0.14) -15.62%, rgba(30,155,169,0.14) 43.39%, rgba(25,149,158,0.14) 67.13%, rgba(158,48,165,0.14) 98.8%),#fff;color:#1A1A1A}.timer-strip--subscription .timer-strip__cta{display:inline-flex;align-items:center;gap:4px;color:#1E9BA9;font-weight:600;text-decoration:none}.timer-strip--subscription .timer-strip__cta svg{fill:currentColor}.new-search__wrap--with-image .wayfinder__image-search-wrapper{position:absolute !important}@media (max-width: 640px){.new-search__wrap--with-image .wayfinder__image-search-wrapper .is-active{position:relative;transform:translateY(15px);z-index:1000;width:100%}.new-search__wrap--with-image .wayfinder__image-search-wrapper{width:calc(100% - 8px)}}.wayfinder__action-link,.wayfinder__image-search{width:100%;height:100%;padding:0 12px;display:flex;justify-content:center;align-items:center}.wayfinder__image-search{border-right:1px solid rgba(30,39,50,0.12);max-width:47px}@media (min-width: 1280px){.wayfinder__action-link,.wayfinder__image-search{padding:0 20px}.wayfinder__image-search{max-width:none}} window.addEventListener("load", function () { const headElement = document.getElementsByTagName("head")[0]; const stylesLinkElement = document.createElement("link"); stylesLinkElement.rel = "stylesheet"; stylesLinkElement.href = 'https://assets.cgtrader.com/assets/new_homepage/new_homepage-458179ad299786a655ead2edd40f24b7f7abc5df14b1c5356aa99b3a0263ae1a.css'; headElement.appendChild(stylesLinkElement); });(function() { window.App = {} window.numberOfAxiosCallPending = 0; })(); // jshint ignore: start 'use strict' window.removeInlineCookieBar = function () { const barSelector = '.js-inline-cookies' const currentBar = document.querySelector(barSelector) if (currentBar) { document.body.removeChild(currentBar) } } window.handleCookiesAccept = function (cookie) { if (cookie) { Cookies.set(cookie, true, { expires: 365, path: '/' }); } removeInlineCookieBar(); } window.handleCookiesDismiss = function (cookie) { if (cookie) { Cookies.set(cookie, true, { path: '/' }); } removeInlineCookieBar(); } window.lazyLoad = function (image, srcAttributeName = 'src') { const urlToLoad = image.dataset[srcAttributeName] if (urlToLoad) { const tempImage = new Image() tempImage.src = urlToLoad tempImage.onload = function () { image.src = tempImage.src } } } window.checkIfUnderControl = function (isUnderControl, currentUserProfile, currentUserUsername) { if (!isUnderControl || !currentUserProfile || !currentUserUsername) { return null } const underControlTarget = withId('under-controll-inner') const profileLink = document.createElement('a') profileLink.href = currentUserProfile profileLink.innerText = `Under ${currentUserUsername} support.` underControlTarget.append(profileLink) withElementsToggleClass('.js-under-controll-bar', 'is-hidden') } function loadScript(source, beforeEl, async = true, defer = true) { return new Promise((resolve, reject) => { let script = document.createElement('script') const prior = beforeEl || document.getElementsByTagName('script')[0] script.async = async script.defer = defer function onloadHander(_, isAbort) { if ( isAbort || !script.readyState || /loaded|complete/.test(script.readyState) ) { script.onload = null script.onreadystatechange = null script = undefined if (isAbort) { reject() } else { resolve() } } } script.onload = onloadHander script.onreadystatechange = onloadHander script.src = source prior.parentNode.insertBefore(script, prior) }) } function decodeHtml(html) { const textarea = document.createElement('textarea') textarea.innerHTML = html return textarea.value } function withId(id) { return document.getElementById(id) } function withElements(selector, callback, rootNode = document) { if (!rootNode) { console.warn('[withElements] rootNode is null for selector:', selector) return [] } let elements if (typeof selector === 'string') { elements = rootNode.querySelectorAll(selector) } else if (!selector.length) { elements = [selector] } else { elements = selector } for (let i = 0; i < elements.length; i++) { callback(elements[i], i) } return elements } function withClosestElementToggleClass(selector, cssClass, rootNode) { rootNode.closest(selector).classList.toggle(cssClass) } function withElementsSetBackground(selector, img, rootNode) { withElements( selector, function (element) { element.style.backgroundImage = `url('${img}')` }, rootNode ) } function withElementsSetDisplay(selector, display, rootNode) { withElements( selector, function (element) { element.style.display = display }, rootNode ) } function withElementsToggleDisplay(selector, display, rootNode) { return withElements( selector, function (element) { if (element.style.display === display) { element.style.display = '' } else { element.style.display = display } }, rootNode ) } function withElementsToggleClass(selector, cssClass, rootNode) { return withElements( selector, function (element) { element.classList.toggle(cssClass) }, rootNode ) } function withElementsRemoveClass(selector, cssClass, rootNode) { return withElements( selector, function (element) { element.classList.remove(cssClass) }, rootNode ) } function withElementsAddClass(selector, cssClass, rootNode) { return withElements( selector, function (element) { element.classList.add(cssClass) }, rootNode ) } function withElementsSetInnerText(selector, innerText, rootNode) { return withElements( selector, function (element) { element.innerText = innerText }, rootNode ) } function withElementsAddEventListener(selector, event, callback, rootNode) { withElements( selector, function (element) { element.addEventListener(event, callback) }, rootNode ) } function timeAgo(timeStamp) { const now = new Date() const secondsPast = (now.getTime() - timeStamp.getTime()) / 1000 if (secondsPast < 60) { return `${parseInt(secondsPast)} seconds ago` } if (secondsPast < 3600) { return `${parseInt(secondsPast / 60)} minutes ago` } if (secondsPast 86400) { return timeStamp.toISOString().slice(0, 10) } } function closeModal(modalRoot) { if (!modalRoot) { modalRoot = document.querySelector('.overlay-modal--background') } document.body.classList.remove('has-open-modal') if (modalRoot.parentNode) { modalRoot.parentNode.removeChild(modalRoot) } } function showModal(modalContainerElement) { document.body.classList.add('has-open-modal') withElements( '.js-close-modal', function (closeButton) { closeButton.addEventListener('click', function (event) { closeModal(modalContainerElement) }) }, modalContainerElement ) } function createModal(contentHTML, options) { options = options || {} const id = `modal-${Math.ceil(Math.random() * 10e4)}` const root = document.createElement('div') root.classList.add('overlay-modal--background') root.id = id if (options.rootClass) { options.rootClass.split(' ').forEach(function (name) { root.classList.add(name) }) } if (!options.skipAutoClose) { root.addEventListener('click', function (e) { if (!getContainer(e, 'overlay-modal--content')) { closeModal(root) } }) } const container = document.createElement('div') container.classList.add( 'overlay-modal-container', 'overlay-modal-container--smaller' ) root.append(container) const modal = document.createElement('div') modal.classList.add('overlay-modal') container.append(modal) const close = document.createElement('button') close.classList.add( 'btn', 'btn-transparent', 'overlay-modal__close', 'js-close-modal' ) modal.append(close) const closeIcon = document.createElement('i') closeIcon.classList.add('far', 'fa-times', 'is-grey') close.append(closeIcon) const content = document.createElement('div') content.classList.add('overlay-modal--content') modal.append(content) content.innerHTML = options.parseHTML ? decodeHtml(contentHTML) : contentHTML document.body.append(root) return root } function getParentWith(selector, node) { let container = node let target while (!target) { if (!container.parentElement) break container = container.parentElement target = container.querySelector(selector) } return container } function getItemData(item) { const data = item.dataset const itemAttributes = data && data.attributes ? JSON.parse(data.attributes) : {} return itemAttributes } function findAncestor(cls, el) { while ((el = el.parentElement) && !el.classList.contains(cls)); return el } function debounce(func, wait, immediate) { var timeout return function () { var context = this, args = arguments var later = function () { timeout = null if (!immediate) func.apply(context, args) } var callNow = immediate && !timeout clearTimeout(timeout) timeout = setTimeout(later, wait) if (callNow) func.apply(context, args) } } function performXHR(method, url, callback, data) { window.numberOfAxiosCallPending += 1 var xhr = new XMLHttpRequest() xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (callback) { const { responseText, status } = xhr callback(responseText, status) } } window.numberOfAxiosCallPending -= 1 } xhr.open(method, url) // Set Accept header for .js requests to ensure proper content negotiation (MARKETPLACE-JS-418X) if (url.match(/\.js(\?|$)/)) { xhr.setRequestHeader('Accept', 'text/javascript, application/javascript') } if (data && !(data instanceof FormData)) { xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8') } xhr.setRequestHeader('X-CSRF-Token', '' + getToken()) xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.send(data) return xhr } // this is a legacy function to get the JSON data from the server // it is was used in the fast pages with vanilla JS bundles // for pages where webpack bundle is used, please don't use this function!!! // use something from axios or react-query instead. async function fetchJSON(url) { window.numberOfAxiosCallPending += 1 const res = await fetch(url, { credentials: 'same-origin', headers: { 'X-CSRF-Token': getToken(), }, }) window.numberOfAxiosCallPending -= 1 if (!res.ok) { throw new Error(`HTTP error when fetching json! status: ${res.status}`) } try { return await res.json(); } catch (error) { console.error('Error parsing JSON:', error); throw new Error('Invalid JSON response'); } } async function postJSON(url, data) { window.numberOfAxiosCallPending += 1 const res = await fetch(url, { method: 'POST', credentials: 'same-origin', headers: { 'X-CSRF-Token': getToken(), 'Content-Type': 'application/json;charset=UTF-8', }, body: JSON.stringify(data), }) window.numberOfAxiosCallPending -= 1 if (!res.ok) { throw new Error(`HTTP error when posting json! status: ${res.status}`) } try { return await res.json(); } catch (error) { console.error('Error parsing JSON:', error); throw new Error('Invalid JSON response'); } } async function fetchHTML(url) { window.numberOfAxiosCallPending += 1 const res = await fetch(url, { credentials: 'same-origin', headers: { 'X-CSRF-Token': getToken(), }, }) window.numberOfAxiosCallPending -= 1 return await res.text() } function getContainer(event, className) { const closest = event.target.closest('.' + className) return event.target.classList.contains(className) ? event.target : closest } function layoutGallery(root) { const carouselContainer = root.querySelector('.product-carousel') const listImageArea = carouselContainer.querySelector( '.product-carousel__thumbs ul' ) if (listImageArea.scrollWidth === listImageArea.offsetWidth) { listImageArea.style.justifyContent = 'center' } else { listImageArea.style.justifyContent = 'flex-start' } } function getOffsetTop(element) { let offsetTop = 0 while (element) { offsetTop += element.offsetTop element = element.offsetParent } return offsetTop } function showTooltip(el) { let closeTimeout function close() { closeTimeout = setTimeout(function () { clearTimeout(timeout) if (tooltip.parentNode) { tooltip.parentNode.removeChild(tooltip) } }, 100) } const tooltip = document.createElement('span') tooltip.classList.add('tooltip') if (el.dataset.class) { tooltip.classList.add(el.dataset.class) } const arrow = document.createElement('span') arrow.classList.add('arrow') tooltip.append(arrow) const content = document.createElement('span') content.classList.add('content') content.innerHTML = el.dataset.value tooltip.append(content) el.parentNode.insertBefore(tooltip, el) if (el.dataset.side) { tooltip.style[el.dataset.side] = el.offsetWidth / 2 + 'px' } else { tooltip.style.left = el.offsetWidth / 2 + 'px' } const timeout = setTimeout(function () { tooltip.classList.add('active') }, 100) content.addEventListener('mouseenter', function () { clearTimeout(closeTimeout) content.addEventListener('mouseleave', function () { close() }) }) el.addEventListener('mouseleave', function () { close() }) } function getItemAttributes(attributes) { return { id: `${attributes.id}`, name: attributes.title, price: `${attributes.price}`, brand: attributes.authorUsername, category: attributes.category, variant: attributes.productType, position: attributes.index, ...attributes.itemCategories } } function prepareItemTracking(attributes, listItemV2 = false, searchQueryPrefixed = false) { const cart = window.pageConfig.cart const isCurrentUser = window.pageConfig.isCurrentUser const productPricing = resolveProductPricing({ cart, attributes, id: attributes.id, isCurrentUser, }) const items = [] data = [{}, 0, 0] if (attributes.searchingFree && productPricing.price > 0) { data = [attributes, 0, attributes.price.toFixed(2)] } else if (productPricing.ribbon === 'saleOff') { if (productPricing.discount > 0) { data = [attributes, (productPricing.originalPrice - productPricing.price).toFixed(2), productPricing.price.toFixed(2)] } else { data = [attributes, 0, attributes.price.toFixed(2)] } } else if (productPricing.ribbon === 'CLD') { if (productPricing.discount > 0) { data = [attributes, (productPricing.originalPrice - productPricing.price).toFixed(2), productPricing.price.toFixed(2)] } else { data = [attributes, 0, attributes.price.toFixed(2)] } } else { data = [attributes, 0, attributes.price.toFixed(2)] } if (listItemV2) { items.push(prepareTrackViewItemList(...data, searchQueryPrefixed)) } else { items.push(prepareTrackViewItem(...data)) } return items } function searchQueryPrefix() { let prefix = ''; let currentSearchParams = new URLSearchParams(window.location.search); if (currentSearchParams.has('keywords') && currentSearchParams.has('suggested') && currentSearchParams.get('suggested') === '1') { prefix = 'suggested_' } else if (currentSearchParams.has('keywords')) { prefix = 'search_' } else { prefix = 'category_' } return prefix } function prepareTrackViewItemUA(attributes, discount, price) { prefix = searchQueryPrefix() const trackable_attributes = { id: String(attributes.id), name: attributes.title, list_position: attributes.index, category: attributes.category, item_list_id: prefix + attributes.searchQuery, item_list_name: prefix + attributes.searchQuery, price: parseFloat((price - discount).toFixed(2)), } return trackable_attributes } function prepareTrackViewItemList(attributes, discount, price, prefixed = false) { const hasSimilarModelsReference = window.pageConfig.similarSelect const searchQuery = hasSimilarModelsReference ? 'similar' : attributes.searchQuery || '' const trackable_attributes = { item_id: String(attributes.id), item_name: attributes.title, affiliation: attributes.affiliation || '', currency: 'USD', index: parseInt(attributes.index) || 0, item_brand: attributes.authorUsername, item_category: attributes.category, item_category2: attributes.subcategory, item_category3: attributes.itemCategory3, item_category4: attributes.itemCategory4, item_category5: attributes.itemCategory5, item_list_id: searchQuery, item_list_name: searchQuery, item_variant: attributes.productType, location_id: attributes.locationId && attributes.locationId.join("_"), price: parseFloat(price), quantity: 1, } trackable_attributes.discount = discount > 0 ? parseFloat(discount) : 0 return trackable_attributes } function prepareTrackViewItem(attributes, discount, price) { let prefix = ''; let currentSearchParams = new URLSearchParams(window.location.search); if (currentSearchParams.has('keywords') && currentSearchParams.has('suggested') && currentSearchParams.get('suggested') === '1') { prefix = 'suggested_' } else if (currentSearchParams.has('keywords')) { prefix = 'search_' } else { prefix = 'category_' } const trackable_attributes = { item_id: String(attributes.id), item_name: attributes.title, currency: 'USD', index: attributes.index, item_category: attributes.category, item_category2: attributes.subcategory, item_list_id: prefix + attributes.searchQuery, item_list_name: prefix + attributes.searchQuery, price: price, value: parseFloat((price - discount).toFixed(2)), quantity: 1, } if (discount > 0) { trackable_attributes.discount = parseFloat(discount) } return trackable_attributes } // Exact copy of /app/javascript/Utils/ResolveProductPricing.js function resolveProductPricing({ cart, attributes, id, isCurrentUser }) { const productDiscountAvailable = { saleOff: cart.isSaleOff && attributes.isSaleOffApplicable, cld: !cart.isCLDDisabled && attributes.isCLDApplicable } if ((productDiscountAvailable.saleOff) && attributes.saleOffDiscount !== 0) { const discountedPrice = attributes.price * (100 - attributes.saleOffDiscount) / 100.0 return { price: discountedPrice, originalPrice: attributes.price, discount: 1.0 - discountedPrice / attributes.price, discountAmount: attributes.price - discountedPrice, ribbon: 'saleOff', } } else if (productDiscountAvailable.cld) { const isCartSizeSufficient = cart.value + attributes.price >= cart.applicableCldValue if (isCurrentUser && isCartSizeSufficient) { let discountedPrice = Math.max( attributes.price - cart.creditsAvailable, attributes.price * 0.7 ) return { price: discountedPrice, originalPrice: attributes.price, discount: 1.0 - discountedPrice / attributes.price, discountAmount: attributes.price - discountedPrice, ribbon: 'CLD', } } else { return { price: attributes.price, originalPrice: attributes.price, discount: 0, discountAmount: 0, ribbon: 'CLD', } } } else { return { price: attributes.price, originalPrice: attributes.price, discount: 0, } } } function createElementWithConfig(element, config) { const el = document.createElement(element); Object.keys(config).forEach((key) => { el.setAttribute(key, config[key]); }); return el; } // Utility function to setup user interaction listeners // Executes callback on first user interaction then removes listeners window.setupUserInteractionListener = function(callback, options = {}) { if (typeof callback !== 'function') { console.warn('[setupUserInteractionListener] callback must be a function'); return; } let userHasInteracted = false; const events = options.events || ['click', 'scroll', 'keydown', 'touchstart', 'mousemove']; const useCapture = options.useCapture || false; const handleUserInteraction = function(event) { if (userHasInteracted) return; userHasInteracted = true; removeInteractionListeners(); callback(event); }; const removeInteractionListeners = function() { events.forEach(eventType => { document.removeEventListener(eventType, handleUserInteraction, useCapture); }); }; // Add listeners for user interactions events.forEach(eventType => { document.addEventListener(eventType, handleUserInteraction, useCapture); }); // Return cleanup function in case manual cleanup is needed return removeInteractionListeners; } ; // // event bus // ; (function () { const events = [] App.events = { publish: function (event, data) { events.forEach(function (item) { if (item.key === event) { item.callback(data) } }) }, subscribe: function (event, callback) { events.push({ key: event, callback: callback, }) }, unsubscribe: function (event, callback) { const index = events.findIndex(function (item) { return item.key === event && item.callback === callback }) if (index > -1) { events.splice(index, 1) } }, } })(); 'use strict' function getToken() { const meta = document.querySelector('meta[name="csrf-token"]') const freshToken = meta ? meta.content : '' return freshToken } function setToken() { withElements('[name=authenticity_token]', function (element) { element.value = getToken() }) } setToken() ; function initSaleOff() { 'use strict' function init(saleOffConfig) { const { content, discount, discountPhrase, endsAt, useTimer } = saleOffConfig let setIntervalId = null withElements('.js-sale-off-timer', function (timerContainer) { timerContainer.innerHTML = JSON.parse(timerContainer.getAttribute('data-timer')).content withElementsSetInnerText('#sale-off-strip-content', content, timerContainer) withElementsSetInnerText('#sale-off-strip-discount', `${discount}%`, timerContainer) withElementsSetInnerText('#sale-off-strip-discount-phrase', discountPhrase, timerContainer) withElementsSetDisplay('#sale-off-strip-time', 'none', timerContainer) function updateTimer() { let timeRemaining = endsAt - new Date().getTime() if (timeRemaining >= 0) { const days = parseInt(timeRemaining / (60 * 60 * 24 * 1000)).toString().padStart(2, '0') timeRemaining = (timeRemaining % (60 * 60 * 24 * 1000)) const hours = parseInt(timeRemaining / (60 * 60 * 1000)).toString().padStart(2, '0') timeRemaining = (timeRemaining % (60 * 60 * 1000)) const minutes = parseInt(timeRemaining / (60 * 1000)).toString().padStart(2, '0') timeRemaining = (timeRemaining % (60 * 1000)) const seconds = parseInt(timeRemaining / 1000).toString().padStart(2, '0') withElementsSetInnerText('#sale-off-strip-days', `${days} : `, timerContainer) withElementsSetInnerText('#sale-off-strip-hours', `${hours} : `, timerContainer) withElementsSetInnerText('#sale-off-strip-minutes', `${minutes} : `, timerContainer) withElementsSetInnerText('#sale-off-strip-seconds', seconds, timerContainer) } else { withElementsSetDisplay('.js-sale-off-timer', 'none') clearInterval(setIntervalId) } } if (useTimer) { setIntervalId = setInterval(updateTimer, 1000) withElementsSetDisplay('#sale-off-strip-time', '', timerContainer) } }) } if ( window.pageConfig.saleOff && window.pageConfig.saleOff.visible && window.pageConfig.saleOff.endsAt - new Date().getTime() > 0 ) { init(window.pageConfig.saleOff) } } ; ;(function() { window.dataLayer = window.dataLayer || [] window.itemIdsBuffer = window.itemIdsBuffer || [] window.impressionsCounter = window.impressionsCounter || 0 window.track = function(options) { window.dataLayer.push({ event: options.event || 'CustomEvent', eventCategory: options.eventCategory || '', eventAction: options.eventAction || '', eventLabel: options.eventLabel || '', eventValue: options.eventValue || '', isNonInteractionHit: options.isNonInteractionHit || false, }) } window.trackCustomEvent = function(event = null) { // this function is used to track GA events // let's use this insted of window.dataLayer.push if (event) { window.dataLayer.push(event) } } })(); "use strict"; function showGuestElements() { withElementsSetDisplay(".js-only-for-user", "none"); withElementsSetDisplay(".js-only-for-admin", "none"); withElementsSetDisplay(".js-only-for-guest", ""); } function showUserElements(isNotAdmin) { withElementsSetDisplay(".js-only-for-guest", "none"); withElementsSetDisplay(".js-only-for-user", ""); if (isNotAdmin) { withElementsSetDisplay(".js-only-for-admin", "none"); } } function bindUserInfo(props) { const { currentUserUsername, currentUserAvatarUrl } = props if (currentUserAvatarUrl) { withElementsSetDisplay(".js-current-user-initials", "none"); withElements(".js-current-user-avatar-image", function (element) { element.src = currentUserAvatarUrl; }); } else { withElements(".js-avatar-container", function (element) { element.classList.add("is-empty"); }); withElementsSetDisplay(".js-current-user-avatar-image", "none"); withElementsSetInnerText( ".js-current-user-initials", currentUserUsername[0].toUpperCase() ); } } function nodeScriptExec(node) { withElements('script', function (el) { eval(el.innerHTML) }, node) } function goBack() { history.go(-1) } window.nodeScriptExec = nodeScriptExec; window.goBack = goBack; ; (function () { window.showNotification = function (text, options) { // Ugly alternative for null coalescing (??) on node 12 const autohide = (options.autohide !== null && options.autohide !== undefined) ? options.autohide : true; const type = options.type || 'success'; const appendIcon = (options.appendIcon !== null && options.appendIcon !== undefined) ? options.appendIcon : true; const notification = document.createElement('div') notification.classList.add( 'notifyjs-custom-base', 'notifyjs-custom-' + type ) notification.addEventListener('click', function () { notification.parentNode.removeChild(notification) }) if (appendIcon) { const icon = document.createElement('div') icon.classList.add('notification-icon') notification.append(icon) switch (type) { case 'success': icon.classList.add('fa', 'fa-check-circle') break case 'error': icon.classList.add('fa', 'fa-times-circle') break } } const content = document.createElement('div') content.classList.add('notification-content') if (options.className) { content.classList.add(options.className) } content.innerHTML = text notification.append(content) const close = document.createElement('div') close.classList.add('notification-close-icon', 'fa', 'fa-times') if (options.onDismiss) { close.addEventListener('click', options.onDismiss) } notification.append(close) if (autohide) { let timeout = autohide === true ? 5000 : parseInt(autohide, 10) setTimeout(function () { if (notification.parentNode) { notification.parentNode.removeChild(notification) } }, timeout) } withId('notifications-container').append(notification) if (type !== 'error') { let eventLabel = text if (/has successfully been added to the cart/.test(eventLabel)) { eventLabel = 'Item has successfully been added to the cart' } else if (/has already been added to the cart/.test(eventLabel)) { eventLabel = 'Item has already been added to the cart' } } } })() ; /*! * JavaScript Cookie v2.2.0 * https://github.com/js-cookie/js-cookie * * Copyright 2006, 2015 Klaus Hartl & Fagner Brack * Released under the MIT license */ ;(function (factory) { var registeredInModuleLoader = false; if (typeof define === 'function' && define.amd) { define(factory); registeredInModuleLoader = true; } if (typeof exports === 'object') { module.exports = factory(); registeredInModuleLoader = true; } if (!registeredInModuleLoader) { var OldCookies = window.Cookies; var api = window.Cookies = factory(); api.noConflict = function () { window.Cookies = OldCookies; return api; }; } }(function () { function extend () { var i = 0; var result = {}; for (; i < arguments.length; i++) { var attributes = arguments[ i ]; for (var key in attributes) { result[key] = attributes[key]; } } return result; } function init (converter) { function api (key, value, attributes) { var result; if (typeof document === 'undefined') { return; } // Write if (arguments.length > 1) { attributes = extend({ path: '/' }, api.defaults, attributes); if (typeof attributes.expires === 'number') { var expires = new Date(); expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); attributes.expires = expires; } // We're using "expires" because "max-age" is not supported by IE attributes.expires = attributes.expires ? attributes.expires.toUTCString() : ''; try { result = JSON.stringify(value); if (/^[\{\[]/.test(result)) { value = result; } } catch (e) {} if (!converter.write) { value = encodeURIComponent(String(value)) .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); } else { value = converter.write(value, key); } key = encodeURIComponent(String(key)); key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); key = key.replace(/[\(\)]/g, escape); var stringifiedAttributes = ''; for (var attributeName in attributes) { if (!attributes[attributeName]) { continue; } stringifiedAttributes += '; ' + attributeName; if (attributes[attributeName] === true) { continue; } stringifiedAttributes += '=' + attributes[attributeName]; } return (document.cookie = key + '=' + value + stringifiedAttributes); } // Read if (!key) { result = {}; } // To prevent the for loop in the first place assign an empty array // in case there are no cookies at all. Also prevents odd result when // calling "get()" var cookies = document.cookie ? document.cookie.split('; ') : []; var rdecode = /(%[0-9A-Z]{2})+/g; var i = 0; for (; i < cookies.length; i++) { var parts = cookies[i].split('='); var cookie = parts.slice(1).join('='); if (!this.json && cookie.charAt(0) === '"') { cookie = cookie.slice(1, -1); } try { var name = parts[0].replace(rdecode, decodeURIComponent); cookie = converter.read ? converter.read(cookie, name) : converter(cookie, name) || cookie.replace(rdecode, decodeURIComponent); if (this.json) { try { cookie = JSON.parse(cookie); } catch (e) {} } if (key === name) { result = cookie; break; } if (!key) { result[name] = cookie; } } catch (e) {} } return result; } api.set = api; api.get = function (key) { return api.call(api, key); }; api.getJSON = function () { return api.apply({ json: true }, [].slice.call(arguments)); }; api.defaults = {}; api.remove = function (key, attributes) { api(key, '', extend(attributes, { expires: -1 })); }; api.withConverter = init; return api; } return init(function () {}); })); // TO-DO: extract this into a fast_pages category. Stop using fast_product_page for everything // // abstract dom controller // ; (function () { window.createAndShowModal = function (data, options) { let html if (data.id) { html = withId(data.id).innerHTML } else { html = data } const modal = createModal(html, options) showModal(modal) } window.reload = function () { document.location.reload() } window.reloadAfterLogin = function () { reload() } window.getData = function (target, event) { if (event) { event.preventDefault() } const dataset = target.dataset const url = !!dataset.url.match(/^\//) ? dataset.url : window.location.pathname + '/' + dataset.url performXHR(dataset.method || 'get', url, function (data) { switch (dataset.onsuccess) { case 'createAndShowModal': createAndShowModal(data, { rootClass: dataset.class }) break case 'showPopover': withId(dataset.target).innerHTML = data showPopover(target, null) break case 'reload': reload() break } }) } window.parseData = function (data) { if (data && data.data && data.data.type) { switch (data.data.type) { case 'cartItems': if (data.meta) { window.pageConfig.cart.size = data.meta.size window.pageConfig.cart.itemIds = data.meta.itemIds window.pageConfig.cart.cartItemIds = data.meta.cartItemIds window.pageConfig.cart.creditsAvailable = data.meta.storeCreditsLeft if (data.meta.item) { window.pageConfig.cart.totalPrice = pageConfig.cart.totalPrice + data.meta.item.price window.pageConfig.cart_items = data.meta.trackingCartItems } personalize(window.pageConfig) } break } } } window.isMobileView = function () { return window.innerWidth 0 && window.searchTracker) { window.searchTracker({ searchTerm: searchQuery, type: 'model', }) } }) } window.showErrorsNotifications = function (errors) { for (let key in errors) { if (typeof errors[key] === 'string' && key !== 'status') { showNotification(errors[key], { type: 'error', autohide: true, }) } } } document.addEventListener('submit', function (e) { const form = e.target const formClasses = form.classList const isSearchForm = formClasses.contains('js-search') const searchButton = form.querySelector('.js-search-button') const isJSform = formClasses.contains('js-form') const isAddToCart = formClasses.contains('js-add-to-cart') if (searchButton) { const icon = searchButton.querySelector('.js-search-button-icon') const loader = searchButton.querySelector('.js-search-button-loader') if (icon && loader) { icon.classList.add('is-hidden') loader.classList.remove('is-hidden') } } const disableFormSubmissions = disabled => { withElements( '[type=submit]', function (el) { el.disabled = disabled }, form ) } const conditionallyAppendInformations = () => form.querySelectorAll('input').forEach((input) => { if (input.name === 'location') { return (input.value = window.location.pathname) } if (input.name === 'utm_statistics[referrer]') { const referrer = Cookies.get('__gtm_referrer') || '' return (input.value = referrer) } if (input.name === 'utm_statistics[raw_utm_string]') { const raw_utm_string = Cookies.get('__gtm_campaign_url') || '' return (input.value = raw_utm_string) } }) conditionallyAppendInformations() if (isSearchForm) { e.preventDefault() sendSearchQueryToAnalytics(e) const formUrl = extractCurrentSearchQuery(form) if (!formUrl) return form.submit() const searchUrl = new URL(formUrl) const searchKeywords = form.querySelector('[name="keywords"]').value searchUrl.searchParams.append('keywords', searchKeywords) return window.location.href = searchUrl.href } if (formClasses.contains('js-purchase-button-form') && !formClasses.contains('js-add-to-cart')) { e.preventDefault() if (window.pageConfig && window.pageConfig && window.pageConfig.product) { const itemAttributes = window.pageConfig.product trackAddToCart(itemAttributes); } } if (isJSform) { e.preventDefault() try { const formData = new FormData(form) if (formClasses.contains('js-purchase-button-form')) { if (window.pageConfig && window.pageConfig.product && window.pageConfig.product.searchQuery) { formData.set('search_query', pageConfig.product.searchQuery) formData.set('index', window.pageConfig.indexTrack) } } if (isAddToCart) { const sendAddToCartActionToAnalytics = () => { const parent = findAncestor('js-fast-listing-item', form) const itemAttributes = getItemData(parent) if (itemAttributes.searchQuery) { formData.set('search_query', itemAttributes.searchQuery) formData.set('index', itemAttributes.index) } trackAddToCart(itemAttributes, false); } sendAddToCartActionToAnalytics() } disableFormSubmissions(true) const appendTwoFaStep = () => { const requiredFields = [ 'user[login]', 'user[password]', 'user[remember_me]', ] for (var [inputField, value] of formData.entries()) { if (requiredFields.includes(inputField)) { document.getElementById('two-fa-second-state-form')[ inputField ].value = value } } withElementsSetDisplay('.form__log-in', 'none') withElementsSetDisplay('.form__two-fa-second-state', 'block') } const handleLoginSessionExpiration = () => { // reload page to get valid session token return window.location.reload() } const formSubmissionCallback = (data, status) => { const isLoginAction = form.action.includes('/2fa-or-login') disableFormSubmissions(false) if (status === 422 && isLoginAction) { return handleLoginSessionExpiration() } data = JSON.parse(data) const isTwoFaForm = data.twoFaEnabled const twoFaIsValid = isTwoFaForm && status === 200 const sucessfulResponse = data.jsonapi || data.success || twoFaIsValid if (sucessfulResponse) { parseData(data) const message = data.message || form.dataset.successmessage const formHasOnSuccessFunction = form.dataset.onsuccess && typeof window[form.dataset.onsuccess] === 'function' const shouldReloadPage = form.dataset.reloadpage === 'true' if (message) { showNotification(message, { type: 'success', autohide: true, }) } if (data.twoFaEnabled) { return appendTwoFaStep() } if (formHasOnSuccessFunction) { window[form.dataset.onsuccess]() } if (shouldReloadPage) { if (location.href.includes('?rating=')) { return window.location.href = location.href.split('?')[0]; } return window.location.reload() } if (data.redirectTo) { disableFormSubmissions(true) window.location = data.redirectTo } } else { const errorMessage = typeof data.error === 'string' ? data.error : data.message const formHasOnErrorFunction = form.dataset.onerror && typeof window[form.dataset.onerror] === 'function' if (formHasOnErrorFunction) { window[form.dataset.onerror]() } if (errorMessage) { showNotification(errorMessage, { type: 'error', autohide: true, }) } else if (data.errors && data.errors instanceof Object && data.errors.length) { showErrorsNotifications(data.errors) } else if (data.errors && data.errors.custom_errors) { showErrorsNotifications(data.errors.custom_errors) } else { showNotification('Something went wrong, please try again', { type: 'error', autohide: true, }) } } } const currentMethod = form.classList.contains('comment-form') ? form.dataset.method : form.method performXHR(currentMethod, form.action, formSubmissionCallback, formData) return false } catch (error) { const isLoginAction = form.action.includes('/2fa-or-login') const isRegistrationAction = form.action.includes('/users') && form .querySelector('button[type="submit"]') .textContent.includes('Register') if (isLoginAction) { const loginErrorContext = { msg: 'Login error', email: form.querySelector('[name="user[login]"]').value, } window.sendErrorToSentry(error, { tags: { section: 'Fast pages login' }, extra: loginErrorContext }) } if (isRegistrationAction) { const registrationErrorContext = { msg: 'Registration error', email: form.querySelector('[name="new_user[email]"]').value, gdprConsent: form.querySelector('[name="new_user[gdpr_consent]"]') .value, } window.sendErrorToSentry(error, { tags: { section: 'Fast pages registration' }, extra: registrationErrorContext }) } return showNotification('An unexpected error ocurred', { type: 'error', autohide: true, }) } } }) function extractCurrentSearchQuery(form) { const params = window.location.href.split('?')[1] const formUrl = new URL(form.action) const skipParams = ['page', 'suggested_keywords', 'keywords'] if (params === undefined) return const searchQuery = new URLSearchParams(params) for (const key of searchQuery.keys()) { if (skipParams.includes(key)) continue formUrl.searchParams.append(key, searchQuery.get(key)) } return formUrl.href } function resetCaptcha(id) { if (document.getElementById(id)) { mtcaptcha.resetUI(id) } } window.resetLoginCaptcha = function () { resetCaptcha('login-captcha') } window.resetRegistrationCaptcha = function () { resetCaptcha('registration-captcha') } })() // // popovers // ; (function () { window.hidePopover = function () { withElements('.popover-container.is-active', function (item) { item.classList.remove('is-active') }) } const showPopoverDelay = 100; let showPopoverLastExecution = 0; window.showPopover = function (container, event) { if ((showPopoverLastExecution + showPopoverDelay) < Date.now()) { // close other popovers withElements('.popover-container.is-active', function (item) { if (item !== container) { item.classList.remove('is-active') } }) if (container) { // block direct-link clicks if (event) { const a = event.target.tagName === 'A' ? event.target : event.target.closest('a') if (a && a.parentNode === container) { event.preventDefault() } } if (event === null || (window.pageConfig && !window.pageConfig.servicesLoaded)) { return } // dont close on popover content click if (!event || (event && !event.target.closest('.popover'))) { if (container.classList.contains('is-active')) { container.classList.remove('is-active') App.events.publish(container, 'popover-closed') } else { container.classList.add('is-active') App.events.publish(container, 'popover-opened') } showPopoverLastExecution = Date.now() } } } } function handlePopoverClick(e) { const container = getContainer(e, 'popover-container') if ( container && container.id === 'login-popover' && window.mountPasswordComponent ) { window.mountPasswordComponent() } showPopover(container, e) } document.addEventListener('click', handlePopoverClick) }()) // // cart // ; (function () { document.addEventListener('click', function (event) { const targetClasses = event.target.classList if (targetClasses.contains('js-checkout-click') && pageConfig && pageConfig.cart_items) { trackProceedToCheckout() } return null }); document.addEventListener('auxclick', function (event) { const targetClasses = event.target.classList if (event.button === 1) { if (targetClasses.contains('js-checkout-click') && pageConfig && pageConfig.cart_items) { trackProceedToCheckout() } } return null }); function trackProceedToCheckout() { let cartItems = []; for (let cartItemId in pageConfig.cart_items) { cartItems.push(prepareItemTracking(pageConfig.cart_items[cartItemId], true, true)[0]) } window.dataLayer && window.dataLayer.push({ event: 'begin_checkout', ecommerce: { currency: 'USD', value: pageConfig.cart.totalPrice, items: cartItems } }) } function trackRemoveFromCart(item_data) { const item = prepareItemTracking(item_data, true, true) window.pageConfig.cart.totalPrice = window.pageConfig.cart.totalPrice - item.price window.dataLayer && window.dataLayer.push({ event: 'remove_from_cart', user_id: window.pageConfig.currentUserId || '', ecommerce: { currency: 'USD', value: item[0]['price'], items: item }, _clear: true, }) } function setCart(html) { withId('top-menu-cart').innerHTML = html nodeScriptExec(withId('top-menu-cart')) } window.getCartAsync = async function () { try { return new Promise((resolve, reject) => { performXHR('get', '/api/internal/cg/cart_items.html', (response, status) => { if (status >= 200 && status < 300) { withId('top-menu-cart').innerHTML = response nodeScriptExec(withId('top-menu-cart')) resolve({ data: response, status, hasItems: window.pageConfig?.cart?.size > 0 }) } else { reject(new Error('Failed to load cart')) } }) }) } catch (error) { console.error('Error in getCartAsync:', error) throw error } } window.removeFromCart = function (context) { const item_id = context.attributes['data-item'].value; trackRemoveFromCart(window.pageConfig.cart_items.filter(function (el) { return el.id == item_id; })[0]) window.pageConfig.cart_items = window.pageConfig.cart_items.filter(function (el) { return el.id != item_id; }); performXHR('delete', context.attributes['data-href'].value, (response) => { setCart(response) App.events.publish('item-removed-from-cart'); window.dispatchEvent(new Event('item-removed-from-cart')); }) if (window.pageConfig.cart_items.length === 0) { hidePopover(); } } function trackGA4ViewCart() { let cartItems = []; for (let cartItem in pageConfig.cart_items) { cartItems.push(prepareItemTracking(pageConfig.cart_items[cartItem], true, true)[0]) } window.dataLayer && window.dataLayer.push({ event: 'view_cart', ecommerce: { currency: 'USD', value: pageConfig.cart.totalPrice, items: cartItems } }) } })() // // tabs // ; (function () { window.setNavTab = function (id, e) { const tabs = getParentWith('#' + id, e.target) withElements( '.cgt-tab, .tab-pane', function (item) { item.classList.remove('is-active', 'cgt-tab--active') }, tabs ) e.target.closest('.cgt-tab').classList.add('cgt-tab--active') withId(id).classList.add('is-active') } window.setTab = function (id, e) { const tabs = getParentWith('#' + id, e.target) withElements( '.tab, .tab-pane', function (item) { item.classList.remove('is-active') }, tabs ) e.target.closest('.tab').classList.add('is-active') withId(id).classList.add('is-active') } })() ; Our website uses cookies to collect statistical visitor data and track interaction with direct marketing communication / improve our website and improve your browsing experience. Please see our Cookie Notice for more information about cookies, data they collect, who may access them, and your rights. Learn more AcceptWeekend Sale🚀 UP TO 50%OFF 🚀Sale ends inFind deals
立即前往 返回首页