├── assets
├── custom.js
├── sparkle.gif
├── section-related-products.css
├── component-show-more.css
├── constants.js
├── password-modal.js
├── section-main-page.css
├── component-list-payment.css
├── component-list-social.css
├── pubsub.js
├── component-totals.css
├── component-list-menu.css
├── component-discounts.css
├── section-contact-form.css
├── show-more.js
├── component-product-model.css
├── newsletter-section.css
├── component-rating.css
├── section-collection-list.css
├── video-section.css
├── component-accordion.css
├── main-search.js
├── product-modal.js
├── component-loading-overlay.css
├── search-form.js
├── product-model.js
├── custom.css
├── component-model-viewer-ui.css
├── component-newsletter.css
├── component-search.css
├── component-pagination.css
├── section-rich-text.css
├── template-collection.css
├── details-disclosure.js
├── section-featured-product.css
├── details-modal.js
├── animations.js
├── theme-editor.js
├── section-featured-blog.css
├── component-price.css
├── component-mega-menu.css
├── localization-form.js
├── slick-theme.css
├── component-modal-video.css
├── share.js
├── magnify.js
├── section-main-blog.css
├── slick.css
├── component-collection-hero.css
├── cart-notification.js
├── component-deferred-media.css
├── section-email-signup-banner.css
├── component-article-card.css
├── customer.js
├── component-cart-notification.css
├── collapsible-content.css
├── section-blog-post.css
├── pickup-availability.js
├── component-pickup-availability.css
├── product-info.js
└── component-cart.css
├── sections
├── cart-drawer.liquid
├── cart-notification-button.liquid
├── cart-live-region-text.liquid
├── upsell-slider.liquid
├── cart-icon-bubble.liquid
├── main-404.liquid
├── footer-group.json
├── apps.liquid
├── header-group.json
├── revy-contents.liquid
├── main-page.liquid
├── custom-liquid.liquid
├── cart-notification-product.liquid
├── page.liquid
├── main-collection-banner.liquid
└── pickup-availability.liquid
├── README.md
├── templates
├── 404.json
├── page.json
├── customers
│ ├── login.json
│ ├── order.json
│ ├── account.json
│ ├── addresses.json
│ ├── register.json
│ ├── reset_password.json
│ └── activate_account.json
├── list-collections.json
├── blog.json
├── page.contact.json
├── search.json
├── cart.json
├── article.json
├── collection.json
├── password.json
├── index.json
└── product.json
└── snippets
├── icon-caret.liquid
├── icon-tumblr.liquid
├── revy-bundle-script.liquid
├── icon-minus.liquid
├── icon-discount.liquid
├── mask-arch.liquid
├── icon-youtube.liquid
├── icon-tiktok.liquid
├── icon-plus.liquid
├── icon-hamburger.liquid
├── icon-arrow.liquid
├── icon-checkmark.liquid
├── icon-tick.liquid
├── icon-close.liquid
├── icon-clipboard.liquid
├── icon-success.liquid
├── icon-play.liquid
├── icon-close-small.liquid
├── icon-facebook.liquid
├── icon-unavailable.liquid
├── icon-cart-empty.liquid
├── icon-vimeo.liquid
├── icon-account.liquid
├── icon-cart.liquid
├── icon-padlock.liquid
├── icon-filter.liquid
├── icon-pause.liquid
├── icon-remove.liquid
├── icon-twitter.liquid
├── icon-error.liquid
├── icon-pinterest.liquid
├── icon-share.liquid
├── icon-instagram.liquid
├── icon-3d-model.liquid
├── icon-zoom.liquid
├── cart-upsell-item.liquid
├── language-localization.liquid
├── cart-upsell.liquid
├── meta-tags.liquid
├── country-localization.liquid
├── icon-snapchat.liquid
├── share-button.liquid
├── product-media-modal.liquid
├── cart-notification.liquid
├── pagination.liquid
├── product-variant-options.liquid
├── email-signup-banner-background-mobile.liquid
├── social-icons.liquid
├── icon-with-text.liquid
├── header-mega-menu.liquid
└── email-signup-banner-background.liquid
/assets/custom.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sections/cart-drawer.liquid:
--------------------------------------------------------------------------------
1 | {%- render 'cart-drawer' -%}
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Shopify Cart Upsell
2 |
3 | This product shows how to create Shopify cart upsell.
--------------------------------------------------------------------------------
/sections/cart-notification-button.liquid:
--------------------------------------------------------------------------------
1 | {{ 'general.cart.view' | t: count: cart.item_count }}
2 |
--------------------------------------------------------------------------------
/assets/sparkle.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liquidshopier/Shopify-Cart-upsell/HEAD/assets/sparkle.gif
--------------------------------------------------------------------------------
/sections/cart-live-region-text.liquid:
--------------------------------------------------------------------------------
1 | {{ 'sections.cart.new_subtotal' | t }}: {{ cart.total_price | money_with_currency }}
2 |
--------------------------------------------------------------------------------
/assets/section-related-products.css:
--------------------------------------------------------------------------------
1 | .related-products {
2 | display: block;
3 | }
4 |
5 | .related-products__heading {
6 | margin: 0 0 3rem;
7 | }
8 |
--------------------------------------------------------------------------------
/templates/404.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-404",
5 | "settings": {}
6 | }
7 | },
8 | "order": [
9 | "main"
10 | ]
11 | }
--------------------------------------------------------------------------------
/assets/component-show-more.css:
--------------------------------------------------------------------------------
1 | .button-show-more {
2 | padding-left: 0;
3 | justify-content: flex-start;
4 | padding-bottom: 1.1rem;
5 | }
6 |
7 | .button-show-more,
8 | .button-show-less {
9 | margin-top: 1.5rem;
10 | }
11 |
--------------------------------------------------------------------------------
/assets/constants.js:
--------------------------------------------------------------------------------
1 | const ON_CHANGE_DEBOUNCE_TIMER = 300;
2 |
3 | const PUB_SUB_EVENTS = {
4 | cartUpdate: 'cart-update',
5 | quantityUpdate: 'quantity-update',
6 | variantChange: 'variant-change',
7 | cartError: 'cart-error',
8 | };
9 |
--------------------------------------------------------------------------------
/sections/upsell-slider.liquid:
--------------------------------------------------------------------------------
1 | {% schema %}
2 | {
3 | "name": "Section name",
4 | "settings": []
5 | }
6 | {% endschema %}
7 |
8 | {% stylesheet %}
9 | {% endstylesheet %}
10 |
11 | {% javascript %}
12 | {% endjavascript %}
--------------------------------------------------------------------------------
/templates/page.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-page",
5 | "settings": {
6 | "padding_top": 28,
7 | "padding_bottom": 28
8 | }
9 | }
10 | },
11 | "order": [
12 | "main"
13 | ]
14 | }
--------------------------------------------------------------------------------
/templates/customers/login.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-login",
5 | "settings": {
6 | "padding_top": 36,
7 | "padding_bottom": 36
8 | }
9 | }
10 | },
11 | "order": [
12 | "main"
13 | ]
14 | }
--------------------------------------------------------------------------------
/templates/customers/order.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-order",
5 | "settings": {
6 | "padding_top": 36,
7 | "padding_bottom": 36
8 | }
9 | }
10 | },
11 | "order": [
12 | "main"
13 | ]
14 | }
--------------------------------------------------------------------------------
/templates/customers/account.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-account",
5 | "settings": {
6 | "padding_top": 36,
7 | "padding_bottom": 36
8 | }
9 | }
10 | },
11 | "order": [
12 | "main"
13 | ]
14 | }
--------------------------------------------------------------------------------
/templates/customers/addresses.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-addresses",
5 | "settings": {
6 | "padding_top": 36,
7 | "padding_bottom": 36
8 | }
9 | }
10 | },
11 | "order": [
12 | "main"
13 | ]
14 | }
--------------------------------------------------------------------------------
/templates/customers/register.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-register",
5 | "settings": {
6 | "padding_top": 36,
7 | "padding_bottom": 36
8 | }
9 | }
10 | },
11 | "order": [
12 | "main"
13 | ]
14 | }
--------------------------------------------------------------------------------
/templates/customers/reset_password.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-reset-password",
5 | "settings": {
6 | "padding_top": 36,
7 | "padding_bottom": 36
8 | }
9 | }
10 | },
11 | "order": [
12 | "main"
13 | ]
14 | }
--------------------------------------------------------------------------------
/templates/customers/activate_account.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-activate-account",
5 | "settings": {
6 | "padding_top": 36,
7 | "padding_bottom": 36
8 | }
9 | }
10 | },
11 | "order": [
12 | "main"
13 | ]
14 | }
--------------------------------------------------------------------------------
/snippets/icon-caret.liquid:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/assets/password-modal.js:
--------------------------------------------------------------------------------
1 | class PasswordModal extends DetailsModal {
2 | constructor() {
3 | super();
4 |
5 | if (this.querySelector('input[aria-invalid="true"]')) this.open({ target: this.querySelector('details') });
6 | }
7 | }
8 |
9 | customElements.define('password-modal', PasswordModal);
10 |
--------------------------------------------------------------------------------
/snippets/icon-tumblr.liquid:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/snippets/revy-bundle-script.liquid:
--------------------------------------------------------------------------------
1 |
7 |
8 |
--------------------------------------------------------------------------------
/snippets/icon-minus.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/snippets/icon-discount.liquid:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/snippets/mask-arch.liquid:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/snippets/icon-youtube.liquid:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/snippets/icon-tiktok.liquid:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/templates/list-collections.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-list-collections",
5 | "settings": {
6 | "title": "Collections",
7 | "sort": "alphabetical",
8 | "image_ratio": "square",
9 | "columns_desktop": 3,
10 | "columns_mobile": "2"
11 | }
12 | }
13 | },
14 | "order": [
15 | "main"
16 | ]
17 | }
--------------------------------------------------------------------------------
/snippets/icon-plus.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/snippets/icon-hamburger.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/templates/blog.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-blog",
5 | "settings": {
6 | "layout": "collage",
7 | "show_image": true,
8 | "image_height": "medium",
9 | "show_date": true,
10 | "show_author": false,
11 | "padding_top": 36,
12 | "padding_bottom": 36
13 | }
14 | }
15 | },
16 | "order": [
17 | "main"
18 | ]
19 | }
--------------------------------------------------------------------------------
/snippets/icon-arrow.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/assets/section-main-page.css:
--------------------------------------------------------------------------------
1 | .page-title {
2 | margin-top: 0;
3 | }
4 |
5 | .main-page-title {
6 | margin-bottom: 3rem;
7 | }
8 |
9 | @media screen and (min-width: 750px) {
10 | .main-page-title {
11 | margin-bottom: 4rem;
12 | }
13 | }
14 |
15 | .page-placeholder-wrapper {
16 | display: flex;
17 | justify-content: center;
18 | }
19 |
20 | .page-placeholder {
21 | width: 52.5rem;
22 | height: 52.5rem;
23 | }
24 |
--------------------------------------------------------------------------------
/snippets/icon-checkmark.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/snippets/icon-tick.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/snippets/icon-close.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/snippets/icon-clipboard.liquid:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/snippets/icon-success.liquid:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/snippets/icon-play.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/assets/component-list-payment.css:
--------------------------------------------------------------------------------
1 | .list-payment {
2 | display: flex;
3 | flex-wrap: wrap;
4 | justify-content: center;
5 | margin: -0.5rem 0;
6 | padding-top: 1rem;
7 | padding-left: 0;
8 | }
9 |
10 | @media screen and (min-width: 750px) {
11 | .list-payment {
12 | justify-content: flex-end;
13 | margin: -0.5rem;
14 | padding-top: 0;
15 | }
16 | }
17 |
18 | .list-payment__item {
19 | align-items: center;
20 | display: flex;
21 | padding: 0.5rem;
22 | }
23 |
--------------------------------------------------------------------------------
/snippets/icon-close-small.liquid:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/snippets/icon-facebook.liquid:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/snippets/icon-unavailable.liquid:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/snippets/icon-cart-empty.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/snippets/icon-vimeo.liquid:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/templates/page.contact.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-page",
5 | "settings": {
6 | "padding_top": 36,
7 | "padding_bottom": 36
8 | }
9 | },
10 | "form": {
11 | "type": "contact-form",
12 | "settings": {
13 | "heading": "",
14 | "heading_size": "h1",
15 | "color_scheme": "background-1",
16 | "padding_top": 36,
17 | "padding_bottom": 36
18 | }
19 | }
20 | },
21 | "order": [
22 | "main",
23 | "form"
24 | ]
25 | }
--------------------------------------------------------------------------------
/sections/cart-icon-bubble.liquid:
--------------------------------------------------------------------------------
1 | {%- liquid
2 | if cart == empty
3 | render 'icon-cart-empty'
4 | else
5 | render 'icon-cart'
6 | endif
7 | -%}
8 | {{ 'templates.cart.cart' | t }}
9 | {%- if cart != empty -%}
10 |
11 | {%- if cart.item_count < 100 -%}
12 | {{ cart.item_count }}
13 | {%- endif -%}
14 | {{ 'sections.header.cart_count' | t: count: cart.item_count }}
15 |
16 | {%- endif -%}
17 |
--------------------------------------------------------------------------------
/assets/component-list-social.css:
--------------------------------------------------------------------------------
1 | .list-social {
2 | display: flex;
3 | flex-wrap: wrap;
4 | justify-content: flex-end;
5 | }
6 |
7 | @media only screen and (max-width: 749px) {
8 | .list-social {
9 | justify-content: center;
10 | }
11 | }
12 |
13 | .list-social__item .icon {
14 | height: 1.8rem;
15 | width: 1.8rem;
16 | }
17 |
18 | .list-social__link {
19 | align-items: center;
20 | display: flex;
21 | padding: 1.4rem;
22 | color: rgb(var(--color-foreground));
23 | }
24 |
25 | .list-social__link:hover .icon {
26 | transform: scale(1.07);
27 | }
28 |
--------------------------------------------------------------------------------
/snippets/icon-account.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/snippets/icon-cart.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/snippets/icon-padlock.liquid:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/snippets/icon-filter.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/sections/main-404.liquid:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 | {{ 'templates.404.subtext' | t }}
16 |
17 |
18 | {{ 'templates.404.title' | t }}
19 |
20 |
21 | {{ 'general.continue_shopping' | t }}
22 |
23 |
24 |
--------------------------------------------------------------------------------
/snippets/icon-pause.liquid:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/assets/pubsub.js:
--------------------------------------------------------------------------------
1 | let subscribers = {};
2 |
3 | function subscribe(eventName, callback) {
4 | if (subscribers[eventName] === undefined) {
5 | subscribers[eventName] = [];
6 | }
7 |
8 | subscribers[eventName] = [...subscribers[eventName], callback];
9 |
10 | return function unsubscribe() {
11 | subscribers[eventName] = subscribers[eventName].filter((cb) => {
12 | return cb !== callback;
13 | });
14 | };
15 | }
16 |
17 | function publish(eventName, data) {
18 | if (subscribers[eventName]) {
19 | subscribers[eventName].forEach((callback) => {
20 | callback(data);
21 | });
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/assets/component-totals.css:
--------------------------------------------------------------------------------
1 | .totals {
2 | display: flex;
3 | justify-content: center;
4 | align-items: flex-end;
5 | }
6 |
7 | .totals > * {
8 | font-size: 1.6rem;
9 | margin: 0;
10 | }
11 |
12 | .totals > h2 {
13 | font-size: calc(var(--font-heading-scale) * 1.6rem);
14 | }
15 |
16 | .totals * {
17 | line-height: 1;
18 | }
19 |
20 | .totals > * + * {
21 | margin-left: 2rem;
22 | }
23 |
24 | .totals__subtotal-value {
25 | font-size: 1.8rem;
26 | }
27 |
28 | .cart__ctas + .totals {
29 | margin-top: 2rem;
30 | }
31 |
32 | @media all and (min-width: 750px) {
33 | .totals {
34 | justify-content: flex-end;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/assets/component-list-menu.css:
--------------------------------------------------------------------------------
1 | .list-menu--right {
2 | right: 0;
3 | }
4 |
5 | .list-menu--disclosure {
6 | position: absolute;
7 | min-width: 100%;
8 | width: 20rem;
9 | border: 1px solid rgba(var(--color-foreground), 0.2);
10 | }
11 |
12 | .list-menu--disclosure:focus {
13 | outline: none;
14 | }
15 |
16 | .list-menu__item--active {
17 | text-decoration: underline;
18 | text-underline-offset: 0.3rem;
19 | }
20 |
21 | .list-menu__item--active:hover {
22 | text-decoration-thickness: 0.2rem;
23 | }
24 |
25 | .list-menu--disclosure.localization-selector {
26 | max-height: 18rem;
27 | overflow: auto;
28 | width: 10rem;
29 | padding: 0.5rem;
30 | }
31 |
--------------------------------------------------------------------------------
/snippets/icon-remove.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/snippets/icon-twitter.liquid:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/templates/search.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-search",
5 | "settings": {
6 | "columns_desktop": 4,
7 | "image_ratio": "adapt",
8 | "image_shape": "default",
9 | "show_secondary_image": false,
10 | "show_vendor": false,
11 | "show_rating": false,
12 | "enable_filtering": true,
13 | "filter_type": "horizontal",
14 | "enable_sorting": true,
15 | "article_show_date": true,
16 | "article_show_author": false,
17 | "columns_mobile": "2",
18 | "padding_top": 36,
19 | "padding_bottom": 36
20 | }
21 | }
22 | },
23 | "order": [
24 | "main"
25 | ]
26 | }
--------------------------------------------------------------------------------
/assets/component-discounts.css:
--------------------------------------------------------------------------------
1 | .discounts {
2 | font-size: 1.2rem;
3 | }
4 |
5 | .discounts__discount {
6 | display: flex;
7 | align-items: center;
8 | line-height: calc(1 + 0.5 / var(--font-body-scale));
9 | }
10 |
11 | .discounts__discount svg {
12 | color: rgba(var(--color-button), var(--alpha-button-background));
13 | }
14 |
15 | .discounts__discount--position {
16 | justify-content: center;
17 | }
18 |
19 | @media screen and (min-width: 750px) {
20 | .discounts__discount--position {
21 | justify-content: flex-end;
22 | }
23 | }
24 |
25 | .discounts__discount > .icon {
26 | color: rgb(var(--color-foreground));
27 | width: 1.2rem;
28 | height: 1.2rem;
29 | margin-right: 0.7rem;
30 | }
31 |
--------------------------------------------------------------------------------
/templates/cart.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "cart-items": {
4 | "type": "main-cart-items",
5 | "settings": {
6 | "padding_top": 36,
7 | "padding_bottom": 36
8 | }
9 | },
10 | "cart-footer": {
11 | "type": "main-cart-footer",
12 | "blocks": {
13 | "subtotal": {
14 | "type": "subtotal",
15 | "settings": {}
16 | },
17 | "buttons": {
18 | "type": "buttons",
19 | "settings": {}
20 | }
21 | },
22 | "block_order": [
23 | "subtotal",
24 | "buttons"
25 | ],
26 | "settings": {}
27 | }
28 | },
29 | "order": [
30 | "cart-items",
31 | "cart-footer"
32 | ]
33 | }
--------------------------------------------------------------------------------
/sections/footer-group.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "t:sections.footer.name",
3 | "type": "footer",
4 | "sections": {
5 | "footer": {
6 | "type": "footer",
7 | "settings": {
8 | "color_scheme": "background-1",
9 | "newsletter_enable": true,
10 | "newsletter_heading": "Subscribe to our emails",
11 | "enable_follow_on_shop": true,
12 | "show_social": true,
13 | "enable_country_selector": true,
14 | "enable_language_selector": true,
15 | "payment_enable": true,
16 | "show_policy": false,
17 | "margin_top": 36,
18 | "padding_top": 36,
19 | "padding_bottom": 36
20 | }
21 | }
22 | },
23 | "order": [
24 | "footer"
25 | ]
26 | }
--------------------------------------------------------------------------------
/assets/section-contact-form.css:
--------------------------------------------------------------------------------
1 | .contact img {
2 | max-width: 100%;
3 | }
4 |
5 | .contact .form__message {
6 | align-items: flex-start;
7 | }
8 |
9 | .contact .icon-success {
10 | margin-top: 0.2rem;
11 | }
12 |
13 | .contact .field {
14 | margin-bottom: 1.5rem;
15 | }
16 |
17 | @media screen and (min-width: 750px) {
18 | .contact .field {
19 | margin-bottom: 2rem;
20 | }
21 | }
22 |
23 | .contact__button {
24 | margin-top: 3rem;
25 | }
26 |
27 | @media screen and (min-width: 750px) {
28 | .contact__button {
29 | margin-top: 4rem;
30 | }
31 | }
32 |
33 | @media screen and (min-width: 750px) {
34 | .contact__fields {
35 | display: grid;
36 | grid-template-columns: repeat(2, 1fr);
37 | grid-column-gap: 2rem;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/sections/apps.liquid:
--------------------------------------------------------------------------------
1 |
2 | {%- for block in section.blocks -%}
3 | {% render block %}
4 | {%- endfor -%}
5 |
6 |
7 | {% schema %}
8 | {
9 | "name": "t:sections.apps.name",
10 | "tag": "section",
11 | "class": "section",
12 | "settings": [
13 | {
14 | "type": "checkbox",
15 | "id": "include_margins",
16 | "default": true,
17 | "label": "t:sections.apps.settings.include_margins.label"
18 | }
19 | ],
20 | "blocks": [
21 | {
22 | "type": "@app"
23 | }
24 | ],
25 | "presets": [
26 | {
27 | "name": "t:sections.apps.presets.name"
28 | }
29 | ]
30 | }
31 | {% endschema %}
32 |
--------------------------------------------------------------------------------
/templates/article.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-article",
5 | "blocks": {
6 | "featured_image": {
7 | "type": "featured_image",
8 | "settings": {
9 | "image_height": "adapt"
10 | }
11 | },
12 | "title": {
13 | "type": "title",
14 | "settings": {
15 | "blog_show_date": true,
16 | "blog_show_author": false
17 | }
18 | },
19 | "share": {
20 | "type": "share",
21 | "settings": {
22 | "share_label": "Share"
23 | }
24 | },
25 | "content": {
26 | "type": "content",
27 | "settings": {}
28 | }
29 | },
30 | "block_order": [
31 | "featured_image",
32 | "title",
33 | "share",
34 | "content"
35 | ],
36 | "settings": {}
37 | }
38 | },
39 | "order": [
40 | "main"
41 | ]
42 | }
--------------------------------------------------------------------------------
/snippets/icon-error.liquid:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/templates/collection.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "banner": {
4 | "type": "main-collection-banner",
5 | "settings": {
6 | "show_collection_description": true,
7 | "show_collection_image": false,
8 | "color_scheme": "background-1"
9 | }
10 | },
11 | "product-grid": {
12 | "type": "main-collection-product-grid",
13 | "settings": {
14 | "products_per_page": 16,
15 | "columns_desktop": 4,
16 | "image_ratio": "adapt",
17 | "image_shape": "default",
18 | "show_secondary_image": false,
19 | "show_vendor": false,
20 | "show_rating": false,
21 | "enable_quick_add": false,
22 | "enable_filtering": true,
23 | "filter_type": "horizontal",
24 | "enable_sorting": true,
25 | "columns_mobile": "2",
26 | "padding_top": 36,
27 | "padding_bottom": 36
28 | }
29 | }
30 | },
31 | "order": [
32 | "banner",
33 | "product-grid"
34 | ]
35 | }
--------------------------------------------------------------------------------
/assets/show-more.js:
--------------------------------------------------------------------------------
1 | class ShowMoreButton extends HTMLElement {
2 | constructor() {
3 | super();
4 | const button = this.querySelector('button');
5 | button.addEventListener('click', (event) => {
6 | this.expandShowMore(event);
7 | const nextElementToFocus = event.target.closest('.parent-display').querySelector('.show-more-item');
8 | if (nextElementToFocus && !nextElementToFocus.classList.contains('hidden')) {
9 | nextElementToFocus.querySelector('input').focus();
10 | }
11 | });
12 | }
13 | expandShowMore(event) {
14 | const parentDisplay = event.target.closest('[id^="Show-More-"]').closest('.parent-display');
15 | const parentWrap = parentDisplay.querySelector('.parent-wrap');
16 | this.querySelectorAll('.label-text').forEach((element) => element.classList.toggle('hidden'));
17 | parentDisplay.querySelectorAll('.show-more-item').forEach((item) => item.classList.toggle('hidden'));
18 | }
19 | }
20 |
21 | customElements.define('show-more-button', ShowMoreButton);
22 |
--------------------------------------------------------------------------------
/assets/component-product-model.css:
--------------------------------------------------------------------------------
1 | .product__xr-button {
2 | background: rgba(var(--color-foreground), 0.08);
3 | color: rgb(var(--color-foreground));
4 | margin: 1rem auto;
5 | box-shadow: none;
6 | display: flex;
7 | }
8 |
9 | .button.product__xr-button:hover {
10 | box-shadow: none;
11 | }
12 |
13 | .product__xr-button[data-shopify-xr-hidden] {
14 | visibility: hidden;
15 | }
16 |
17 | .shopify-design-mode .product__xr-button[data-shopify-xr-hidden] {
18 | display: none;
19 | }
20 |
21 | @media screen and (max-width: 749px) {
22 | slider-component .product__xr-button {
23 | display: none;
24 | }
25 |
26 | .active .product__xr-button:not([data-shopify-xr-hidden]) {
27 | display: block;
28 | }
29 | }
30 |
31 | @media screen and (min-width: 750px) {
32 | slider-component + .button.product__xr-button {
33 | display: none;
34 | }
35 |
36 | .product__xr-button[data-shopify-xr-hidden] {
37 | display: none;
38 | }
39 | }
40 |
41 | .product__xr-button .icon {
42 | width: 1.4rem;
43 | margin-right: 1rem;
44 | }
45 |
--------------------------------------------------------------------------------
/snippets/icon-pinterest.liquid:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/assets/newsletter-section.css:
--------------------------------------------------------------------------------
1 | .newsletter__wrapper {
2 | padding-right: calc(4rem / var(--font-body-scale));
3 | padding-left: calc(4rem / var(--font-body-scale));
4 | }
5 |
6 | @media screen and (min-width: 750px) {
7 | .newsletter__wrapper {
8 | padding-right: 9rem;
9 | padding-left: 9rem;
10 | }
11 | }
12 |
13 | .newsletter__wrapper > * {
14 | margin-top: 0;
15 | margin-bottom: 0;
16 | }
17 |
18 | .newsletter__wrapper > * + * {
19 | margin-top: 2rem;
20 | }
21 |
22 | .newsletter__wrapper > * + .newsletter-form {
23 | margin-top: 3rem;
24 | }
25 |
26 | .newsletter__subheading {
27 | max-width: 70rem;
28 | margin-left: auto;
29 | margin-right: auto;
30 | }
31 |
32 | .newsletter__wrapper .newsletter-form__field-wrapper {
33 | max-width: 36rem;
34 | }
35 |
36 | .newsletter-form__field-wrapper .newsletter-form__message {
37 | margin-top: 1.5rem;
38 | }
39 |
40 | .newsletter__button {
41 | margin-top: 3rem;
42 | width: fit-content;
43 | }
44 |
45 | @media screen and (min-width: 750px) {
46 | .newsletter__button {
47 | flex-shrink: 0;
48 | margin: 0 0 0 1rem;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/snippets/icon-share.liquid:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/templates/password.json:
--------------------------------------------------------------------------------
1 | {
2 | "layout": "password",
3 | "sections": {
4 | "main": {
5 | "type": "email-signup-banner",
6 | "blocks": {
7 | "heading": {
8 | "type": "heading",
9 | "settings": {
10 | "heading": "Opening soon",
11 | "heading_size": "h1"
12 | }
13 | },
14 | "paragraph": {
15 | "type": "paragraph",
16 | "settings": {
17 | "text": "Be the first to know when we launch.<\/p>",
18 | "text_style": "body"
19 | }
20 | },
21 | "email_form": {
22 | "type": "email_form",
23 | "settings": {}
24 | }
25 | },
26 | "block_order": [
27 | "heading",
28 | "paragraph",
29 | "email_form"
30 | ],
31 | "settings": {
32 | "image_overlay_opacity": 0,
33 | "show_background_image": true,
34 | "image_height": "medium",
35 | "desktop_content_position": "middle-center",
36 | "show_text_box": true,
37 | "desktop_content_alignment": "center",
38 | "color_scheme": "background-1",
39 | "mobile_content_alignment": "center",
40 | "show_text_below": true
41 | }
42 | }
43 | },
44 | "order": [
45 | "main"
46 | ]
47 | }
--------------------------------------------------------------------------------
/snippets/icon-instagram.liquid:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/sections/header-group.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "t:sections.header.name",
3 | "type": "header",
4 | "sections": {
5 | "announcement-bar": {
6 | "type": "announcement-bar",
7 | "blocks": {
8 | "announcement-bar-0": {
9 | "type": "announcement",
10 | "settings": {
11 | "text": "Welcome to our store",
12 | "link": ""
13 | }
14 | }
15 | },
16 | "block_order": [
17 | "announcement-bar-0"
18 | ],
19 | "settings": {
20 | "color_scheme": "background-1",
21 | "show_line_separator": true,
22 | "auto_rotate": false,
23 | "change_slides_speed": 5
24 | }
25 | },
26 | "header": {
27 | "type": "header",
28 | "settings": {
29 | "logo_position": "middle-left",
30 | "menu": "main-menu",
31 | "menu_type_desktop": "dropdown",
32 | "sticky_header_type": "on-scroll-up",
33 | "show_line_separator": true,
34 | "color_scheme": "background-1",
35 | "enable_country_selector": false,
36 | "enable_language_selector": false,
37 | "mobile_logo_position": "center",
38 | "margin_bottom": 0,
39 | "padding_top": 20,
40 | "padding_bottom": 20
41 | }
42 | }
43 | },
44 | "order": [
45 | "announcement-bar",
46 | "header"
47 | ]
48 | }
--------------------------------------------------------------------------------
/snippets/icon-3d-model.liquid:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/assets/component-rating.css:
--------------------------------------------------------------------------------
1 | .rating {
2 | display: inline-block;
3 | margin: 0;
4 | }
5 |
6 | .product .rating-star {
7 | --letter-spacing: 0.8;
8 | --font-size: 1.7;
9 | }
10 |
11 | .card-wrapper .rating-star {
12 | --letter-spacing: 0.7;
13 | --font-size: 1.4;
14 | }
15 |
16 | .rating-star {
17 | --color-rating-star: rgb(var(--color-foreground));
18 | --percent: calc(
19 | (
20 | var(--rating) / var(--rating-max) + var(--rating-decimal) * var(--font-size) /
21 | (var(--rating-max) * (var(--letter-spacing) + var(--font-size)))
22 | ) * 100%
23 | );
24 | letter-spacing: calc(var(--letter-spacing) * 1rem);
25 | font-size: calc(var(--font-size) * 1rem);
26 | line-height: 1;
27 | display: inline-block;
28 | font-family: Times;
29 | margin: 0;
30 | }
31 |
32 | .rating-star::before {
33 | content: '★★★★★';
34 | background: linear-gradient(
35 | 90deg,
36 | var(--color-rating-star) var(--percent),
37 | rgba(var(--color-foreground), 0.15) var(--percent)
38 | );
39 | -webkit-background-clip: text;
40 | -webkit-text-fill-color: transparent;
41 | }
42 |
43 | .rating-text {
44 | display: none;
45 | }
46 |
47 | .rating-count {
48 | display: inline-block;
49 | margin: 0;
50 | }
51 |
52 | @media (forced-colors: active) {
53 | .rating {
54 | display: none;
55 | }
56 |
57 | .rating-text {
58 | display: block;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/assets/section-collection-list.css:
--------------------------------------------------------------------------------
1 | .collection-list {
2 | margin-top: 0;
3 | margin-bottom: 0;
4 | }
5 |
6 | .collection-list-title {
7 | margin: 0;
8 | }
9 |
10 | @media screen and (max-width: 749px) {
11 | .collection-list:not(.slider) {
12 | padding-left: 0;
13 | padding-right: 0;
14 | }
15 |
16 | .section-collection-list .page-width {
17 | padding-left: 0;
18 | padding-right: 0;
19 | }
20 |
21 | .section-collection-list .collection-list:not(.slider) {
22 | padding-left: 1.5rem;
23 | padding-right: 1.5rem;
24 | }
25 | }
26 |
27 | .collection-list__item:only-child {
28 | max-width: 100%;
29 | width: 100%;
30 | }
31 |
32 | @media screen and (max-width: 749px) {
33 | .slider.collection-list--1-items {
34 | padding-bottom: 0;
35 | }
36 | }
37 |
38 | @media screen and (min-width: 750px) and (max-width: 989px) {
39 | .slider.collection-list--1-items,
40 | .slider.collection-list--2-items,
41 | .slider.collection-list--3-items,
42 | .slider.collection-list--4-items {
43 | padding-bottom: 0;
44 | }
45 | }
46 |
47 | @media screen and (min-width: 750px) {
48 | .collection-list__item a:hover {
49 | box-shadow: none;
50 | }
51 | }
52 |
53 | @media screen and (max-width: 989px) {
54 | .collection-list.slider .collection-list__item {
55 | max-width: 100%;
56 | }
57 | }
58 |
59 | .collection-list-view-all {
60 | margin-top: 2rem;
61 | }
62 |
--------------------------------------------------------------------------------
/assets/video-section.css:
--------------------------------------------------------------------------------
1 | .video-section__media {
2 | --ratio-percent: 56.25%;
3 | position: relative;
4 | padding-bottom: calc(var(--ratio-percent) - var(--media-border-width));
5 | }
6 |
7 | /* Needed for gradient continuity with or without animation so that transparent PNG images come up as we would expect */
8 | .scroll-trigger:where(.gradient.video-section__media) {
9 | background: transparent;
10 | }
11 |
12 | .video-section__media.global-media-settings--full-width {
13 | padding-bottom: var(--ratio-percent);
14 | }
15 |
16 | .video-section__media.deferred-media {
17 | box-shadow: var(--media-shadow-horizontal-offset) var(--media-shadow-vertical-offset) var(--media-shadow-blur-radius)
18 | rgba(var(--color-shadow), var(--media-shadow-opacity));
19 | }
20 |
21 | .video-section__media.deferred-media:after {
22 | content: none;
23 | }
24 |
25 | .video-section__poster.deferred-media__poster:focus {
26 | outline-offset: 0.3rem;
27 | }
28 |
29 | .video-section__media iframe {
30 | background-color: rgba(var(--color-foreground), 0.03);
31 | border: 0;
32 | }
33 |
34 | .video-section__poster,
35 | .video-section__media iframe,
36 | .video-section__media video {
37 | position: absolute;
38 | width: 100%;
39 | height: 100%;
40 | }
41 |
42 | .video-section__media video {
43 | background: #000000;
44 | }
45 |
46 | .video-section__media.media-fit-cover video {
47 | object-fit: cover;
48 | }
49 |
--------------------------------------------------------------------------------
/assets/component-accordion.css:
--------------------------------------------------------------------------------
1 | .accordion summary {
2 | display: flex;
3 | position: relative;
4 | line-height: 1;
5 | padding: 1.5rem 0;
6 | }
7 |
8 | .accordion .summary__title {
9 | display: flex;
10 | flex: 1;
11 | }
12 |
13 | .accordion .summary__title + .icon-caret {
14 | height: calc(var(--font-heading-scale) * 0.6rem);
15 | }
16 |
17 | .accordion + .accordion {
18 | margin-top: 0;
19 | border-top: none;
20 | }
21 |
22 | .accordion {
23 | margin-top: 2.5rem;
24 | margin-bottom: 0;
25 | border-top: 0.1rem solid rgba(var(--color-foreground), 0.08);
26 | border-bottom: 0.1rem solid rgba(var(--color-foreground), 0.08);
27 | }
28 |
29 | .accordion__title {
30 | display: inline-block;
31 | max-width: calc(100% - 6rem);
32 | min-height: 1.6rem;
33 | margin: 0;
34 | word-break: break-word;
35 | }
36 |
37 | .accordion .icon-accordion {
38 | align-self: center;
39 | fill: rgb(var(--color-foreground));
40 | height: calc(var(--font-heading-scale) * 2rem);
41 | margin-right: calc(var(--font-heading-scale) * 1rem);
42 | width: calc(var(--font-heading-scale) * 2rem);
43 | }
44 |
45 | .accordion details[open] > summary .icon-caret {
46 | transform: rotate(180deg);
47 | }
48 |
49 | .accordion__content {
50 | margin-bottom: 1.5rem;
51 | word-break: break-word;
52 | overflow-x: auto;
53 | padding: 0 0.6rem;
54 | }
55 |
56 | .accordion__content img {
57 | max-width: 100%;
58 | }
59 |
--------------------------------------------------------------------------------
/assets/main-search.js:
--------------------------------------------------------------------------------
1 | class MainSearch extends SearchForm {
2 | constructor() {
3 | super();
4 | this.allSearchInputs = document.querySelectorAll('input[type="search"]');
5 | this.setupEventListeners();
6 | }
7 |
8 | setupEventListeners() {
9 | let allSearchForms = [];
10 | this.allSearchInputs.forEach((input) => allSearchForms.push(input.form));
11 | this.input.addEventListener('focus', this.onInputFocus.bind(this));
12 | if (allSearchForms.length < 2) return;
13 | allSearchForms.forEach((form) => form.addEventListener('reset', this.onFormReset.bind(this)));
14 | this.allSearchInputs.forEach((input) => input.addEventListener('input', this.onInput.bind(this)));
15 | }
16 |
17 | onFormReset(event) {
18 | super.onFormReset(event);
19 | if (super.shouldResetForm()) {
20 | this.keepInSync('', this.input);
21 | }
22 | }
23 |
24 | onInput(event) {
25 | const target = event.target;
26 | this.keepInSync(target.value, target);
27 | }
28 |
29 | onInputFocus() {
30 | const isSmallScreen = window.innerWidth < 750;
31 | if (isSmallScreen) {
32 | this.scrollIntoView({ behavior: 'smooth' });
33 | }
34 | }
35 |
36 | keepInSync(value, target) {
37 | this.allSearchInputs.forEach((input) => {
38 | if (input !== target) {
39 | input.value = value;
40 | }
41 | });
42 | }
43 | }
44 |
45 | customElements.define('main-search', MainSearch);
46 |
--------------------------------------------------------------------------------
/snippets/icon-zoom.liquid:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/product-modal.js:
--------------------------------------------------------------------------------
1 | if (!customElements.get('product-modal')) {
2 | customElements.define(
3 | 'product-modal',
4 | class ProductModal extends ModalDialog {
5 | constructor() {
6 | super();
7 | }
8 |
9 | hide() {
10 | super.hide();
11 | }
12 |
13 | show(opener) {
14 | super.show(opener);
15 | this.showActiveMedia();
16 | }
17 |
18 | showActiveMedia() {
19 | this.querySelectorAll(
20 | `[data-media-id]:not([data-media-id="${this.openedBy.getAttribute('data-media-id')}"])`
21 | ).forEach((element) => {
22 | element.classList.remove('active');
23 | });
24 | const activeMedia = this.querySelector(`[data-media-id="${this.openedBy.getAttribute('data-media-id')}"]`);
25 | const activeMediaTemplate = activeMedia.querySelector('template');
26 | const activeMediaContent = activeMediaTemplate ? activeMediaTemplate.content : null;
27 | activeMedia.classList.add('active');
28 | activeMedia.scrollIntoView();
29 |
30 | const container = this.querySelector('[role="document"]');
31 | container.scrollLeft = (activeMedia.width - container.clientWidth) / 2;
32 |
33 | if (
34 | activeMedia.nodeName == 'DEFERRED-MEDIA' &&
35 | activeMediaContent &&
36 | activeMediaContent.querySelector('.js-youtube')
37 | )
38 | activeMedia.loadContent();
39 | }
40 | }
41 | );
42 | }
43 |
--------------------------------------------------------------------------------
/assets/component-loading-overlay.css:
--------------------------------------------------------------------------------
1 | .loading-overlay {
2 | position: absolute;
3 | z-index: 1;
4 | width: 1.8rem;
5 | }
6 |
7 | @media screen and (max-width: 749px) {
8 | .loading-overlay {
9 | top: 0;
10 | right: 0;
11 | }
12 | }
13 |
14 | @media screen and (min-width: 750px) {
15 | .loading-overlay {
16 | left: 0;
17 | }
18 | }
19 |
20 | .loading-overlay__spinner {
21 | width: 1.8rem;
22 | display: inline-block;
23 | }
24 |
25 | .spinner {
26 | animation: rotator 1.4s linear infinite;
27 | }
28 |
29 | @keyframes rotator {
30 | 0% {
31 | transform: rotate(0deg);
32 | }
33 | 100% {
34 | transform: rotate(270deg);
35 | }
36 | }
37 |
38 | .path {
39 | stroke-dasharray: 280;
40 | stroke-dashoffset: 0;
41 | transform-origin: center;
42 | stroke: rgb(var(--color-foreground));
43 | animation: dash 1.4s ease-in-out infinite;
44 | }
45 |
46 | @media screen and (forced-colors: active) {
47 | .path {
48 | stroke: CanvasText;
49 | }
50 | }
51 |
52 | @keyframes dash {
53 | 0% {
54 | stroke-dashoffset: 280;
55 | }
56 | 50% {
57 | stroke-dashoffset: 75;
58 | transform: rotate(135deg);
59 | }
60 | 100% {
61 | stroke-dashoffset: 280;
62 | transform: rotate(450deg);
63 | }
64 | }
65 |
66 | .loading-overlay:not(.hidden) + .cart-item__price-wrapper,
67 | .loading-overlay:not(.hidden) ~ cart-remove-button {
68 | opacity: 50%;
69 | }
70 |
71 | .loading-overlay:not(.hidden) ~ cart-remove-button {
72 | pointer-events: none;
73 | cursor: default;
74 | }
75 |
--------------------------------------------------------------------------------
/snippets/cart-upsell-item.liquid:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
19 |
20 |
21 |
22 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/assets/search-form.js:
--------------------------------------------------------------------------------
1 | class SearchForm extends HTMLElement {
2 | constructor() {
3 | super();
4 | this.input = this.querySelector('input[type="search"]');
5 | this.resetButton = this.querySelector('button[type="reset"]');
6 |
7 | if (this.input) {
8 | this.input.form.addEventListener('reset', this.onFormReset.bind(this));
9 | this.input.addEventListener(
10 | 'input',
11 | debounce((event) => {
12 | this.onChange(event);
13 | }, 300).bind(this)
14 | );
15 | }
16 | }
17 |
18 | toggleResetButton() {
19 | const resetIsHidden = this.resetButton.classList.contains('hidden');
20 | if (this.input.value.length > 0 && resetIsHidden) {
21 | this.resetButton.classList.remove('hidden');
22 | } else if (this.input.value.length === 0 && !resetIsHidden) {
23 | this.resetButton.classList.add('hidden');
24 | }
25 | }
26 |
27 | onChange() {
28 | this.toggleResetButton();
29 | }
30 |
31 | shouldResetForm() {
32 | return !document.querySelector('[aria-selected="true"] a');
33 | }
34 |
35 | onFormReset(event) {
36 | // Prevent default so the form reset doesn't set the value gotten from the url on page load
37 | event.preventDefault();
38 | // Don't reset if the user has selected an element on the predictive search dropdown
39 | if (this.shouldResetForm()) {
40 | this.input.value = '';
41 | this.input.focus();
42 | this.toggleResetButton();
43 | }
44 | }
45 | }
46 |
47 | customElements.define('search-form', SearchForm);
48 |
--------------------------------------------------------------------------------
/sections/revy-contents.liquid:
--------------------------------------------------------------------------------
1 |
2 | {% for block in section.blocks %}
3 |
4 |
5 | {{ block.settings.revy-content-section }}
6 |
7 |
8 | {% endfor %}
9 |
10 |
11 | {% schema %}
12 | {
13 | "name": "Revy Contents",
14 | "max_blocks": 20,
15 | "blocks" : [
16 | {
17 | "type": "html",
18 | "name": "Revy Content",
19 | "settings": [
20 | {
21 | "type": "textarea",
22 | "id": "revy-content-section",
23 | "default": "",
24 | "label": "Revy Content"
25 | }
26 | ]
27 | }
28 | ],
29 | "presets": [
30 | {
31 | "name": "Revy Content",
32 | "category": "Revy Apps",
33 | "blocks": [
34 | {
35 | "type": "html"
36 | }
37 | ]
38 | }
39 | ]
40 | }
41 | {% endschema %}
42 |
43 |
44 | {% stylesheet %}
45 | .revy-custom-content-section-content {
46 | display: -webkit-box;
47 | display: -ms-flexbox;
48 | display: flex;
49 | -webkit-box-align: center;
50 | -ms-flex-align: center;
51 | align-items: center;
52 | -webkit-box-pack: center;
53 | -ms-flex-pack: center;
54 | justify-content: center;
55 | margin: 10px;
56 | max-width: 100%;
57 | -ms-flex-wrap: wrap;
58 | flex-wrap: wrap;
59 | }
60 | {% endstylesheet %}
61 |
62 | {% javascript %}
63 | {% endjavascript %}
64 |
--------------------------------------------------------------------------------
/assets/product-model.js:
--------------------------------------------------------------------------------
1 | if (!customElements.get('product-model')) {
2 | customElements.define(
3 | 'product-model',
4 | class ProductModel extends DeferredMedia {
5 | constructor() {
6 | super();
7 | }
8 |
9 | loadContent() {
10 | super.loadContent();
11 |
12 | Shopify.loadFeatures([
13 | {
14 | name: 'model-viewer-ui',
15 | version: '1.0',
16 | onLoad: this.setupModelViewerUI.bind(this),
17 | },
18 | ]);
19 | }
20 |
21 | setupModelViewerUI(errors) {
22 | if (errors) return;
23 |
24 | this.modelViewerUI = new Shopify.ModelViewerUI(this.querySelector('model-viewer'));
25 | }
26 | }
27 | );
28 | }
29 |
30 | window.ProductModel = {
31 | loadShopifyXR() {
32 | Shopify.loadFeatures([
33 | {
34 | name: 'shopify-xr',
35 | version: '1.0',
36 | onLoad: this.setupShopifyXR.bind(this),
37 | },
38 | ]);
39 | },
40 |
41 | setupShopifyXR(errors) {
42 | if (errors) return;
43 |
44 | if (!window.ShopifyXR) {
45 | document.addEventListener('shopify_xr_initialized', () => this.setupShopifyXR());
46 | return;
47 | }
48 |
49 | document.querySelectorAll('[id^="ProductJSON-"]').forEach((modelJSON) => {
50 | window.ShopifyXR.addModels(JSON.parse(modelJSON.textContent));
51 | modelJSON.remove();
52 | });
53 | window.ShopifyXR.setupXRElements();
54 | },
55 | };
56 |
57 | window.addEventListener('DOMContentLoaded', () => {
58 | if (window.ProductModel) window.ProductModel.loadShopifyXR();
59 | });
60 |
--------------------------------------------------------------------------------
/assets/custom.css:
--------------------------------------------------------------------------------
1 | .cartupsell-item {
2 | border: 1px solid #dbdbdb;
3 | border-radius: 5px;
4 | }
5 |
6 | .cartupsell-slick-slider {
7 | width: 100%;
8 | }
9 |
10 | .cartupsell-panel {
11 | width: 100%;
12 | padding: 10px;
13 | border-radius: 5px;
14 | display: flex;
15 | column-gap:10px;
16 | }
17 |
18 | .cartupsell-image-panel a {
19 | width: 100%;
20 | height: 100%;
21 | }
22 |
23 | .cartupsell-image-panel .cartupsell-img {
24 | width: 100%;
25 | height: 100%;
26 | object-fit: cover;
27 | border-radius: 5px;
28 | }
29 |
30 | .cartupsell-product-title a {
31 | display: inline;
32 | font-size: 18px;
33 | font-weight: bold;
34 | color: #3f3f3f;
35 | text-decoration: none;
36 | }
37 |
38 | .btn-add-order {
39 | font-size: 15px;
40 | cursor: pointer;
41 | background-color: #1973b1;
42 | color: #fff;
43 | width: 100%;
44 | padding: 15px;
45 | border-radius: 3px;
46 | border: none;
47 | }
48 |
49 | .cartupsell-data-panel {
50 | width: 100%;
51 | }
52 |
53 | .cartupsell-product-price {
54 | font-size: 18px;
55 | color: #909090;
56 | }
57 |
58 | .cartupsell-product-data {
59 | margin-bottom: 5px;
60 | }
61 |
62 | .slick-dots li.slick-active button:before,
63 | .cartupsell-slick-slider .slick-dots li button:before {
64 | font-size: 35px;
65 | }
66 |
67 | #saved_money {
68 | display: none;
69 | }
70 |
71 | @media (max-width: 767px) {
72 | .returning-user .badge {
73 | display: none !important;
74 | }
75 | .returning-user #saved_money {
76 | display: inline-block !important;
77 | }
78 | }
--------------------------------------------------------------------------------
/assets/component-model-viewer-ui.css:
--------------------------------------------------------------------------------
1 | .shopify-model-viewer-ui .shopify-model-viewer-ui__controls-area {
2 | background: rgb(var(--color-background));
3 | border-color: rgba(var(--color-foreground), 0.04);
4 | }
5 |
6 | .shopify-model-viewer-ui .shopify-model-viewer-ui__button {
7 | color: rgba(var(--color-foreground), 0.75);
8 | }
9 |
10 | .shopify-model-viewer-ui .shopify-model-viewer-ui__button--control:hover {
11 | color: rgba(var(--color-foreground), 0.55);
12 | }
13 |
14 | .shopify-model-viewer-ui .shopify-model-viewer-ui__button--control:active,
15 | .shopify-model-viewer-ui .shopify-model-viewer-ui__button--control.focus-visible:focus {
16 | color: rgba(var(--color-foreground), 0.55);
17 | background: rgba(var(--color-foreground), 0.04);
18 | }
19 |
20 | .shopify-model-viewer-ui .shopify-model-viewer-ui__button--control:not(:last-child):after {
21 | border-color: rgba(var(--color-foreground), 0.04);
22 | }
23 |
24 | .shopify-model-viewer-ui .shopify-model-viewer-ui__button--poster {
25 | border-radius: 50%;
26 | color: rgb(var(--color-foreground));
27 | background: rgb(var(--color-background));
28 | border-color: rgba(var(--color-foreground), 0.1);
29 | transform: translate(-50%, -50%) scale(1);
30 | transition: transform var(--duration-short) ease, color var(--duration-short) ease;
31 | }
32 |
33 | .shopify-model-viewer-ui .shopify-model-viewer-ui__poster-control-icon {
34 | width: 4.8rem;
35 | height: 4.8rem;
36 | margin-top: 0.3rem;
37 | }
38 |
39 | .shopify-model-viewer-ui .shopify-model-viewer-ui__button--poster:hover,
40 | .shopify-model-viewer-ui .shopify-model-viewer-ui__button--poster:focus {
41 | transform: translate(-50%, -50%) scale(1.1);
42 | }
43 |
--------------------------------------------------------------------------------
/snippets/language-localization.liquid:
--------------------------------------------------------------------------------
1 | {%- comment -%}
2 | Renders the language picker for the localization form
3 |
4 | Accepts:
5 | - localPosition: pass in the position in which the form is coming up to create specific IDs
6 | {%- endcomment -%}
7 |
8 |
9 |
19 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/assets/component-newsletter.css:
--------------------------------------------------------------------------------
1 | .newsletter-form {
2 | display: flex;
3 | flex-direction: column;
4 | justify-content: center;
5 | align-items: center;
6 | width: 100%;
7 | position: relative;
8 | }
9 |
10 | @media screen and (min-width: 750px) {
11 | .newsletter-form {
12 | align-items: flex-start;
13 | margin: 0 auto;
14 | max-width: 36rem;
15 | }
16 | }
17 |
18 | .newsletter-form__field-wrapper {
19 | width: 100%;
20 | }
21 |
22 | .newsletter-form__field-wrapper .field__input {
23 | padding-right: 5rem;
24 | }
25 |
26 | .newsletter-form__field-wrapper .field {
27 | z-index: 0;
28 | }
29 |
30 | .newsletter-form__message {
31 | justify-content: center;
32 | margin-bottom: 0;
33 | }
34 |
35 | .newsletter-form__message--success {
36 | margin-top: 2rem;
37 | }
38 |
39 | @media screen and (min-width: 750px) {
40 | .newsletter-form__message {
41 | justify-content: flex-start;
42 | }
43 | }
44 |
45 | .newsletter-form__button {
46 | width: 4.4rem;
47 | margin: 0;
48 | right: var(--inputs-border-width);
49 | top: 0;
50 | height: 100%;
51 | z-index: 2;
52 | }
53 |
54 | .newsletter-form__button:focus-visible {
55 | box-shadow: 0 0 0 0.3rem rgb(var(--color-background)), 0 0 0 0.4rem rgba(var(--color-foreground));
56 | background-color: rgb(var(--color-background));
57 | }
58 |
59 | .newsletter-form__button:focus {
60 | box-shadow: 0 0 0 0.3rem rgb(var(--color-background)), 0 0 0 0.4rem rgba(var(--color-foreground));
61 | background-color: rgb(var(--color-background));
62 | }
63 |
64 | .newsletter-form__button:not(:focus-visible):not(.focused) {
65 | box-shadow: inherit;
66 | background-color: inherit;
67 | }
68 |
69 | .newsletter-form__button .icon {
70 | width: 1.5rem;
71 | }
72 |
--------------------------------------------------------------------------------
/snippets/cart-upsell.liquid:
--------------------------------------------------------------------------------
1 | {% assign u_product1 = all_products[settings.u_product1] %}
2 | {% assign u_product2 = all_products[settings.u_product2] %}
3 | {% assign u_product3 = all_products[settings.u_product3] %}
4 |
5 | {% assign is_upsell1 = false %}
6 | {% assign is_upsell2 = false %}
7 | {% assign is_upsell3 = false %}
8 |
9 | {% for item in cart.items %}
10 | {% if item.product.id == u_product1.id %}
11 | {% assign is_upsell1 = true %}
12 | {% elsif item.product.id == u_product2.id %}
13 | {% assign is_upsell2 = true %}
14 | {% elsif item.product.id == u_product3.id %}
15 | {% assign is_upsell3 = true %}
16 | {% endif %}
17 | {% endfor %}
18 |
19 | {% unless is_upsell1 and is_upsell2 and is_upsell3 %}
20 |
21 |
22 | {% if settings.u_product1 and is_upsell1 == false %}
23 | {% render 'cart-upsell-item', upsell_product: u_product1 %}
24 | {% endif %}
25 | {% if settings.u_product2 and is_upsell2 == false %}
26 | {% render 'cart-upsell-item', upsell_product: u_product2 %}
27 | {% endif %}
28 | {% if settings.u_product3 and is_upsell3 == false %}
29 | {% render 'cart-upsell-item', upsell_product: u_product3 %}
30 | {% endif %}
31 |
32 |
33 | {% endunless %}
34 |
35 |
--------------------------------------------------------------------------------
/assets/component-search.css:
--------------------------------------------------------------------------------
1 | .search__input.field__input {
2 | padding-right: 9.8rem;
3 | }
4 |
5 | .search__button {
6 | right: var(--inputs-border-width);
7 | top: var(--inputs-border-width);
8 | }
9 |
10 | .reset__button {
11 | right: calc(var(--inputs-border-width) + 4.4rem);
12 | top: var(--inputs-border-width);
13 | }
14 |
15 | .reset__button:not(:focus-visible)::after {
16 | border-right: 0.1rem solid rgba(var(--color-foreground), 0.08);
17 | display: block;
18 | height: calc(100% - 1.6rem);
19 | content: '';
20 | position: absolute;
21 | right: 0;
22 | }
23 |
24 | .reset__button:not(:focus)::after {
25 | border-right: 0.1rem solid rgba(var(--color-foreground), 0.08);
26 | display: block;
27 | height: calc(100% - 1.8rem);
28 | content: '';
29 | position: absolute;
30 | right: 0;
31 | }
32 |
33 | .search__button:focus-visible,
34 | .reset__button:focus-visible {
35 | background-color: rgb(var(--color-background));
36 | z-index: 4;
37 | }
38 |
39 | .search__button:focus,
40 | .reset__button:focus {
41 | background-color: rgb(var(--color-background));
42 | z-index: 4;
43 | }
44 |
45 | .search__button:not(:focus-visible):not(.focused),
46 | .reset__button:not(:focus-visible):not(.focused) {
47 | box-shadow: inherit;
48 | background-color: inherit;
49 | }
50 |
51 | .search__button:hover .icon,
52 | .reset__button:hover .icon {
53 | transform: scale(1.07);
54 | }
55 |
56 | .search__button .icon {
57 | height: 1.8rem;
58 | width: 1.8rem;
59 | }
60 |
61 | .reset__button .icon.icon-close {
62 | height: 1.8rem;
63 | width: 1.8rem;
64 | stroke-width: 0.1rem;
65 | }
66 |
67 | /* Remove extra spacing for search inputs in Safari */
68 | input::-webkit-search-decoration {
69 | -webkit-appearance: none;
70 | }
71 |
--------------------------------------------------------------------------------
/assets/component-pagination.css:
--------------------------------------------------------------------------------
1 | .pagination-wrapper {
2 | margin-top: 4rem;
3 | }
4 |
5 | @media screen and (min-width: 990px) {
6 | .pagination-wrapper {
7 | margin-top: 5rem;
8 | }
9 | }
10 |
11 | .pagination__list {
12 | display: flex;
13 | flex-wrap: wrap;
14 | justify-content: center;
15 | }
16 |
17 | .pagination__list > li {
18 | flex: 1 0 4.4rem;
19 | max-width: 4.4rem;
20 | }
21 |
22 | .pagination__list > li:not(:last-child) {
23 | margin-right: 1rem;
24 | }
25 |
26 | .pagination__item {
27 | color: rgb(var(--color-foreground));
28 | display: inline-flex;
29 | justify-content: center;
30 | align-items: center;
31 | position: relative;
32 | height: 4.5rem;
33 | width: 100%;
34 | padding: 0;
35 | text-decoration: none;
36 | }
37 |
38 | a.pagination__item:hover::after {
39 | height: 0.1rem;
40 | }
41 |
42 | .pagination__item .icon-caret {
43 | height: 0.6rem;
44 | }
45 |
46 | .pagination__item--current::after {
47 | height: 0.1rem;
48 | }
49 |
50 | .pagination__item--current::after,
51 | .pagination__item:hover::after {
52 | content: '';
53 | display: block;
54 | width: 2rem;
55 | position: absolute;
56 | bottom: 8px;
57 | left: 50%;
58 | transform: translateX(-50%);
59 | background-color: currentColor;
60 | }
61 |
62 | .pagination__item--next .icon {
63 | margin-left: -0.2rem;
64 | transform: rotate(90deg);
65 | }
66 |
67 | .pagination__item--next:hover .icon {
68 | transform: rotate(90deg) scale(1.07);
69 | }
70 |
71 | .pagination__item--prev .icon {
72 | margin-right: -0.2rem;
73 | transform: rotate(-90deg);
74 | }
75 |
76 | .pagination__item--prev:hover .icon {
77 | transform: rotate(-90deg) scale(1.07);
78 | }
79 |
80 | .pagination__item-arrow:hover::after {
81 | display: none;
82 | }
83 |
--------------------------------------------------------------------------------
/assets/section-rich-text.css:
--------------------------------------------------------------------------------
1 | .rich-text {
2 | z-index: 1;
3 | }
4 |
5 | .rich-text__wrapper {
6 | display: flex;
7 | justify-content: center;
8 | width: calc(100% - 4rem / var(--font-body-scale));
9 | }
10 |
11 | .rich-text:not(.rich-text--full-width) .rich-text__wrapper {
12 | margin: auto;
13 | width: calc(100% - 8rem / var(--font-body-scale));
14 | }
15 |
16 | .rich-text__blocks {
17 | width: 100%;
18 | }
19 |
20 | @media screen and (min-width: 750px) {
21 | .rich-text__wrapper {
22 | width: 100%;
23 | }
24 |
25 | .rich-text__wrapper--left {
26 | justify-content: flex-start;
27 | }
28 |
29 | .rich-text__wrapper--right {
30 | justify-content: flex-end;
31 | }
32 |
33 | .rich-text__blocks {
34 | max-width: 50rem;
35 | }
36 | }
37 |
38 | @media screen and (min-width: 990px) {
39 | .rich-text__blocks {
40 | max-width: 78rem;
41 | }
42 | }
43 |
44 | .rich-text__blocks * {
45 | overflow-wrap: break-word;
46 | }
47 |
48 | .rich-text__blocks > * {
49 | margin-top: 0;
50 | margin-bottom: 0;
51 | }
52 |
53 | .rich-text__blocks > * + * {
54 | margin-top: 2rem;
55 | }
56 |
57 | .rich-text__blocks > * + a {
58 | margin-top: 3rem;
59 | }
60 |
61 | .rich-text__buttons {
62 | display: inline-flex;
63 | justify-content: center;
64 | flex-wrap: wrap;
65 | gap: 1rem;
66 | width: 100%;
67 | max-width: 45rem;
68 | word-break: break-word;
69 | }
70 |
71 | .rich-text__buttons--multiple > * {
72 | flex-grow: 1;
73 | min-width: 22rem;
74 | }
75 |
76 | .rich-text__buttons + .rich-text__buttons {
77 | margin-top: 1rem;
78 | }
79 |
80 | .rich-text__blocks.left .rich-text__buttons {
81 | justify-content: flex-start;
82 | }
83 |
84 | .rich-text__blocks.right .rich-text__buttons {
85 | justify-content: flex-end;
86 | }
87 |
--------------------------------------------------------------------------------
/assets/template-collection.css:
--------------------------------------------------------------------------------
1 | @media screen and (max-width: 749px) {
2 | .collection .grid__item:only-child {
3 | flex: 0 0 100%;
4 | max-width: 100%;
5 | }
6 | }
7 |
8 | @media screen and (max-width: 989px) {
9 | .collection .slider.slider--tablet {
10 | margin-bottom: 1.5rem;
11 | }
12 | }
13 |
14 | .collection .loading-overlay {
15 | top: 0;
16 | right: 0;
17 | bottom: 0;
18 | left: 0;
19 | display: none;
20 | width: 100%;
21 | padding: 0 1.5rem;
22 | opacity: 0.7;
23 | }
24 |
25 | @media screen and (min-width: 750px) {
26 | .collection .loading-overlay {
27 | padding-left: 5rem;
28 | padding-right: 5rem;
29 | }
30 | }
31 |
32 | .collection.loading .loading-overlay {
33 | display: block;
34 | }
35 |
36 | .collection--empty .title-wrapper {
37 | margin-top: 10rem;
38 | margin-bottom: 15rem;
39 | }
40 |
41 | @media screen and (max-width: 989px) {
42 | .collection .slider--tablet.product-grid {
43 | scroll-padding-left: 1.5rem;
44 | }
45 | }
46 |
47 | .collection__description > * {
48 | margin: 0;
49 | }
50 |
51 | .collection__title.title-wrapper {
52 | margin-bottom: 2.5rem;
53 | }
54 |
55 | .collection__title .title:not(:only-child) {
56 | margin-bottom: 1rem;
57 | }
58 |
59 | @media screen and (min-width: 990px) {
60 | .collection__title--desktop-slider .title {
61 | margin-bottom: 2.5rem;
62 | }
63 |
64 | .collection__title.title-wrapper--self-padded-tablet-down {
65 | padding: 0 5rem;
66 | }
67 |
68 | .collection slider-component:not(.page-width-desktop) {
69 | padding: 0;
70 | }
71 |
72 | .collection--full-width slider-component:not(.slider-component-desktop) {
73 | padding: 0 1.5rem;
74 | max-width: none;
75 | }
76 | }
77 |
78 | .collection__view-all a:not(.link) {
79 | margin-top: 1rem;
80 | }
81 |
--------------------------------------------------------------------------------
/sections/main-page.liquid:
--------------------------------------------------------------------------------
1 | {{ 'section-main-page.css' | asset_url | stylesheet_tag }}
2 |
3 | {%- style -%}
4 | .section-{{ section.id }}-padding {
5 | padding-top: {{ section.settings.padding_top | times: 0.75 | round: 0 }}px;
6 | padding-bottom: {{ section.settings.padding_bottom | times: 0.75 | round: 0 }}px;
7 | }
8 |
9 | @media screen and (min-width: 750px) {
10 | .section-{{ section.id }}-padding {
11 | padding-top: {{ section.settings.padding_top }}px;
12 | padding-bottom: {{ section.settings.padding_bottom }}px;
13 | }
14 | }
15 | {%- endstyle -%}
16 |
17 |
18 |
19 | {{ page.title | escape }}
20 |
21 |
22 | {{ page.content }}
23 |
24 |
25 |
26 | {% schema %}
27 | {
28 | "name": "t:sections.main-page.name",
29 | "tag": "section",
30 | "class": "section",
31 | "settings": [
32 | {
33 | "type": "header",
34 | "content": "t:sections.all.padding.section_padding_heading"
35 | },
36 | {
37 | "type": "range",
38 | "id": "padding_top",
39 | "min": 0,
40 | "max": 100,
41 | "step": 4,
42 | "unit": "px",
43 | "label": "t:sections.all.padding.padding_top",
44 | "default": 36
45 | },
46 | {
47 | "type": "range",
48 | "id": "padding_bottom",
49 | "min": 0,
50 | "max": 100,
51 | "step": 4,
52 | "unit": "px",
53 | "label": "t:sections.all.padding.padding_bottom",
54 | "default": 36
55 | }
56 | ]
57 | }
58 | {% endschema %}
59 |
--------------------------------------------------------------------------------
/assets/details-disclosure.js:
--------------------------------------------------------------------------------
1 | class DetailsDisclosure extends HTMLElement {
2 | constructor() {
3 | super();
4 | this.mainDetailsToggle = this.querySelector('details');
5 | this.content = this.mainDetailsToggle.querySelector('summary').nextElementSibling;
6 |
7 | this.mainDetailsToggle.addEventListener('focusout', this.onFocusOut.bind(this));
8 | this.mainDetailsToggle.addEventListener('toggle', this.onToggle.bind(this));
9 | }
10 |
11 | onFocusOut() {
12 | setTimeout(() => {
13 | if (!this.contains(document.activeElement)) this.close();
14 | });
15 | }
16 |
17 | onToggle() {
18 | if (!this.animations) this.animations = this.content.getAnimations();
19 |
20 | if (this.mainDetailsToggle.hasAttribute('open')) {
21 | this.animations.forEach((animation) => animation.play());
22 | } else {
23 | this.animations.forEach((animation) => animation.cancel());
24 | }
25 | }
26 |
27 | close() {
28 | this.mainDetailsToggle.removeAttribute('open');
29 | this.mainDetailsToggle.querySelector('summary').setAttribute('aria-expanded', false);
30 | }
31 | }
32 |
33 | customElements.define('details-disclosure', DetailsDisclosure);
34 |
35 | class HeaderMenu extends DetailsDisclosure {
36 | constructor() {
37 | super();
38 | this.header = document.querySelector('.header-wrapper');
39 | }
40 |
41 | onToggle() {
42 | if (!this.header) return;
43 | this.header.preventHide = this.mainDetailsToggle.open;
44 |
45 | if (document.documentElement.style.getPropertyValue('--header-bottom-position-desktop') !== '') return;
46 | document.documentElement.style.setProperty(
47 | '--header-bottom-position-desktop',
48 | `${Math.floor(this.header.getBoundingClientRect().bottom)}px`
49 | );
50 | }
51 | }
52 |
53 | customElements.define('header-menu', HeaderMenu);
54 |
--------------------------------------------------------------------------------
/assets/section-featured-product.css:
--------------------------------------------------------------------------------
1 | .featured-product .product__media-list {
2 | width: 100%;
3 | margin: 0;
4 | padding-bottom: 0;
5 | }
6 |
7 | .featured-product .product-media-container {
8 | margin-bottom: var(--media-shadow-vertical-offset);
9 | max-width: 100%;
10 | }
11 |
12 | .featured-product .product__media-item {
13 | padding-left: 0;
14 | width: 100%;
15 | }
16 |
17 | .featured-product .product__media-item:not(:first-child) {
18 | display: none;
19 | }
20 |
21 | .featured-product .placeholder-svg {
22 | display: block;
23 | height: auto;
24 | width: 100%;
25 | }
26 |
27 | .background-secondary .featured-product {
28 | padding: 2.5rem;
29 | }
30 |
31 | .featured-product .share-button:nth-last-child(2) {
32 | display: inline-flex;
33 | }
34 |
35 | .share-button + .product__view-details {
36 | display: inline-flex;
37 | float: right;
38 | align-items: center;
39 | }
40 |
41 | .share-button + .product__view-details::after {
42 | content: '';
43 | clear: both;
44 | display: table;
45 | }
46 |
47 | @media screen and (min-width: 750px) {
48 | .featured-product .product__media-item {
49 | padding-bottom: 0;
50 | }
51 |
52 | .background-secondary .featured-product {
53 | padding: 5rem;
54 | }
55 | }
56 |
57 | @media screen and (min-width: 990px) {
58 | .background-secondary .featured-product:not(.product--no-media) > .product__info-wrapper {
59 | padding: 0 0 0 5rem;
60 | }
61 |
62 | .background-secondary .featured-product:not(.product--no-media).product--right > .product__info-wrapper {
63 | padding: 0 5rem 0 0;
64 | }
65 |
66 | .featured-product:not(.product--no-media) > .product__info-wrapper {
67 | padding: 0 7rem;
68 | }
69 |
70 | .background-secondary .featured-product {
71 | padding: 6rem 7rem;
72 | position: relative;
73 | z-index: 1;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/snippets/meta-tags.liquid:
--------------------------------------------------------------------------------
1 | {%- liquid
2 | assign og_title = page_title | default: shop.name
3 | assign og_url = canonical_url | default: request.origin
4 | assign og_type = 'website'
5 | assign og_description = page_description | default: shop.description | default: shop.name
6 |
7 | if request.page_type == 'product'
8 | assign og_type = 'product'
9 | elsif request.page_type == 'article'
10 | assign og_type = 'article'
11 | elsif request.page_type == 'password'
12 | assign og_url = request.origin
13 | endif
14 | %}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | {%- if page_image -%}
23 |
24 |
25 |
26 |
27 | {%- endif -%}
28 |
29 | {%- if request.page_type == 'product' -%}
30 |
31 |
32 | {%- endif -%}
33 |
34 | {%- if settings.social_twitter_link != blank -%}
35 |
36 | {%- endif -%}
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/assets/details-modal.js:
--------------------------------------------------------------------------------
1 | class DetailsModal extends HTMLElement {
2 | constructor() {
3 | super();
4 | this.detailsContainer = this.querySelector('details');
5 | this.summaryToggle = this.querySelector('summary');
6 |
7 | this.detailsContainer.addEventListener('keyup', (event) => event.code.toUpperCase() === 'ESCAPE' && this.close());
8 | this.summaryToggle.addEventListener('click', this.onSummaryClick.bind(this));
9 | this.querySelector('button[type="button"]').addEventListener('click', this.close.bind(this));
10 |
11 | this.summaryToggle.setAttribute('role', 'button');
12 | }
13 |
14 | isOpen() {
15 | return this.detailsContainer.hasAttribute('open');
16 | }
17 |
18 | onSummaryClick(event) {
19 | event.preventDefault();
20 | event.target.closest('details').hasAttribute('open') ? this.close() : this.open(event);
21 | }
22 |
23 | onBodyClick(event) {
24 | if (!this.contains(event.target) || event.target.classList.contains('modal-overlay')) this.close(false);
25 | }
26 |
27 | open(event) {
28 | this.onBodyClickEvent = this.onBodyClickEvent || this.onBodyClick.bind(this);
29 | event.target.closest('details').setAttribute('open', true);
30 | document.body.addEventListener('click', this.onBodyClickEvent);
31 | document.body.classList.add('overflow-hidden');
32 |
33 | trapFocus(
34 | this.detailsContainer.querySelector('[tabindex="-1"]'),
35 | this.detailsContainer.querySelector('input:not([type="hidden"])')
36 | );
37 | }
38 |
39 | close(focusToggle = true) {
40 | removeTrapFocus(focusToggle ? this.summaryToggle : null);
41 | this.detailsContainer.removeAttribute('open');
42 | document.body.removeEventListener('click', this.onBodyClickEvent);
43 | document.body.classList.remove('overflow-hidden');
44 | }
45 | }
46 |
47 | customElements.define('details-modal', DetailsModal);
48 |
--------------------------------------------------------------------------------
/snippets/country-localization.liquid:
--------------------------------------------------------------------------------
1 | {%- comment -%}
2 | Renders the country picker for the localization form
3 |
4 | Accepts:
5 | - localPosition: pass in the position in which the form is coming up to create specific IDs
6 | {%- endcomment -%}
7 |
8 |
9 |
22 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/snippets/icon-snapchat.liquid:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/sections/custom-liquid.liquid:
--------------------------------------------------------------------------------
1 | {%- style -%}
2 | .section-{{ section.id }}-padding {
3 | padding-top: calc({{ section.settings.padding_top }}px * 0.75);
4 | padding-bottom: calc({{ section.settings.padding_bottom }}px * 0.75);
5 | }
6 |
7 | @media screen and (min-width: 750px) {
8 | .section-{{ section.id }}-padding {
9 | padding-top: {{ section.settings.padding_top }}px;
10 | padding-bottom: {{ section.settings.padding_bottom }}px;
11 | }
12 | }
13 | {%- endstyle -%}
14 |
15 |
16 | {{ section.settings.custom_liquid }}
17 |
18 |
19 |
20 | {% schema %}
21 | {
22 | "name": "t:sections.custom-liquid.name",
23 | "tag": "section",
24 | "class": "section",
25 | "settings": [
26 | {
27 | "type": "liquid",
28 | "id": "custom_liquid",
29 | "label": "t:sections.custom-liquid.settings.custom_liquid.label",
30 | "info": "t:sections.custom-liquid.settings.custom_liquid.info"
31 | },
32 | {
33 | "type": "color_scheme",
34 | "id": "color_scheme",
35 | "label": "t:sections.all.colors.label",
36 | "default": "background-1"
37 | },
38 | {
39 | "type": "header",
40 | "content": "t:sections.all.padding.section_padding_heading"
41 | },
42 | {
43 | "type": "range",
44 | "id": "padding_top",
45 | "min": 0,
46 | "max": 100,
47 | "step": 4,
48 | "unit": "px",
49 | "label": "t:sections.all.padding.padding_top",
50 | "default": 40
51 | },
52 | {
53 | "type": "range",
54 | "id": "padding_bottom",
55 | "min": 0,
56 | "max": 100,
57 | "step": 4,
58 | "unit": "px",
59 | "label": "t:sections.all.padding.padding_bottom",
60 | "default": 52
61 | }
62 | ],
63 | "presets": [
64 | {
65 | "name": "t:sections.custom-liquid.presets.name"
66 | }
67 | ]
68 | }
69 | {% endschema %}
70 |
--------------------------------------------------------------------------------
/snippets/share-button.liquid:
--------------------------------------------------------------------------------
1 | {% comment %}
2 | Renders share button.
3 | Accepts:
4 | - block: {Object} passes in the block information.
5 | - share_link: {String} url to be added to the input the user will get/copy.
6 |
7 | Usage:
8 | {% render 'share-button',
9 | block: block,
10 | share_link: share_url
11 | %}
12 | {% endcomment %}
13 |
14 |
15 |
16 |
20 |
21 |
22 | {% render 'icon-share' %}
23 | {{ block.settings.share_label | escape }}
24 |
25 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/assets/animations.js:
--------------------------------------------------------------------------------
1 | const SCROLL_ANIMATION_TRIGGER_CLASSNAME = 'scroll-trigger';
2 | const SCROLL_ANIMATION_OFFSCREEN_CLASSNAME = 'scroll-trigger--offscreen';
3 | const SCROLL_ANIMATION_CANCEL_CLASSNAME = 'scroll-trigger--cancel';
4 |
5 | function onIntersection(elements, observer) {
6 | elements.forEach((element, index) => {
7 | if (element.isIntersecting) {
8 | const elementTarget = element.target;
9 | if (elementTarget.classList.contains(SCROLL_ANIMATION_OFFSCREEN_CLASSNAME)) {
10 | elementTarget.classList.remove(SCROLL_ANIMATION_OFFSCREEN_CLASSNAME);
11 | if (elementTarget.hasAttribute('data-cascade'))
12 | elementTarget.setAttribute('style', `--animation-order: ${index};`);
13 | }
14 | observer.unobserve(elementTarget);
15 | } else {
16 | element.target.classList.add(SCROLL_ANIMATION_OFFSCREEN_CLASSNAME);
17 | element.target.classList.remove(SCROLL_ANIMATION_CANCEL_CLASSNAME);
18 | }
19 | });
20 | }
21 |
22 | function initializeScrollAnimationTrigger(rootEl = document, isDesignModeEvent = false) {
23 | const animationTriggerElements = Array.from(rootEl.getElementsByClassName(SCROLL_ANIMATION_TRIGGER_CLASSNAME));
24 | if (animationTriggerElements.length === 0) return;
25 |
26 | if (isDesignModeEvent) {
27 | animationTriggerElements.forEach((element) => {
28 | element.classList.add('scroll-trigger--design-mode');
29 | });
30 | return;
31 | }
32 |
33 | const observer = new IntersectionObserver(onIntersection, {
34 | rootMargin: '0px 0px -50px 0px',
35 | });
36 | animationTriggerElements.forEach((element) => observer.observe(element));
37 | }
38 |
39 | window.addEventListener('DOMContentLoaded', () => initializeScrollAnimationTrigger());
40 |
41 | if (Shopify.designMode) {
42 | document.addEventListener('shopify:section:load', (event) => initializeScrollAnimationTrigger(event.target, true));
43 | document.addEventListener('shopify:section:reorder', () => initializeScrollAnimationTrigger(document, true));
44 | }
45 |
--------------------------------------------------------------------------------
/assets/theme-editor.js:
--------------------------------------------------------------------------------
1 | function hideProductModal() {
2 | const productModal = document.querySelectorAll('product-modal[open]');
3 | productModal && productModal.forEach((modal) => modal.hide());
4 | }
5 |
6 | document.addEventListener('shopify:block:select', function (event) {
7 | hideProductModal();
8 | const blockSelectedIsSlide = event.target.classList.contains('slideshow__slide');
9 | if (!blockSelectedIsSlide) return;
10 |
11 | const parentSlideshowComponent = event.target.closest('slideshow-component');
12 | parentSlideshowComponent.pause();
13 |
14 | setTimeout(function () {
15 | parentSlideshowComponent.slider.scrollTo({
16 | left: event.target.offsetLeft,
17 | });
18 | }, 200);
19 | });
20 |
21 | document.addEventListener('shopify:block:deselect', function (event) {
22 | const blockDeselectedIsSlide = event.target.classList.contains('slideshow__slide');
23 | if (!blockDeselectedIsSlide) return;
24 | const parentSlideshowComponent = event.target.closest('slideshow-component');
25 | if (parentSlideshowComponent.autoplayButtonIsSetToPlay) parentSlideshowComponent.play();
26 | });
27 |
28 | document.addEventListener('shopify:section:load', () => {
29 | hideProductModal();
30 | const zoomOnHoverScript = document.querySelector('[id^=EnableZoomOnHover]');
31 | if (!zoomOnHoverScript) return;
32 | if (zoomOnHoverScript) {
33 | const newScriptTag = document.createElement('script');
34 | newScriptTag.src = zoomOnHoverScript.src;
35 | zoomOnHoverScript.parentNode.replaceChild(newScriptTag, zoomOnHoverScript);
36 | }
37 | });
38 |
39 | document.addEventListener('shopify:section:reorder', () => hideProductModal());
40 |
41 | document.addEventListener('shopify:section:select', () => hideProductModal());
42 |
43 | document.addEventListener('shopify:section:deselect', () => hideProductModal());
44 |
45 | document.addEventListener('shopify:inspector:activate', () => hideProductModal());
46 |
47 | document.addEventListener('shopify:inspector:deactivate', () => hideProductModal());
48 |
--------------------------------------------------------------------------------
/assets/section-featured-blog.css:
--------------------------------------------------------------------------------
1 | .blog-placeholder {
2 | margin: 0 1.5rem;
3 | background: rgb(var(--color-background));
4 | }
5 |
6 | @media screen and (min-width: 750px) {
7 | .blog-placeholder {
8 | text-align: center;
9 | width: 50%;
10 | margin: 0;
11 | }
12 | }
13 |
14 | .blog-placeholder__content {
15 | padding: 3rem;
16 | background: rgba(var(--color-foreground), 0.04);
17 | }
18 |
19 | .blog-placeholder .placeholder {
20 | position: relative;
21 | }
22 |
23 | .blog-placeholder .placeholder .placeholder-svg {
24 | height: auto;
25 | }
26 |
27 | .blog-placeholder h2 {
28 | margin: 0;
29 | }
30 |
31 | .blog-placeholder .rte-width {
32 | margin-top: 1.2rem;
33 | color: rgba(var(--color-foreground), 0.75);
34 | }
35 |
36 | @media screen and (min-width: 990px) {
37 | .grid--1-col-desktop .article-card .card__content {
38 | text-align: center;
39 | }
40 | }
41 |
42 | .blog__title {
43 | margin: 0;
44 | }
45 |
46 | .blog__posts.articles-wrapper {
47 | margin-bottom: 1rem;
48 | }
49 |
50 | @media screen and (min-width: 990px) {
51 | .blog__posts.articles-wrapper {
52 | margin-bottom: 0;
53 | }
54 | }
55 |
56 | .blog__posts.articles-wrapper .article {
57 | scroll-snap-align: start;
58 | }
59 |
60 | @media screen and (max-width: 749px) {
61 | .blog__post.article {
62 | width: calc(100% - 3rem - var(--grid-mobile-horizontal-spacing));
63 | }
64 | }
65 |
66 | .background-secondary .blog-placeholder__content {
67 | background-color: rgb(var(--color-background));
68 | }
69 |
70 | .blog__posts .card-wrapper {
71 | width: 100%;
72 | }
73 |
74 | .blog__button {
75 | margin-top: 3rem;
76 | }
77 |
78 | @media screen and (min-width: 750px) {
79 | .blog__button {
80 | margin-top: 5rem;
81 | }
82 | }
83 |
84 | /* check for flexbox gap in older Safari versions */
85 | @supports not (inset: 10px) {
86 | @media screen and (min-width: 750px) {
87 | .blog__posts .article + .article {
88 | margin-left: var(--grid-desktop-horizontal-spacing);
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/snippets/product-media-modal.liquid:
--------------------------------------------------------------------------------
1 | {% comment %}
2 | Renders a product media modal. Also see 'product-media-gallery'
3 |
4 | Accepts:
5 | - product: {Object} Product liquid object
6 | - variant_images: {Array} Product images associated with a variant
7 |
8 | Usage:
9 | {% render 'product-media-modal' %}
10 | {% endcomment %}
11 |
12 |
13 |
57 |
58 |
--------------------------------------------------------------------------------
/assets/component-price.css:
--------------------------------------------------------------------------------
1 | .price {
2 | font-size: 1.6rem;
3 | letter-spacing: 0.1rem;
4 | line-height: calc(1 + 0.5 / var(--font-body-scale));
5 | color: rgb(var(--color-foreground));
6 | }
7 |
8 | .price > * {
9 | display: inline-block;
10 | vertical-align: top;
11 | }
12 |
13 | .price.price--unavailable {
14 | visibility: hidden;
15 | }
16 |
17 | .price--end {
18 | text-align: right;
19 | }
20 |
21 | .price .price-item {
22 | display: inline-block;
23 | margin: 0 1rem 0 0;
24 | }
25 |
26 | .price__regular .price-item--regular {
27 | margin-right: 0;
28 | }
29 |
30 | .price:not(.price--show-badge) .price-item--last:last-of-type {
31 | margin: 0;
32 | }
33 |
34 | @media screen and (min-width: 750px) {
35 | .price {
36 | margin-bottom: 0;
37 | }
38 | }
39 |
40 | .price--large {
41 | font-size: 1.6rem;
42 | line-height: calc(1 + 0.5 / var(--font-body-scale));
43 | letter-spacing: 0.13rem;
44 | }
45 |
46 | @media screen and (min-width: 750px) {
47 | .price--large {
48 | font-size: 1.8rem;
49 | }
50 | }
51 |
52 | .price--sold-out .price__availability,
53 | .price__regular {
54 | display: block;
55 | }
56 |
57 | .price__sale,
58 | .price__availability,
59 | .price .price__badge-sale,
60 | .price .price__badge-sold-out,
61 | .price--on-sale .price__regular,
62 | .price--on-sale .price__availability {
63 | display: none;
64 | }
65 |
66 | .price--sold-out .price__badge-sold-out,
67 | .price--on-sale .price__badge-sale {
68 | display: inline-block;
69 | }
70 |
71 | .price--on-sale .price__sale {
72 | display: initial;
73 | flex-direction: row;
74 | flex-wrap: wrap;
75 | }
76 |
77 | .price--center {
78 | display: initial;
79 | justify-content: center;
80 | }
81 |
82 | .price--on-sale .price-item--regular {
83 | text-decoration: line-through;
84 | color: rgba(var(--color-foreground), 0.75);
85 | font-size: 1.3rem;
86 | }
87 |
88 | .unit-price {
89 | display: block;
90 | font-size: 1.1rem;
91 | letter-spacing: 0.04rem;
92 | line-height: calc(1 + 0.2 / var(--font-body-scale));
93 | margin-top: 0.2rem;
94 | text-transform: uppercase;
95 | color: rgba(var(--color-foreground), 0.7);
96 | }
97 |
--------------------------------------------------------------------------------
/assets/component-mega-menu.css:
--------------------------------------------------------------------------------
1 | .mega-menu {
2 | position: static;
3 | }
4 |
5 | .mega-menu__content {
6 | background-color: rgb(var(--color-background));
7 | border-left: 0;
8 | border-radius: 0;
9 | border-right: 0;
10 | left: 0;
11 | overflow-y: auto;
12 | padding-bottom: 2.4rem;
13 | padding-top: 2.4rem;
14 | position: absolute;
15 | right: 0;
16 | top: 100%;
17 | }
18 |
19 | .shopify-section-header-sticky .mega-menu__content {
20 | max-height: calc(100vh - var(--header-bottom-position-desktop, 20rem) - 4rem);
21 | }
22 |
23 | .header-wrapper--border-bottom .mega-menu__content {
24 | border-top: 0;
25 | }
26 |
27 | .js .mega-menu__content {
28 | opacity: 0;
29 | transform: translateY(-1.5rem);
30 | }
31 |
32 | .mega-menu[open] .mega-menu__content {
33 | opacity: 1;
34 | transform: translateY(0);
35 | }
36 |
37 | .mega-menu__list {
38 | display: grid;
39 | gap: 2.4rem 4rem;
40 | grid-template-columns: repeat(6, minmax(0, 1fr));
41 | list-style: none;
42 | }
43 |
44 | .mega-menu__link {
45 | color: rgba(var(--color-foreground), 0.75);
46 | display: block;
47 | font-size: 1.3rem;
48 | line-height: calc(1 + 0.3 / var(--font-body-scale));
49 | padding-bottom: 0.6rem;
50 | padding-top: 0.6rem;
51 | text-decoration: none;
52 | transition: text-decoration var(--duration-short) ease;
53 | word-wrap: break-word;
54 | }
55 |
56 | .mega-menu__link--level-2 {
57 | font-size: 1.4rem;
58 | }
59 |
60 | .mega-menu__link--level-2:not(:only-child) {
61 | margin-bottom: 0.8rem;
62 | }
63 |
64 | .header--top-center .mega-menu__list {
65 | display: flex;
66 | justify-content: center;
67 | flex-wrap: wrap;
68 | column-gap: 0;
69 | }
70 |
71 | .header--top-center .mega-menu__list > li {
72 | width: 16%;
73 | padding-right: 2.4rem;
74 | }
75 |
76 | .mega-menu__link:hover,
77 | .mega-menu__link--active {
78 | color: rgb(var(--color-foreground));
79 | text-decoration: underline;
80 | }
81 |
82 | .mega-menu__link--active:hover {
83 | text-decoration-thickness: 0.2rem;
84 | }
85 |
86 | .mega-menu .mega-menu__list--condensed {
87 | display: block;
88 | }
89 |
90 | .mega-menu__list--condensed .mega-menu__link {
91 | font-weight: normal;
92 | }
93 |
--------------------------------------------------------------------------------
/assets/localization-form.js:
--------------------------------------------------------------------------------
1 | if (!customElements.get('localization-form')) {
2 | customElements.define(
3 | 'localization-form',
4 | class LocalizationForm extends HTMLElement {
5 | constructor() {
6 | super();
7 | this.elements = {
8 | input: this.querySelector('input[name="locale_code"], input[name="country_code"]'),
9 | button: this.querySelector('button'),
10 | panel: this.querySelector('.disclosure__list-wrapper'),
11 | };
12 | this.elements.button.addEventListener('click', this.openSelector.bind(this));
13 | this.elements.button.addEventListener('focusout', this.closeSelector.bind(this));
14 | this.addEventListener('keyup', this.onContainerKeyUp.bind(this));
15 |
16 | this.querySelectorAll('a').forEach((item) => item.addEventListener('click', this.onItemClick.bind(this)));
17 | }
18 |
19 | hidePanel() {
20 | this.elements.button.setAttribute('aria-expanded', 'false');
21 | this.elements.panel.setAttribute('hidden', true);
22 | }
23 |
24 | onContainerKeyUp(event) {
25 | if (event.code.toUpperCase() !== 'ESCAPE') return;
26 |
27 | if(this.elements.button.getAttribute('aria-expanded') == 'false') return;
28 | this.hidePanel();
29 | event.stopPropagation();
30 | this.elements.button.focus();
31 | }
32 |
33 | onItemClick(event) {
34 | event.preventDefault();
35 | const form = this.querySelector('form');
36 | this.elements.input.value = event.currentTarget.dataset.value;
37 | if (form) form.submit();
38 | }
39 |
40 | openSelector() {
41 | this.elements.button.focus();
42 | this.elements.panel.toggleAttribute('hidden');
43 | this.elements.button.setAttribute(
44 | 'aria-expanded',
45 | (this.elements.button.getAttribute('aria-expanded') === 'false').toString()
46 | );
47 | }
48 |
49 | closeSelector(event) {
50 | const isChild =
51 | this.elements.panel.contains(event.relatedTarget) || this.elements.button.contains(event.relatedTarget);
52 | if (!event.relatedTarget || !isChild) {
53 | this.hidePanel();
54 | }
55 | }
56 | }
57 | );
58 | }
59 |
--------------------------------------------------------------------------------
/assets/slick-theme.css:
--------------------------------------------------------------------------------
1 | @charset 'UTF-8';.slick-loading .slick-list{background:#fff url(ajax-loader.gif) center center no-repeat}@font-face{font-family:slick;font-weight:400;font-style:normal;src:url(fonts/slick.eot);src:url(fonts/slick.eot?#iefix) format('embedded-opentype'),url(fonts/slick.woff) format('woff'),url(fonts/slick.ttf) format('truetype'),url(fonts/slick.svg#slick) format('svg')}.slick-next,.slick-prev{font-size:0;line-height:0;position:absolute;top:50%;display:block;width:20px;height:20px;padding:0;-webkit-transform:translate(0,-50%);-ms-transform:translate(0,-50%);transform:translate(0,-50%);cursor:pointer;color:transparent;border:none;outline:0;background:0 0}.slick-next:focus,.slick-next:hover,.slick-prev:focus,.slick-prev:hover{color:transparent;outline:0;background:0 0}.slick-next:focus:before,.slick-next:hover:before,.slick-prev:focus:before,.slick-prev:hover:before{opacity:1}.slick-next.slick-disabled:before,.slick-prev.slick-disabled:before{opacity:.25}.slick-next:before,.slick-prev:before{font-family:slick;font-size:20px;line-height:1;opacity:.75;color:#fff;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.slick-prev{left:-25px}[dir=rtl] .slick-prev{right:-25px;left:auto}.slick-prev:before{content:'←'}[dir=rtl] .slick-prev:before{content:'→'}.slick-next{right:-25px}[dir=rtl] .slick-next{right:auto;left:-25px}.slick-next:before{content:'→'}[dir=rtl] .slick-next:before{content:'←'}.slick-dotted.slick-slider{margin-bottom:30px}.slick-dots{position:absolute;bottom:-25px;display:block;width:100%;padding:0;margin:0;list-style:none;text-align:center}.slick-dots li{position:relative;display:inline-block;width:20px;height:20px;margin:0 5px;padding:0;cursor:pointer}.slick-dots li button{font-size:0;line-height:0;display:block;width:20px;height:20px;padding:5px;cursor:pointer;color:transparent;border:0;outline:0;background:0 0}.slick-dots li button:focus,.slick-dots li button:hover{outline:0}.slick-dots li button:focus:before,.slick-dots li button:hover:before{opacity:1}.slick-dots li button:before{font-family:slick;font-size:6px;line-height:20px;position:absolute;top:0;left:0;width:20px;height:20px;content:'•';text-align:center;opacity:.25;color:#000;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.slick-dots li.slick-active button:before{opacity:.75;color:#000}
2 | /*# sourceMappingURL=slick-theme.min.css.map */
3 |
--------------------------------------------------------------------------------
/sections/cart-notification-product.liquid:
--------------------------------------------------------------------------------
1 | {%- if cart != empty -%}
2 | {%- for item in cart.items -%}
3 |
4 | {%- if item.image -%}
5 |
14 | {%- endif -%}
15 |
16 | {%- if settings.show_vendor -%}
17 |
{{ item.product.vendor }}
18 | {%- endif -%}
19 |
{{ item.product.title | escape }}
20 |
21 | {%- unless item.product.has_only_default_variant -%}
22 | {%- for option in item.options_with_values -%}
23 |
24 |
- {{ option.name }}:
25 | - {{ option.value }}
26 |
27 | {%- endfor -%}
28 | {%- endunless -%}
29 | {%- for property in item.properties -%}
30 | {%- assign property_first_char = property.first | slice: 0 -%}
31 | {%- if property.last != blank and property_first_char != '_' -%}
32 |
44 | {%- endif -%}
45 | {%- endfor -%}
46 |
47 | {%- if item.selling_plan_allocation != null -%}
48 |
{{ item.selling_plan_allocation.selling_plan.name }}
49 | {%- endif -%}
50 |
51 |
52 | {%- endfor -%}
53 | {%- endif -%}
54 |
--------------------------------------------------------------------------------
/snippets/cart-notification.liquid:
--------------------------------------------------------------------------------
1 | {% comment %}
2 | Renders cart notification
3 |
4 | Accepts:
5 | - color_scheme: {String} sets the color scheme of the notification (optional)
6 | - desktop_menu_type: {String} passes the desktop menu type which allows us to use the right css class (optional)
7 |
8 | Usage:
9 | {% render 'cart-notification' %}
10 | {% endcomment %}
11 |
12 |
13 |
53 |
54 | {% style %}
55 | .cart-notification {
56 | display: none;
57 | }
58 | {% endstyle %}
59 |
--------------------------------------------------------------------------------
/templates/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "image_banner": {
4 | "type": "image-banner",
5 | "blocks": {
6 | "heading": {
7 | "type": "heading",
8 | "settings": {
9 | "heading": "Browse our latest products",
10 | "heading_size": "h0"
11 | }
12 | },
13 | "button": {
14 | "type": "buttons",
15 | "settings": {
16 | "button_label_1": "Shop all",
17 | "button_link_1": "shopify:\/\/collections\/all",
18 | "button_style_secondary_1": true,
19 | "button_label_2": "",
20 | "button_link_2": "",
21 | "button_style_secondary_2": false
22 | }
23 | }
24 | },
25 | "block_order": [
26 | "heading",
27 | "button"
28 | ],
29 | "settings": {
30 | "image_overlay_opacity": 40,
31 | "image_height": "large",
32 | "desktop_content_position": "bottom-center",
33 | "show_text_box": false,
34 | "desktop_content_alignment": "center",
35 | "color_scheme": "inverse",
36 | "image_behavior": "none",
37 | "mobile_content_alignment": "center",
38 | "stack_images_on_mobile": false,
39 | "show_text_below": false
40 | }
41 | },
42 | "featured_collection": {
43 | "type": "featured-collection",
44 | "settings": {
45 | "title": "Featured products",
46 | "heading_size": "h2",
47 | "description": "",
48 | "show_description": false,
49 | "description_style": "body",
50 | "collection": "all",
51 | "products_to_show": 8,
52 | "columns_desktop": 4,
53 | "full_width": false,
54 | "show_view_all": true,
55 | "view_all_style": "solid",
56 | "enable_desktop_slider": false,
57 | "color_scheme": "background-1",
58 | "image_ratio": "adapt",
59 | "image_shape": "default",
60 | "show_secondary_image": true,
61 | "show_vendor": false,
62 | "show_rating": false,
63 | "enable_quick_add": false,
64 | "columns_mobile": "2",
65 | "swipe_on_mobile": false,
66 | "padding_top": 44,
67 | "padding_bottom": 36
68 | }
69 | }
70 | },
71 | "order": [
72 | "image_banner",
73 | "featured_collection"
74 | ]
75 | }
--------------------------------------------------------------------------------
/assets/component-modal-video.css:
--------------------------------------------------------------------------------
1 | .modal-video {
2 | background: rgba(var(--color-foreground), 0.2);
3 | box-sizing: border-box;
4 | height: 100%;
5 | left: 0;
6 | margin: 0 auto;
7 | opacity: 0;
8 | overflow: auto;
9 | position: fixed;
10 | top: 0;
11 | visibility: hidden;
12 | width: 100%;
13 | z-index: -1;
14 | }
15 |
16 | .modal-video[open] {
17 | opacity: 1;
18 | visibility: visible;
19 | z-index: 101;
20 | }
21 |
22 | .modal-video__content {
23 | background-color: rgb(var(--color-background));
24 | height: 100%;
25 | margin: 0;
26 | overflow: auto;
27 | padding: 0;
28 | position: absolute;
29 | width: 100%;
30 | }
31 |
32 | .modal-video__toggle {
33 | align-items: center;
34 | background-color: rgb(var(--color-background));
35 | border-radius: 50%;
36 | border: 0.1rem solid rgba(var(--color-foreground), 0.1);
37 | color: rgba(var(--color-foreground), 0.55);
38 | cursor: pointer;
39 | display: flex;
40 | justify-content: center;
41 | margin: 0 0 0 auto;
42 | padding: 1.2rem;
43 | position: fixed;
44 | right: 0.5rem;
45 | top: 2rem;
46 | width: 4rem;
47 | z-index: 2;
48 | }
49 |
50 | @media screen and (min-width: 750px) {
51 | .modal-video__toggle {
52 | right: 4.8rem;
53 | top: 3.5rem;
54 | }
55 | }
56 |
57 | @media screen and (min-width: 990px) {
58 | .modal-video__toggle {
59 | right: 4.3rem;
60 | top: 3rem;
61 | }
62 | }
63 |
64 | .modal-video__toggle .icon {
65 | height: auto;
66 | margin: 0;
67 | width: 2.2rem;
68 | }
69 |
70 | .modal-video__content-info {
71 | height: calc(100% - 6rem);
72 | margin: 0 auto;
73 | padding-top: 8rem;
74 | width: calc(100% - 1rem);
75 | }
76 |
77 | @media screen and (min-width: 750px) {
78 | .modal-video__content-info {
79 | height: calc(100% - 7.5rem);
80 | padding-top: 9.5rem;
81 | width: calc(100% - 9.6rem);
82 | }
83 | }
84 |
85 | @media screen and (min-width: 990px) {
86 | .modal-video__content-info {
87 | height: calc(100% - 7rem);
88 | padding-top: 9rem;
89 | width: calc(100% - 8.6rem);
90 | }
91 | }
92 |
93 | .modal-video__video,
94 | .modal-video__video iframe {
95 | height: 100%;
96 | width: 100%;
97 | }
98 |
99 | .modal-video__video iframe {
100 | position: static;
101 | border: 0;
102 | }
103 |
--------------------------------------------------------------------------------
/assets/share.js:
--------------------------------------------------------------------------------
1 | if (!customElements.get('share-button')) {
2 | customElements.define(
3 | 'share-button',
4 | class ShareButton extends DetailsDisclosure {
5 | constructor() {
6 | super();
7 |
8 | this.elements = {
9 | shareButton: this.querySelector('button'),
10 | shareSummary: this.querySelector('summary'),
11 | closeButton: this.querySelector('.share-button__close'),
12 | successMessage: this.querySelector('[id^="ShareMessage"]'),
13 | urlInput: this.querySelector('input'),
14 | };
15 | this.urlToShare = this.elements.urlInput ? this.elements.urlInput.value : document.location.href;
16 |
17 | if (navigator.share) {
18 | this.mainDetailsToggle.setAttribute('hidden', '');
19 | this.elements.shareButton.classList.remove('hidden');
20 | this.elements.shareButton.addEventListener('click', () => {
21 | navigator.share({ url: this.urlToShare, title: document.title });
22 | });
23 | } else {
24 | this.mainDetailsToggle.addEventListener('toggle', this.toggleDetails.bind(this));
25 | this.mainDetailsToggle
26 | .querySelector('.share-button__copy')
27 | .addEventListener('click', this.copyToClipboard.bind(this));
28 | this.mainDetailsToggle.querySelector('.share-button__close').addEventListener('click', this.close.bind(this));
29 | }
30 | }
31 |
32 | toggleDetails() {
33 | if (!this.mainDetailsToggle.open) {
34 | this.elements.successMessage.classList.add('hidden');
35 | this.elements.successMessage.textContent = '';
36 | this.elements.closeButton.classList.add('hidden');
37 | this.elements.shareSummary.focus();
38 | }
39 | }
40 |
41 | copyToClipboard() {
42 | navigator.clipboard.writeText(this.elements.urlInput.value).then(() => {
43 | this.elements.successMessage.classList.remove('hidden');
44 | this.elements.successMessage.textContent = window.accessibilityStrings.shareSuccess;
45 | this.elements.closeButton.classList.remove('hidden');
46 | this.elements.closeButton.focus();
47 | });
48 | }
49 |
50 | updateUrl(url) {
51 | this.urlToShare = url;
52 | this.elements.urlInput.value = url;
53 | }
54 | }
55 | );
56 | }
57 |
--------------------------------------------------------------------------------
/assets/magnify.js:
--------------------------------------------------------------------------------
1 | // create a container and set the full-size image as its background
2 | function createOverlay(image) {
3 | const overlayImage = document.createElement('img');
4 | overlayImage.setAttribute('src', `${image.src}`);
5 | overlay = document.createElement('div');
6 | prepareOverlay(overlay, overlayImage);
7 |
8 | image.style.opacity = '50%';
9 | toggleLoadingSpinner(image);
10 |
11 | overlayImage.onload = () => {
12 | toggleLoadingSpinner(image);
13 | image.parentElement.insertBefore(overlay, image);
14 | image.style.opacity = '100%';
15 | };
16 |
17 | return overlay;
18 | }
19 |
20 | function prepareOverlay(container, image) {
21 | container.setAttribute('class', 'image-magnify-full-size');
22 | container.setAttribute('aria-hidden', 'true');
23 | container.style.backgroundImage = `url('${image.src}')`;
24 | container.style.backgroundColor = 'var(--gradient-background)';
25 | }
26 |
27 | function toggleLoadingSpinner(image) {
28 | const loadingSpinner = image.parentElement.parentElement.querySelector(`.loading-overlay__spinner`);
29 | loadingSpinner.classList.toggle('hidden');
30 | }
31 |
32 | function moveWithHover(image, event, zoomRatio) {
33 | // calculate mouse position
34 | const ratio = image.height / image.width;
35 | const container = event.target.getBoundingClientRect();
36 | const xPosition = event.clientX - container.left;
37 | const yPosition = event.clientY - container.top;
38 | const xPercent = `${xPosition / (image.clientWidth / 100)}%`;
39 | const yPercent = `${yPosition / ((image.clientWidth * ratio) / 100)}%`;
40 |
41 | // determine what to show in the frame
42 | overlay.style.backgroundPosition = `${xPercent} ${yPercent}`;
43 | overlay.style.backgroundSize = `${image.width * zoomRatio}px`;
44 | }
45 |
46 | function magnify(image, zoomRatio) {
47 | const overlay = createOverlay(image);
48 | overlay.onclick = () => overlay.remove();
49 | overlay.onmousemove = (event) => moveWithHover(image, event, zoomRatio);
50 | overlay.onmouseleave = () => overlay.remove();
51 | }
52 |
53 | function enableZoomOnHover(zoomRatio) {
54 | const images = document.querySelectorAll('.image-magnify-hover');
55 | images.forEach((image) => {
56 | image.onclick = (event) => {
57 | magnify(image, zoomRatio);
58 | moveWithHover(image, event, zoomRatio);
59 | };
60 | });
61 | }
62 |
63 | enableZoomOnHover(2);
64 |
--------------------------------------------------------------------------------
/assets/section-main-blog.css:
--------------------------------------------------------------------------------
1 | .blog-articles {
2 | display: grid;
3 | grid-gap: 1rem;
4 | column-gap: var(--grid-mobile-horizontal-spacing);
5 | row-gap: var(--grid-mobile-vertical-spacing);
6 | }
7 |
8 | .blog-articles .card-wrapper {
9 | width: 100%;
10 | }
11 |
12 | @media screen and (min-width: 750px) {
13 | .blog-articles {
14 | grid-template-columns: 1fr 1fr;
15 | column-gap: var(--grid-desktop-horizontal-spacing);
16 | row-gap: var(--grid-desktop-vertical-spacing);
17 | }
18 |
19 | .blog-articles--collage > *:nth-child(3n + 1),
20 | .blog-articles--collage > *:nth-child(3n + 2):last-child {
21 | grid-column: span 2;
22 | text-align: center;
23 | }
24 |
25 | .blog-articles--collage > *:nth-child(3n + 1) .card,
26 | .blog-articles--collage > *:nth-child(3n + 2):last-child .card {
27 | text-align: center;
28 | }
29 |
30 | .blog-articles--collage > *:nth-child(3n + 1) .article-card__image--small .ratio::before,
31 | .blog-articles--collage > *:nth-child(3n + 2):last-child .article-card__image--small .ratio::before {
32 | padding-bottom: 22rem;
33 | }
34 |
35 | .blog-articles--collage > *:nth-child(3n + 1) .article-card__image--medium .ratio::before,
36 | .blog-articles--collage > *:nth-child(3n + 2):last-child .article-card__image--medium .ratio::before {
37 | padding-bottom: 44rem;
38 | }
39 |
40 | .blog-articles--collage > *:nth-child(3n + 1) .article-card__image--large .ratio::before,
41 | .blog-articles--collage > *:nth-child(3n + 2):last-child .article-card__image--large .ratio::before {
42 | padding-bottom: 66rem;
43 | }
44 | }
45 |
46 | @media screen and (min-width: 990px) {
47 | .blog-articles--collage > *:nth-child(3n + 1) .article-card__image--small .ratio .ratio::before,
48 | .blog-articles--collage > *:nth-child(3n + 2):last-child .article-card__image--small .ratio .ratio::before {
49 | padding-bottom: 27.5rem;
50 | }
51 |
52 | .blog-articles--collage > *:nth-child(3n + 1) .article-card__image--medium .ratio::before,
53 | .blog-articles--collage > *:nth-child(3n + 2):last-child .article-card__image--medium .ratio::before {
54 | padding-bottom: 55rem;
55 | }
56 |
57 | .blog-articles--collage > *:nth-child(3n + 1) .article-card__image--large .ratio::before,
58 | .blog-articles--collage > *:nth-child(3n + 2):last-child .article-card__image--large .ratio::before {
59 | padding-bottom: 82.5rem;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/assets/slick.css:
--------------------------------------------------------------------------------
1 | /* Slider */
2 | .slick-slider
3 | {
4 | position: relative;
5 |
6 | display: block;
7 | box-sizing: border-box;
8 |
9 | -webkit-user-select: none;
10 | -moz-user-select: none;
11 | -ms-user-select: none;
12 | user-select: none;
13 |
14 | -webkit-touch-callout: none;
15 | -khtml-user-select: none;
16 | -ms-touch-action: pan-y;
17 | touch-action: pan-y;
18 | -webkit-tap-highlight-color: transparent;
19 | }
20 |
21 | .slick-list
22 | {
23 | position: relative;
24 |
25 | display: block;
26 | overflow: hidden;
27 |
28 | margin: 0;
29 | padding: 0;
30 | }
31 | .slick-list:focus
32 | {
33 | outline: none;
34 | }
35 | .slick-list.dragging
36 | {
37 | cursor: pointer;
38 | cursor: hand;
39 | }
40 |
41 | .slick-slider .slick-track,
42 | .slick-slider .slick-list
43 | {
44 | -webkit-transform: translate3d(0, 0, 0);
45 | -moz-transform: translate3d(0, 0, 0);
46 | -ms-transform: translate3d(0, 0, 0);
47 | -o-transform: translate3d(0, 0, 0);
48 | transform: translate3d(0, 0, 0);
49 | }
50 |
51 | .slick-track
52 | {
53 | position: relative;
54 | top: 0;
55 | left: 0;
56 |
57 | display: block;
58 | margin-left: auto;
59 | margin-right: auto;
60 | }
61 | .slick-track:before,
62 | .slick-track:after
63 | {
64 | display: table;
65 |
66 | content: '';
67 | }
68 | .slick-track:after
69 | {
70 | clear: both;
71 | }
72 | .slick-loading .slick-track
73 | {
74 | visibility: hidden;
75 | }
76 |
77 | .slick-slide
78 | {
79 | display: none;
80 | float: left;
81 |
82 | height: 100%;
83 | min-height: 1px;
84 | }
85 | [dir='rtl'] .slick-slide
86 | {
87 | float: right;
88 | }
89 | .slick-slide img
90 | {
91 | display: block;
92 | }
93 | .slick-slide.slick-loading img
94 | {
95 | display: none;
96 | }
97 | .slick-slide.dragging img
98 | {
99 | pointer-events: none;
100 | }
101 | .slick-initialized .slick-slide
102 | {
103 | display: block;
104 | }
105 | .slick-loading .slick-slide
106 | {
107 | visibility: hidden;
108 | }
109 | .slick-vertical .slick-slide
110 | {
111 | display: block;
112 |
113 | height: auto;
114 |
115 | border: 1px solid transparent;
116 | }
117 | .slick-arrow.slick-hidden {
118 | display: none;
119 | }
120 |
--------------------------------------------------------------------------------
/assets/component-collection-hero.css:
--------------------------------------------------------------------------------
1 | .collection-hero__inner {
2 | display: flex;
3 | flex-direction: column;
4 | }
5 |
6 | .collection-hero--with-image .collection-hero__inner {
7 | margin-bottom: 0;
8 | padding-bottom: 2rem;
9 | }
10 |
11 | @media screen and (min-width: 750px) {
12 | .collection-hero.collection-hero--with-image {
13 | padding: calc(4rem + var(--page-width-margin)) 0 calc(4rem + var(--page-width-margin));
14 | overflow: hidden;
15 | }
16 |
17 | .collection-hero--with-image .collection-hero__inner {
18 | padding-bottom: 0;
19 | }
20 | }
21 |
22 | .collection-hero__text-wrapper {
23 | flex-basis: 100%;
24 | }
25 |
26 | @media screen and (min-width: 750px) {
27 | .collection-hero {
28 | padding: 0;
29 | }
30 |
31 | .collection-hero__inner {
32 | align-items: center;
33 | flex-direction: row;
34 | padding-bottom: 0;
35 | }
36 | }
37 |
38 | .collection-hero__title {
39 | margin: 2.5rem 0;
40 | }
41 |
42 | .collection-hero__title + .collection-hero__description {
43 | margin-top: 1.5rem;
44 | margin-bottom: 1.5rem;
45 | font-size: 1.6rem;
46 | line-height: calc(1 + 0.5 / var(--font-body-scale));
47 | }
48 |
49 | @media screen and (min-width: 750px) {
50 | .collection-hero__title + .collection-hero__description {
51 | font-size: 1.8rem;
52 | margin-top: 2rem;
53 | margin-bottom: 2rem;
54 | }
55 |
56 | .collection-hero__description {
57 | max-width: 66.67%;
58 | }
59 |
60 | .collection-hero--with-image .collection-hero__description {
61 | max-width: 100%;
62 | }
63 | }
64 |
65 | .collection-hero--with-image .collection-hero__title {
66 | margin: 0;
67 | }
68 |
69 | .collection-hero--with-image .collection-hero__text-wrapper {
70 | padding: 5rem 0 4rem;
71 | }
72 |
73 | .collection-hero__image-container {
74 | border: var(--media-border-width) solid rgba(var(--color-foreground), var(--media-border-opacity));
75 | border-radius: var(--media-radius);
76 | box-shadow: var(--media-shadow-horizontal-offset) var(--media-shadow-vertical-offset) var(--media-shadow-blur-radius)
77 | rgba(var(--color-shadow), var(--media-shadow-opacity));
78 | }
79 |
80 | @media screen and (max-width: 749px) {
81 | .collection-hero__image-container {
82 | height: 20rem;
83 | }
84 | }
85 |
86 | @media screen and (min-width: 750px) {
87 | .collection-hero--with-image .collection-hero__text-wrapper {
88 | padding: 4rem 2rem 4rem 0;
89 | flex-basis: 50%;
90 | }
91 |
92 | .collection-hero__image-container {
93 | align-self: stretch;
94 | flex: 1 0 50%;
95 | margin-left: 3rem;
96 | min-height: 20rem;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/assets/cart-notification.js:
--------------------------------------------------------------------------------
1 | class CartNotification extends HTMLElement {
2 | constructor() {
3 | super();
4 |
5 | this.notification = document.getElementById('cart-notification');
6 | this.header = document.querySelector('sticky-header');
7 | this.onBodyClick = this.handleBodyClick.bind(this);
8 |
9 | this.notification.addEventListener('keyup', (evt) => evt.code === 'Escape' && this.close());
10 | this.querySelectorAll('button[type="button"]').forEach((closeButton) =>
11 | closeButton.addEventListener('click', this.close.bind(this))
12 | );
13 | }
14 |
15 | open() {
16 | this.notification.classList.add('animate', 'active');
17 |
18 | this.notification.addEventListener(
19 | 'transitionend',
20 | () => {
21 | this.notification.focus();
22 | trapFocus(this.notification);
23 | },
24 | { once: true }
25 | );
26 |
27 | document.body.addEventListener('click', this.onBodyClick);
28 | }
29 |
30 | close() {
31 | this.notification.classList.remove('active');
32 | document.body.removeEventListener('click', this.onBodyClick);
33 |
34 | removeTrapFocus(this.activeElement);
35 | }
36 |
37 | renderContents(parsedState) {
38 | this.cartItemKey = parsedState.key;
39 | this.getSectionsToRender().forEach((section) => {
40 | document.getElementById(section.id).innerHTML = this.getSectionInnerHTML(
41 | parsedState.sections[section.id],
42 | section.selector
43 | );
44 | });
45 |
46 | if (this.header) this.header.reveal();
47 | this.open();
48 | }
49 |
50 | getSectionsToRender() {
51 | return [
52 | {
53 | id: 'cart-notification-product',
54 | selector: `[id="cart-notification-product-${this.cartItemKey}"]`,
55 | },
56 | {
57 | id: 'cart-notification-button',
58 | },
59 | {
60 | id: 'cart-icon-bubble',
61 | },
62 | ];
63 | }
64 |
65 | getSectionInnerHTML(html, selector = '.shopify-section') {
66 | return new DOMParser().parseFromString(html, 'text/html').querySelector(selector).innerHTML;
67 | }
68 |
69 | handleBodyClick(evt) {
70 | const target = evt.target;
71 | if (target !== this.notification && !target.closest('cart-notification')) {
72 | const disclosure = target.closest('details-disclosure, header-menu');
73 | this.activeElement = disclosure ? disclosure.querySelector('summary') : null;
74 | this.close();
75 | }
76 | }
77 |
78 | setActiveElement(element) {
79 | this.activeElement = element;
80 | }
81 | }
82 |
83 | customElements.define('cart-notification', CartNotification);
84 |
--------------------------------------------------------------------------------
/templates/product.json:
--------------------------------------------------------------------------------
1 | {
2 | "sections": {
3 | "main": {
4 | "type": "main-product",
5 | "blocks": {
6 | "vendor": {
7 | "type": "text",
8 | "settings": {
9 | "text": "{{ product.vendor }}",
10 | "text_style": "uppercase"
11 | }
12 | },
13 | "title": {
14 | "type": "title",
15 | "settings": {}
16 | },
17 | "price": {
18 | "type": "price",
19 | "settings": {}
20 | },
21 | "variant_picker": {
22 | "type": "variant_picker",
23 | "settings": {
24 | "picker_type": "button"
25 | }
26 | },
27 | "quantity_selector": {
28 | "type": "quantity_selector",
29 | "settings": {}
30 | },
31 | "buy_buttons": {
32 | "type": "buy_buttons",
33 | "settings": {
34 | "show_dynamic_checkout": true,
35 | "show_gift_card_recipient": false
36 | }
37 | },
38 | "description": {
39 | "type": "description",
40 | "settings": {}
41 | },
42 | "share": {
43 | "type": "share",
44 | "settings": {
45 | "share_label": "Share"
46 | }
47 | }
48 | },
49 | "block_order": [
50 | "vendor",
51 | "title",
52 | "price",
53 | "variant_picker",
54 | "quantity_selector",
55 | "buy_buttons",
56 | "description",
57 | "share"
58 | ],
59 | "settings": {
60 | "enable_sticky_info": true,
61 | "media_size": "large",
62 | "constrain_to_viewport": true,
63 | "media_fit": "contain",
64 | "gallery_layout": "stacked",
65 | "media_position": "left",
66 | "image_zoom": "lightbox",
67 | "mobile_thumbnails": "hide",
68 | "hide_variants": true,
69 | "enable_video_looping": false,
70 | "padding_top": 36,
71 | "padding_bottom": 12
72 | }
73 | },
74 | "related-products": {
75 | "type": "related-products",
76 | "settings": {
77 | "heading": "You may also like",
78 | "heading_size": "h2",
79 | "products_to_show": 4,
80 | "columns_desktop": 4,
81 | "color_scheme": "background-1",
82 | "image_ratio": "square",
83 | "image_shape": "default",
84 | "show_secondary_image": true,
85 | "show_vendor": false,
86 | "show_rating": false,
87 | "columns_mobile": "2",
88 | "padding_top": 36,
89 | "padding_bottom": 28
90 | }
91 | }
92 | },
93 | "order": [
94 | "main",
95 | "related-products"
96 | ]
97 | }
--------------------------------------------------------------------------------
/snippets/pagination.liquid:
--------------------------------------------------------------------------------
1 | {% comment %}
2 | Renders a set of links for paginated results. Must be used within paginate tags.
3 |
4 | Usage:
5 | {% paginate results by 2 %}
6 | {% render 'pagination', paginate: paginate, anchor: '#yourID' %}
7 | {% endpaginate %}
8 |
9 | Accepts:
10 | - paginate: {Object}
11 | - anchor: {String} (optional) This can be added so that on page reload it takes you to wherever you've placed your anchor tag.
12 | {% endcomment %}
13 |
14 | {{ 'component-pagination.css' | asset_url | stylesheet_tag }}
15 |
16 | {%- if paginate.parts.size > 0 -%}
17 |
74 | {%- endif -%}
75 |
--------------------------------------------------------------------------------
/assets/component-deferred-media.css:
--------------------------------------------------------------------------------
1 | .deferred-media__poster {
2 | background-color: transparent;
3 | border: none;
4 | cursor: pointer;
5 | margin: 0;
6 | padding: 0;
7 | height: 100%;
8 | width: 100%;
9 | overflow: hidden;
10 | border-radius: calc(var(--border-radius) - var(--border-width));
11 | }
12 |
13 | .media > .deferred-media__poster {
14 | display: flex;
15 | align-items: center;
16 | justify-content: center;
17 | }
18 |
19 | .deferred-media__poster img {
20 | width: auto;
21 | max-width: 100%;
22 | height: 100%;
23 | }
24 |
25 | .deferred-media {
26 | overflow: hidden;
27 | }
28 |
29 | .deferred-media:not([loaded]) template {
30 | z-index: -1;
31 | }
32 |
33 | .deferred-media[loaded] > .deferred-media__poster {
34 | display: none;
35 | }
36 |
37 | .deferred-media__poster:focus-visible {
38 | outline: none;
39 | box-shadow: 0 0 0 var(--media-border-width) rgba(var(--color-foreground), var(--media-border-opacity)),
40 | 0 0 0 calc(var(--media-border-width) + 0.3rem) rgb(var(--color-background)),
41 | 0 0 0 calc(var(--media-border-width) + 0.5rem) rgba(var(--color-foreground), 0.5);
42 | border-radius: calc(var(--media-radius) - var(--media-border-width));
43 | }
44 |
45 | .deferred-media__poster:focus {
46 | outline: none;
47 | box-shadow: 0 0 0 var(--media-border-width) rgba(var(--color-foreground), var(--media-border-opacity)),
48 | 0 0 0 calc(var(--media-border-width) + 0.3rem) rgb(var(--color-background)),
49 | 0 0 0 calc(var(--media-border-width) + 0.5rem) rgba(var(--color-foreground), 0.5);
50 | border-radius: calc(var(--media-radius) - var(--media-border-width));
51 | }
52 |
53 | .global-media-settings--full-width .deferred-media__poster,
54 | .global-media-settings--full-width .deferred-media__poster:is(:focus, :focus-visible) {
55 | border-radius: 0;
56 | }
57 |
58 | /* outline styling for Windows High Contrast Mode */
59 | @media (forced-colors: active) {
60 | .deferred-media__poster:focus {
61 | outline: transparent solid 1px;
62 | }
63 | }
64 | .deferred-media__poster:focus:not(:focus-visible) {
65 | outline: 0;
66 | box-shadow: none;
67 | }
68 |
69 | .deferred-media__poster-button {
70 | background-color: rgb(var(--color-background));
71 | border: 0.1rem solid rgba(var(--color-foreground), 0.1);
72 | border-radius: 50%;
73 | color: rgb(var(--color-foreground));
74 | display: flex;
75 | align-items: center;
76 | justify-content: center;
77 | height: 6.2rem;
78 | width: 6.2rem;
79 | position: absolute;
80 | left: 50%;
81 | top: 50%;
82 | transform: translate(-50%, -50%) scale(1);
83 | transition: transform var(--duration-short) ease, color var(--duration-short) ease;
84 | z-index: 1;
85 | }
86 |
87 | .deferred-media__poster-button:hover {
88 | transform: translate(-50%, -50%) scale(1.1);
89 | }
90 |
91 | .deferred-media__poster-button .icon {
92 | width: 2rem;
93 | height: 2rem;
94 | }
95 |
96 | .deferred-media__poster-button .icon-play {
97 | margin-left: 0.2rem;
98 | }
99 |
--------------------------------------------------------------------------------
/snippets/product-variant-options.liquid:
--------------------------------------------------------------------------------
1 | {% comment %}
2 | Renders product variant options
3 |
4 | Accepts:
5 | - product: {Object} product object.
6 | - option: {Object} current product_option object.
7 | - block: {Object} block object.
8 |
9 |
10 | Usage:
11 | {% render 'product-variant-options',
12 | product: product,
13 | option: option,
14 | block: block
15 | %}
16 | {% endcomment %}
17 | {%- liquid
18 | assign variants_available_arr = product.variants | map: 'available'
19 | assign variants_option1_arr = product.variants | map: 'option1'
20 | assign variants_option2_arr = product.variants | map: 'option2'
21 | assign variants_option3_arr = product.variants | map: 'option3'
22 |
23 | assign product_form_id = 'product-form-' | append: section.id
24 | -%}
25 |
26 | {%- for value in option.values -%}
27 | {%- liquid
28 | assign option_disabled = true
29 |
30 | for option1_name in variants_option1_arr
31 | case option.position
32 | when 1
33 | if variants_option1_arr[forloop.index0] == value and variants_available_arr[forloop.index0]
34 | assign option_disabled = false
35 | endif
36 | when 2
37 | if option1_name == product.selected_or_first_available_variant.option1 and variants_option2_arr[forloop.index0] == value and variants_available_arr[forloop.index0]
38 | assign option_disabled = false
39 | endif
40 | when 3
41 | if option1_name == product.selected_or_first_available_variant.option1 and variants_option2_arr[forloop.index0] == product.selected_or_first_available_variant.option2 and variants_option3_arr[forloop.index0] == value and variants_available_arr[forloop.index0]
42 | assign option_disabled = false
43 | endif
44 | endcase
45 | endfor
46 | -%}
47 |
48 | {%- if block.settings.picker_type == 'button' -%}
49 |
62 |
66 | {%- elsif block.settings.picker_type == 'dropdown' -%}
67 |
79 | {%- endif -%}
80 | {%- endfor -%}
81 |
--------------------------------------------------------------------------------
/assets/section-email-signup-banner.css:
--------------------------------------------------------------------------------
1 | .email-signup-banner .newsletter-form,
2 | .email-signup-banner .newsletter-form__field-wrapper {
3 | display: inline-block;
4 | }
5 |
6 | @media only screen and (min-width: 750px) {
7 | .email-signup-banner:not(.banner--desktop-transparent) .email-signup-banner__box {
8 | width: 100%;
9 | }
10 | }
11 |
12 | .email-signup-banner__box .email-signup-banner__heading {
13 | margin-bottom: 0;
14 | }
15 |
16 | .email-signup-banner__box > * + .newsletter__subheading {
17 | margin-top: 2rem;
18 | }
19 |
20 | .email-signup-banner__box .newsletter__subheading p {
21 | margin: 0;
22 | }
23 |
24 | .email-signup-banner-background {
25 | width: 100%;
26 | height: 100%;
27 | position: relative;
28 | left: 50%;
29 | transform: translateX(-50%);
30 | }
31 |
32 | @media screen and (max-width: 749px) {
33 | .email-signup-banner:not(.banner--mobile-bottom) .banner__box:not(.email-signup-banner__box--no-image) {
34 | background-color: transparent;
35 | --color-foreground: 255, 255, 255;
36 | --color-button: 255, 255, 255;
37 | --color-button-text: 0, 0, 0;
38 | }
39 | }
40 |
41 | @media only screen and (min-width: 750px) {
42 | .banner--desktop-transparent .email-signup-banner__box--no-image * {
43 | color: rgb(var(--color-foreground));
44 | }
45 |
46 | .banner--desktop-transparent .email-signup-banner__box .field__input {
47 | background-color: transparent;
48 | }
49 |
50 | .banner--desktop-transparent .email-signup-banner__box--no-image .field__input {
51 | box-shadow: 0 0 0 0.1rem rgba(var(--color-foreground), 0.55);
52 | }
53 |
54 | .banner--desktop-transparent .email-signup-banner__box--no-image .field__input:focus {
55 | box-shadow: 0 0 0 0.2rem rgba(var(--color-foreground), 0.75);
56 | }
57 |
58 | .banner--desktop-transparent .email-signup-banner__box--no-image .field__button:focus-visible {
59 | outline: 0.2rem solid rgba(var(--color-foreground), 0.5);
60 | box-shadow: 0 0 0 0.3rem rgb(var(--color-background)), 0 0 0.5rem 0.4rem rgba(var(--color-foreground), 0.3);
61 | }
62 | }
63 |
64 | @media only screen and (min-width: 750px) {
65 | .email-signup-banner-background-mobile {
66 | display: none;
67 | }
68 | }
69 |
70 | @media only screen and (max-width: 749px) {
71 | .email-signup-banner-background:not(.email-signup-banner-background-mobile) {
72 | display: none;
73 | }
74 | }
75 |
76 | .email-signup-banner .banner__media {
77 | overflow: hidden;
78 | }
79 |
80 | @media screen and (max-width: 749px) {
81 | .banner--mobile-content-align-left .newsletter-form__message {
82 | justify-content: flex-start;
83 | }
84 |
85 | .banner--mobile-content-align-right .newsletter-form__message {
86 | justify-content: right;
87 | }
88 | }
89 |
90 | @media screen and (min-width: 750px) {
91 | .banner--content-align-center .newsletter-form__message {
92 | justify-content: center;
93 | }
94 |
95 | .banner--content-align-right .newsletter-form__message {
96 | justify-content: right;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/assets/component-article-card.css:
--------------------------------------------------------------------------------
1 | @media screen and (max-width: 749px) {
2 | .articles-wrapper .article {
3 | width: 100%;
4 | }
5 | }
6 |
7 | .article {
8 | display: flex;
9 | align-items: center;
10 | }
11 |
12 | .article.grid__item {
13 | padding: 0;
14 | }
15 |
16 | .grid--peek .article-card {
17 | box-sizing: border-box;
18 | }
19 |
20 | .article-card__image-wrapper > a {
21 | display: block;
22 | }
23 |
24 | .article-card__title {
25 | text-decoration: none;
26 | word-break: break-word;
27 | }
28 |
29 | .article-card__title a:after {
30 | bottom: 0;
31 | content: '';
32 | height: 100%;
33 | left: 0;
34 | position: absolute;
35 | right: 0;
36 | top: 0;
37 | width: 100%;
38 | z-index: 1;
39 | }
40 |
41 | .article-card__link.link {
42 | padding: 0;
43 | }
44 |
45 | .article-card__link {
46 | text-underline-offset: 0.3rem;
47 | }
48 |
49 | .article-card .card__heading {
50 | margin-bottom: 0.6rem;
51 | }
52 |
53 | .blog-articles .article-card .card__information,
54 | .blog__posts .article-card .card__information {
55 | padding-left: 2rem;
56 | padding-right: 2rem;
57 | }
58 |
59 | .article-card__info {
60 | padding-top: 0.4rem;
61 | }
62 |
63 | .article-card__footer {
64 | letter-spacing: 0.1rem;
65 | font-size: 1.4rem;
66 | }
67 |
68 | .article-card__footer:not(:last-child) {
69 | margin-bottom: 1rem;
70 | }
71 |
72 | .article-card__footer:last-child {
73 | margin-top: auto;
74 | }
75 |
76 | .article-card__excerpt {
77 | width: 100%;
78 | margin-top: 1.2rem;
79 | }
80 |
81 | .article-card__link:not(:only-child) {
82 | margin-right: 3rem;
83 | }
84 |
85 | @media screen and (min-width: 990px) {
86 | .article-card__link:not(:only-child) {
87 | margin-right: 4rem;
88 | }
89 | }
90 |
91 | .article-card__image--small .ratio::before {
92 | padding-bottom: 11rem;
93 | }
94 |
95 | .article-card__image--medium .ratio::before {
96 | padding-bottom: 22rem;
97 | }
98 |
99 | .article-card__image--large .ratio::before {
100 | padding-bottom: 33rem;
101 | }
102 |
103 | @media screen and (min-width: 750px) {
104 | .article-card__image--small .ratio::before {
105 | padding-bottom: 14.3rem;
106 | }
107 |
108 | .article-card__image--medium .ratio::before {
109 | padding-bottom: 21.9rem;
110 | }
111 |
112 | .article-card__image--large .ratio::before {
113 | padding-bottom: 27.5rem;
114 | }
115 | }
116 |
117 | @media screen and (min-width: 990px) {
118 | .article-card__image--small .ratio::before {
119 | padding-bottom: 17.7rem;
120 | }
121 |
122 | .article-card__image--medium .ratio::before {
123 | padding-bottom: 30.7rem;
124 | }
125 |
126 | .article-card__image--large .ratio::before {
127 | padding-bottom: 40.7rem;
128 | }
129 | }
130 |
131 | /* check for flexbox gap in older Safari versions */
132 | @supports not (inset: 10px) {
133 | .articles-wrapper.grid {
134 | margin: 0 0 5rem 0;
135 | }
136 |
137 | @media screen and (min-width: 750px) {
138 | .articles-wrapper.grid {
139 | margin-bottom: 7rem;
140 | }
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/assets/customer.js:
--------------------------------------------------------------------------------
1 | const selectors = {
2 | customerAddresses: '[data-customer-addresses]',
3 | addressCountrySelect: '[data-address-country-select]',
4 | addressContainer: '[data-address]',
5 | toggleAddressButton: 'button[aria-expanded]',
6 | cancelAddressButton: 'button[type="reset"]',
7 | deleteAddressButton: 'button[data-confirm-message]',
8 | };
9 |
10 | const attributes = {
11 | expanded: 'aria-expanded',
12 | confirmMessage: 'data-confirm-message',
13 | };
14 |
15 | class CustomerAddresses {
16 | constructor() {
17 | this.elements = this._getElements();
18 | if (Object.keys(this.elements).length === 0) return;
19 | this._setupCountries();
20 | this._setupEventListeners();
21 | }
22 |
23 | _getElements() {
24 | const container = document.querySelector(selectors.customerAddresses);
25 | return container
26 | ? {
27 | container,
28 | addressContainer: container.querySelector(selectors.addressContainer),
29 | toggleButtons: document.querySelectorAll(selectors.toggleAddressButton),
30 | cancelButtons: container.querySelectorAll(selectors.cancelAddressButton),
31 | deleteButtons: container.querySelectorAll(selectors.deleteAddressButton),
32 | countrySelects: container.querySelectorAll(selectors.addressCountrySelect),
33 | }
34 | : {};
35 | }
36 |
37 | _setupCountries() {
38 | if (Shopify && Shopify.CountryProvinceSelector) {
39 | // eslint-disable-next-line no-new
40 | new Shopify.CountryProvinceSelector('AddressCountryNew', 'AddressProvinceNew', {
41 | hideElement: 'AddressProvinceContainerNew',
42 | });
43 | this.elements.countrySelects.forEach((select) => {
44 | const formId = select.dataset.formId;
45 | // eslint-disable-next-line no-new
46 | new Shopify.CountryProvinceSelector(`AddressCountry_${formId}`, `AddressProvince_${formId}`, {
47 | hideElement: `AddressProvinceContainer_${formId}`,
48 | });
49 | });
50 | }
51 | }
52 |
53 | _setupEventListeners() {
54 | this.elements.toggleButtons.forEach((element) => {
55 | element.addEventListener('click', this._handleAddEditButtonClick);
56 | });
57 | this.elements.cancelButtons.forEach((element) => {
58 | element.addEventListener('click', this._handleCancelButtonClick);
59 | });
60 | this.elements.deleteButtons.forEach((element) => {
61 | element.addEventListener('click', this._handleDeleteButtonClick);
62 | });
63 | }
64 |
65 | _toggleExpanded(target) {
66 | target.setAttribute(attributes.expanded, (target.getAttribute(attributes.expanded) === 'false').toString());
67 | }
68 |
69 | _handleAddEditButtonClick = ({ currentTarget }) => {
70 | this._toggleExpanded(currentTarget);
71 | };
72 |
73 | _handleCancelButtonClick = ({ currentTarget }) => {
74 | this._toggleExpanded(currentTarget.closest(selectors.addressContainer).querySelector(`[${attributes.expanded}]`));
75 | };
76 |
77 | _handleDeleteButtonClick = ({ currentTarget }) => {
78 | // eslint-disable-next-line no-alert
79 | if (confirm(currentTarget.getAttribute(attributes.confirmMessage))) {
80 | Shopify.postLink(currentTarget.dataset.target, {
81 | parameters: { _method: 'delete' },
82 | });
83 | }
84 | };
85 | }
86 |
--------------------------------------------------------------------------------
/snippets/email-signup-banner-background-mobile.liquid:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/snippets/social-icons.liquid:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sections/page.liquid:
--------------------------------------------------------------------------------
1 | {{ 'section-main-page.css' | asset_url | stylesheet_tag }}
2 |
3 | {%- style -%}
4 | .section-{{ section.id }}-padding {
5 | padding-top: {{ section.settings.padding_top | times: 0.75 | round: 0 }}px;
6 | padding-bottom: {{ section.settings.padding_bottom | times: 0.75 | round: 0 }}px;
7 | }
8 |
9 | @media screen and (min-width: 750px) {
10 | .section-{{ section.id }}-padding {
11 | padding-top: {{ section.settings.padding_top }}px;
12 | padding-bottom: {{ section.settings.padding_bottom }}px;
13 | }
14 | }
15 | {%- endstyle -%}
16 |
17 |
18 |
19 |
20 | {%- if section.settings.page.title != blank -%}
21 | {{ section.settings.page.title | escape }}
22 | {%- else -%}
23 | {{ 'sections.page.title' | t }}
24 | {%- endif -%}
25 |
26 |
35 |
36 |
37 |
38 | {% schema %}
39 | {
40 | "name": "t:sections.page.name",
41 | "tag": "section",
42 | "class": "section",
43 | "disabled_on": {
44 | "groups": ["header", "footer"]
45 | },
46 | "settings": [
47 | {
48 | "type": "page",
49 | "id": "page",
50 | "label": "t:sections.page.settings.page.label"
51 | },
52 | {
53 | "type": "select",
54 | "id": "heading_size",
55 | "options": [
56 | {
57 | "value": "h2",
58 | "label": "t:sections.all.heading_size.options__1.label"
59 | },
60 | {
61 | "value": "h1",
62 | "label": "t:sections.all.heading_size.options__2.label"
63 | },
64 | {
65 | "value": "h0",
66 | "label": "t:sections.all.heading_size.options__3.label"
67 | }
68 | ],
69 | "default": "h1",
70 | "label": "t:sections.all.heading_size.label"
71 | },
72 | {
73 | "type": "color_scheme",
74 | "id": "color_scheme",
75 | "label": "t:sections.all.colors.label",
76 | "default": "background-1"
77 | },
78 | {
79 | "type": "header",
80 | "content": "t:sections.all.padding.section_padding_heading"
81 | },
82 | {
83 | "type": "range",
84 | "id": "padding_top",
85 | "min": 0,
86 | "max": 100,
87 | "step": 4,
88 | "unit": "px",
89 | "label": "t:sections.all.padding.padding_top",
90 | "default": 36
91 | },
92 | {
93 | "type": "range",
94 | "id": "padding_bottom",
95 | "min": 0,
96 | "max": 100,
97 | "step": 4,
98 | "unit": "px",
99 | "label": "t:sections.all.padding.padding_bottom",
100 | "default": 36
101 | }
102 | ],
103 | "presets": [
104 | {
105 | "name": "t:sections.page.presets.name"
106 | }
107 | ]
108 | }
109 | {% endschema %}
110 |
--------------------------------------------------------------------------------
/assets/component-cart-notification.css:
--------------------------------------------------------------------------------
1 | .cart-notification-wrapper {
2 | position: relative;
3 | }
4 |
5 | .cart-notification-wrapper .cart-notification {
6 | display: block;
7 | }
8 |
9 | .cart-notification {
10 | border-bottom-right-radius: var(--popup-corner-radius);
11 | border-bottom-left-radius: var(--popup-corner-radius);
12 | border-color: rgba(var(--color-foreground), var(--popup-border-opacity));
13 | border-style: solid;
14 | border-width: 0 0 var(--popup-border-width);
15 | padding: 2.5rem 3.5rem;
16 | position: absolute;
17 | right: 0;
18 | transform: translateY(-100%);
19 | visibility: hidden;
20 | width: 100%;
21 | box-shadow: var(--popup-shadow-horizontal-offset) var(--popup-shadow-vertical-offset) var(--popup-shadow-blur-radius)
22 | rgba(var(--color-shadow), var(--popup-shadow-opacity));
23 | z-index: -1;
24 | }
25 |
26 | .cart-notification.focused {
27 | box-shadow: 0 0 0.2rem 0 rgba(var(--color-foreground), 0.3),
28 | var(--popup-shadow-horizontal-offset) var(--popup-shadow-vertical-offset) var(--popup-shadow-blur-radius)
29 | rgba(var(--color-shadow), var(--popup-shadow-opacity));
30 | }
31 |
32 | .cart-notification:focus-visible {
33 | box-shadow: 0 0 0.2rem 0 rgba(var(--color-foreground), 0.3),
34 | var(--popup-shadow-horizontal-offset) var(--popup-shadow-vertical-offset) var(--popup-shadow-blur-radius)
35 | rgba(var(--color-shadow), var(--popup-shadow-opacity));
36 | }
37 |
38 | @media screen and (min-width: 750px) {
39 | .header-wrapper:not(.header-wrapper--border-bottom) + cart-notification .cart-notification {
40 | border-top-width: var(--popup-border-width);
41 | }
42 |
43 | .cart-notification {
44 | border-width: 0 var(--popup-border-width) var(--popup-border-width);
45 | max-width: 36.8rem;
46 | right: 2.2rem;
47 | }
48 | }
49 |
50 | @media screen and (min-width: 990px) {
51 | .cart-notification-wrapper:is(.page-width) > .cart-notification {
52 | right: 4rem;
53 | }
54 | }
55 |
56 | .cart-notification.animate {
57 | transition: transform var(--duration-short) ease, visibility 0s var(--duration-short) ease;
58 | }
59 |
60 | .cart-notification.active {
61 | transform: translateY(0);
62 | transition: transform var(--duration-default) ease, visibility 0s;
63 | visibility: visible;
64 | }
65 |
66 | .cart-notification__header {
67 | align-items: flex-start;
68 | display: flex;
69 | }
70 |
71 | .cart-notification__heading {
72 | align-items: center;
73 | display: flex;
74 | flex-grow: 1;
75 | margin-bottom: 0;
76 | margin-top: 0;
77 | }
78 |
79 | .cart-notification__heading .icon-checkmark {
80 | color: rgb(var(--color-foreground));
81 | margin-right: 1rem;
82 | width: 1.3rem;
83 | }
84 |
85 | .cart-notification__close {
86 | margin-top: -2rem;
87 | margin-right: -3rem;
88 | }
89 |
90 | .cart-notification__links {
91 | text-align: center;
92 | }
93 |
94 | .cart-notification__links > * {
95 | margin-top: 1rem;
96 | }
97 |
98 | .cart-notification-product {
99 | align-items: flex-start;
100 | display: flex;
101 | padding-bottom: 3rem;
102 | padding-top: 2rem;
103 | }
104 |
105 | .cart-notification-product dl {
106 | margin-bottom: 0;
107 | margin-top: 0;
108 | }
109 |
110 | .cart-notification-product__image {
111 | display: inline-flex;
112 | margin-right: 1.5rem;
113 | margin-top: 0.5rem;
114 | }
115 |
116 | .cart-notification-product__image:after {
117 | content: none;
118 | }
119 |
120 | .cart-notification-product__name {
121 | margin-bottom: 0.5rem;
122 | margin-top: 0;
123 | }
124 |
--------------------------------------------------------------------------------
/assets/collapsible-content.css:
--------------------------------------------------------------------------------
1 | .collapsible-content {
2 | position: relative;
3 | z-index: 0;
4 | }
5 |
6 | .collapsible-section-layout {
7 | padding-bottom: 5rem;
8 | padding-top: 5rem;
9 | }
10 |
11 | @media screen and (min-width: 750px) {
12 | .collapsible-section-layout {
13 | padding-bottom: 7rem;
14 | padding-top: 7rem;
15 | }
16 | }
17 |
18 | /* Needed for gradient continuity with or without animation so that transparent PNG images come up as we would expect */
19 | .collapsible-content__media {
20 | background: transparent;
21 | }
22 |
23 | .collapsible-content__media--small {
24 | height: 19.4rem;
25 | }
26 |
27 | .collapsible-content__media--large {
28 | height: 43.5rem;
29 | }
30 |
31 | @media screen and (min-width: 750px) {
32 | .collapsible-content__media--small {
33 | height: 31.4rem;
34 | }
35 |
36 | .collapsible-content__media--large {
37 | height: 69.5rem;
38 | }
39 | }
40 |
41 | @media screen and (min-width: 750px) {
42 | .collapsible-content__grid--reverse {
43 | flex-direction: row-reverse;
44 | }
45 | }
46 |
47 | .collapsible-content-wrapper-narrow {
48 | margin: 0 auto;
49 | padding-right: 1.5rem;
50 | padding-left: 1.5rem;
51 | max-width: 73.4rem;
52 | }
53 |
54 | .collapsible-content__header {
55 | word-break: break-word;
56 | }
57 |
58 | .collapsible-content__heading {
59 | margin-bottom: 2rem;
60 | margin-top: 0;
61 | }
62 |
63 | @media screen and (min-width: 750px) {
64 | .collapsible-content__heading {
65 | margin-bottom: 3rem;
66 | }
67 | }
68 |
69 | .collapsible-none-layout .accordion + .accordion {
70 | border-top: 0;
71 | }
72 |
73 | .collapsible-row-layout .accordion:not(:first-child):not(.color-background-1) {
74 | margin-top: 1rem;
75 | }
76 |
77 | .caption-with-letter-spacing + h2 {
78 | margin-top: 1rem;
79 | }
80 |
81 | @media screen and (min-width: 750px) {
82 | .collapsible-content .accordion {
83 | margin-top: 0;
84 | }
85 | }
86 |
87 | .collapsible-row-layout .accordion {
88 | border: var(--text-boxes-border-width) solid rgba(var(--color-foreground), var(--text-boxes-border-opacity));
89 | margin-bottom: 1.5rem;
90 | /* Needed for gradient continuity with or without animation, the transform scopes the gradient to its container which happens already when animation are turned on */
91 | transform: perspective(0);
92 | }
93 |
94 | .collapsible-row-layout .accordion summary,
95 | .collapsible-row-layout .accordion .accordion__content {
96 | padding: 1.5rem;
97 | }
98 |
99 | .collapsible-row-layout .accordion .accordion__content {
100 | padding-top: 0;
101 | }
102 |
103 | .collapsible-content summary:hover {
104 | background: rgba(var(--color-foreground), 0.04);
105 | }
106 |
107 | .collapsible-content summary:hover .accordion__title {
108 | text-decoration: underline;
109 | text-underline-offset: 0.3rem;
110 | }
111 |
112 | /* check for flexbox gap in older Safari versions */
113 | @supports not (inset: 10px) {
114 | @media screen and (min-width: 750px) {
115 | .collapsible-content__grid:not(.collapsible-content__grid--reverse) .grid__item:last-child,
116 | .collapsible-content__grid--reverse .collapsible-content__grid-item {
117 | padding-left: 5rem;
118 | padding-right: 0;
119 | }
120 | }
121 |
122 | @media screen and (min-width: 990px) {
123 | .collapsible-content__grid:not(.collapsible-content__grid--reverse) .grid__item:last-child,
124 | .collapsible-content__grid--reverse .collapsible-content__grid-item {
125 | padding-left: 7rem;
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/sections/main-collection-banner.liquid:
--------------------------------------------------------------------------------
1 | {% comment %}theme-check-disable ImgLazyLoading{% endcomment %}
2 | {{ 'component-collection-hero.css' | asset_url | stylesheet_tag }}
3 |
4 | {%- style -%}
5 | @media screen and (max-width: 749px) {
6 | .collection-hero--with-image .collection-hero__inner {
7 | padding-bottom: calc({{ settings.media_shadow_vertical_offset | at_least: 0 }}px + 2rem);
8 | }
9 | }
10 | {%- endstyle -%}
11 |
12 |
13 |
14 |
15 |
16 | {{ 'sections.collection_template.title' | t }}:
17 | {{- collection.title | escape -}}
18 |
19 |
20 | {%- if section.settings.show_collection_description -%}
21 |
{{ collection.description }}
22 | {%- endif -%}
23 |
24 |
25 | {%- if section.settings.show_collection_image and collection.image -%}
26 |
44 | {%- endif -%}
45 |
46 |
47 |
48 | {% schema %}
49 | {
50 | "name": "t:sections.main-collection-banner.name",
51 | "class": "section",
52 | "settings": [
53 | {
54 | "type": "paragraph",
55 | "content": "t:sections.main-collection-banner.settings.paragraph.content"
56 | },
57 | {
58 | "type": "checkbox",
59 | "id": "show_collection_description",
60 | "default": true,
61 | "label": "t:sections.main-collection-banner.settings.show_collection_description.label"
62 | },
63 | {
64 | "type": "checkbox",
65 | "id": "show_collection_image",
66 | "default": false,
67 | "label": "t:sections.main-collection-banner.settings.show_collection_image.label",
68 | "info": "t:sections.main-collection-banner.settings.show_collection_image.info"
69 | },
70 | {
71 | "type": "color_scheme",
72 | "id": "color_scheme",
73 | "label": "t:sections.all.colors.label",
74 | "default": "background-1"
75 | }
76 | ]
77 | }
78 | {% endschema %}
79 |
--------------------------------------------------------------------------------
/snippets/icon-with-text.liquid:
--------------------------------------------------------------------------------
1 | {% comment %}
2 | Renders icon with text block
3 |
4 | Accepts:
5 | - block: {Object} passes in the block information.
6 |
7 |
8 | Usage:
9 | {% render 'icon-with-text',
10 | block: block
11 | %}
12 | {% endcomment %}
13 | {%- liquid
14 | assign heading_1_empty = false
15 | assign heading_2_empty = false
16 | assign heading_3_empty = false
17 | assign text_only_all_items = true
18 |
19 | if block.settings.heading_1 == empty
20 | assign heading_1_empty = true
21 | endif
22 |
23 | if block.settings.heading_2 == empty
24 | assign heading_2_empty = true
25 | endif
26 |
27 | if block.settings.heading_3 == empty
28 | assign heading_3_empty = true
29 | endif
30 |
31 | if heading_1_empty == false and block.settings.icon_1 != 'none' or block.settings.image_1 != null
32 | assign text_only_all_items = false
33 | elsif heading_2_empty == false and block.settings.icon_2 != 'none' or block.settings.image_2 != null
34 | assign text_only_all_items = false
35 | elsif heading_3_empty == false and block.settings.icon_3 != 'none' or block.settings.image_3 != null
36 | assign text_only_all_items = false
37 | endif
38 | -%}
39 |
43 | {%- unless heading_1_empty -%}
44 | -
45 | {%- if block.settings.image_1 == null -%}
46 | {%- render 'icon-accordion', icon: block.settings.icon_1 -%}
47 | {%- else -%}
48 |
59 | {%- endif -%}
60 |
61 | {{- block.settings.heading_1 -}}
62 |
63 |
64 | {%- endunless -%}
65 | {%- unless heading_2_empty -%}
66 | -
67 | {%- if block.settings.image_2 == null -%}
68 | {% render 'icon-accordion', icon: block.settings.icon_2 -%}
69 | {%- else -%}
70 |
81 | {%- endif -%}
82 |
83 | {{- block.settings.heading_2 -}}
84 |
85 |
86 | {%- endunless -%}
87 | {%- unless heading_3_empty -%}
88 | -
89 | {%- if block.settings.image_3 == null -%}
90 | {% render 'icon-accordion', icon: block.settings.icon_3 -%}
91 | {%- else -%}
92 |
103 | {%- endif -%}
104 |
105 | {{- block.settings.heading_3 -}}
106 |
107 |
108 | {%- endunless -%}
109 |
110 |
--------------------------------------------------------------------------------
/snippets/header-mega-menu.liquid:
--------------------------------------------------------------------------------
1 | {% comment %}
2 | Renders a megamenu for the header.
3 |
4 | Usage:
5 | {% render 'header-mega-menu' %}
6 | {% endcomment %}
7 |
8 |
95 |
--------------------------------------------------------------------------------
/assets/section-blog-post.css:
--------------------------------------------------------------------------------
1 | .article-template > *:first-child:not(.article-template__hero-container) {
2 | margin-top: 5rem;
3 | }
4 |
5 | @media screen and (min-width: 750px) {
6 | .article-template > *:first-child:not(.article-template__hero-container) {
7 | margin-top: calc(5rem + var(--page-width-margin));
8 | }
9 | }
10 |
11 | .article-template__hero-container {
12 | max-width: 130rem;
13 | margin: 0 auto;
14 | }
15 |
16 | .article-template__hero-small {
17 | height: 11rem;
18 | }
19 |
20 | .article-template__hero-medium {
21 | height: 22rem;
22 | }
23 |
24 | .article-template__hero-large {
25 | height: 33rem;
26 | }
27 |
28 | @media screen and (min-width: 750px) and (max-width: 989px) {
29 | .article-template__hero-small {
30 | height: 22rem;
31 | }
32 |
33 | .article-template__hero-medium {
34 | height: 44rem;
35 | }
36 |
37 | .article-template__hero-large {
38 | height: 66rem;
39 | }
40 | }
41 |
42 | @media screen and (min-width: 990px) {
43 | .article-template__hero-small {
44 | height: 27.5rem;
45 | }
46 |
47 | .article-template__hero-medium {
48 | height: 55rem;
49 | }
50 |
51 | .article-template__hero-large {
52 | height: 82.5rem;
53 | }
54 | }
55 |
56 | .article-template header {
57 | margin-top: 4.4rem;
58 | margin-bottom: 2rem;
59 | line-height: calc(0.8 / var(--font-body-scale));
60 | }
61 |
62 | @media screen and (min-width: 750px) {
63 | .article-template header {
64 | margin-top: 5rem;
65 | }
66 | }
67 |
68 | .article-template__title {
69 | margin: 0;
70 | }
71 |
72 | .article-template__title:not(:only-child) {
73 | margin-bottom: 1rem;
74 | }
75 |
76 | .article-template__link {
77 | font-size: 1.8rem;
78 | display: flex;
79 | justify-content: center;
80 | align-items: center;
81 | text-decoration: none;
82 | }
83 |
84 | .article-template__link .icon-wrap {
85 | display: flex;
86 | margin-right: 1rem;
87 | transform: rotate(180deg);
88 | }
89 |
90 | .article-template__content {
91 | margin-top: 3rem;
92 | margin-bottom: 3rem;
93 | }
94 |
95 | .article-template__social-sharing {
96 | margin-top: 3rem;
97 | }
98 |
99 | .article-template__social-sharing + header,
100 | .article-template__social-sharing + .article-template__content {
101 | margin-top: 1.5rem;
102 | }
103 |
104 | .article-template__comment-wrapper {
105 | margin-top: 5rem;
106 | padding: 2.7rem 0;
107 | }
108 |
109 | @media screen and (min-width: 750px) {
110 | .article-template__comment-wrapper {
111 | margin-top: 6rem;
112 | padding: 3.6rem 0;
113 | }
114 | }
115 |
116 | .article-template__comment-wrapper h2 {
117 | margin-top: 0;
118 | }
119 |
120 | .article-template__comments {
121 | margin-bottom: 5rem;
122 | }
123 |
124 | @media screen and (min-width: 750px) {
125 | .article-template__comments {
126 | margin-bottom: 7rem;
127 | }
128 | }
129 |
130 | .article-template__comments-fields {
131 | margin-bottom: 4rem;
132 | }
133 |
134 | .article-template__comments-comment {
135 | color: rgba(var(--color-foreground), 0.75);
136 | background-color: rgb(var(--color-background));
137 | margin-bottom: 1.5rem;
138 | padding: 2rem 2rem 1.5rem;
139 | }
140 |
141 | @media screen and (min-width: 750px) {
142 | .article-template__comments-comment {
143 | padding: 2rem 2.5rem;
144 | }
145 | }
146 |
147 | .article-template__comments-comment p {
148 | margin: 0 0 1rem;
149 | }
150 |
151 | .article-template__comment-fields > * {
152 | margin-bottom: 3rem;
153 | }
154 |
155 | @media screen and (min-width: 750px) {
156 | .article-template__comment-fields {
157 | display: grid;
158 | grid-template-columns: repeat(2, 1fr);
159 | grid-column-gap: 4rem;
160 | }
161 | }
162 |
163 | .article-template__comment-warning {
164 | margin: 2rem 0 2.5rem;
165 | }
166 |
167 | @media screen and (min-width: 990px) {
168 | .article-template__comments .pagination-wrapper {
169 | margin: 5rem 0 8rem;
170 | }
171 | }
172 |
173 | .article-template__back:last-child {
174 | margin-bottom: 3.2rem;
175 | }
176 |
--------------------------------------------------------------------------------
/assets/pickup-availability.js:
--------------------------------------------------------------------------------
1 | if (!customElements.get('pickup-availability')) {
2 | customElements.define(
3 | 'pickup-availability',
4 | class PickupAvailability extends HTMLElement {
5 | constructor() {
6 | super();
7 |
8 | if (!this.hasAttribute('available')) return;
9 |
10 | this.errorHtml = this.querySelector('template').content.firstElementChild.cloneNode(true);
11 | this.onClickRefreshList = this.onClickRefreshList.bind(this);
12 | this.fetchAvailability(this.dataset.variantId);
13 | }
14 |
15 | fetchAvailability(variantId) {
16 | let rootUrl = this.dataset.rootUrl;
17 | if (!rootUrl.endsWith('/')) {
18 | rootUrl = rootUrl + '/';
19 | }
20 | const variantSectionUrl = `${rootUrl}variants/${variantId}/?section_id=pickup-availability`;
21 |
22 | fetch(variantSectionUrl)
23 | .then((response) => response.text())
24 | .then((text) => {
25 | const sectionInnerHTML = new DOMParser()
26 | .parseFromString(text, 'text/html')
27 | .querySelector('.shopify-section');
28 | this.renderPreview(sectionInnerHTML);
29 | })
30 | .catch((e) => {
31 | const button = this.querySelector('button');
32 | if (button) button.removeEventListener('click', this.onClickRefreshList);
33 | this.renderError();
34 | });
35 | }
36 |
37 | onClickRefreshList(evt) {
38 | this.fetchAvailability(this.dataset.variantId);
39 | }
40 |
41 | renderError() {
42 | this.innerHTML = '';
43 | this.appendChild(this.errorHtml);
44 |
45 | this.querySelector('button').addEventListener('click', this.onClickRefreshList);
46 | }
47 |
48 | renderPreview(sectionInnerHTML) {
49 | const drawer = document.querySelector('pickup-availability-drawer');
50 | if (drawer) drawer.remove();
51 | if (!sectionInnerHTML.querySelector('pickup-availability-preview')) {
52 | this.innerHTML = '';
53 | this.removeAttribute('available');
54 | return;
55 | }
56 |
57 | this.innerHTML = sectionInnerHTML.querySelector('pickup-availability-preview').outerHTML;
58 | this.setAttribute('available', '');
59 |
60 | document.body.appendChild(sectionInnerHTML.querySelector('pickup-availability-drawer'));
61 |
62 | const button = this.querySelector('button');
63 | if (button)
64 | button.addEventListener('click', (evt) => {
65 | document.querySelector('pickup-availability-drawer').show(evt.target);
66 | });
67 | }
68 | }
69 | );
70 | }
71 |
72 | if (!customElements.get('pickup-availability-drawer')) {
73 | customElements.define(
74 | 'pickup-availability-drawer',
75 | class PickupAvailabilityDrawer extends HTMLElement {
76 | constructor() {
77 | super();
78 |
79 | this.onBodyClick = this.handleBodyClick.bind(this);
80 |
81 | this.querySelector('button').addEventListener('click', () => {
82 | this.hide();
83 | });
84 |
85 | this.addEventListener('keyup', (event) => {
86 | if (event.code.toUpperCase() === 'ESCAPE') this.hide();
87 | });
88 | }
89 |
90 | handleBodyClick(evt) {
91 | const target = evt.target;
92 | if (
93 | target != this &&
94 | !target.closest('pickup-availability-drawer') &&
95 | target.id != 'ShowPickupAvailabilityDrawer'
96 | ) {
97 | this.hide();
98 | }
99 | }
100 |
101 | hide() {
102 | this.removeAttribute('open');
103 | document.body.removeEventListener('click', this.onBodyClick);
104 | document.body.classList.remove('overflow-hidden');
105 | removeTrapFocus(this.focusElement);
106 | }
107 |
108 | show(focusElement) {
109 | this.focusElement = focusElement;
110 | this.setAttribute('open', '');
111 | document.body.addEventListener('click', this.onBodyClick);
112 | document.body.classList.add('overflow-hidden');
113 | trapFocus(this);
114 | }
115 | }
116 | );
117 | }
118 |
--------------------------------------------------------------------------------
/assets/component-pickup-availability.css:
--------------------------------------------------------------------------------
1 | pickup-availability {
2 | display: block;
3 | }
4 |
5 | pickup-availability[available] {
6 | min-height: 8rem;
7 | }
8 |
9 | .pickup-availability-preview {
10 | align-items: flex-start;
11 | display: flex;
12 | gap: 0.2rem;
13 | padding: 1rem 2rem 0 0;
14 | }
15 |
16 | .pickup-availability-preview .icon {
17 | flex-shrink: 0;
18 | height: 1.8rem;
19 | }
20 |
21 | .pickup-availability-preview .icon-unavailable {
22 | height: 1.6rem;
23 | margin-top: 0.1rem;
24 | }
25 |
26 | .pickup-availability-button {
27 | background-color: transparent;
28 | color: rgba(var(--color-foreground), 0.75);
29 | letter-spacing: 0.06rem;
30 | padding: 0 0 0.2rem;
31 | text-align: left;
32 | text-decoration: underline;
33 | }
34 |
35 | .pickup-availability-button:hover {
36 | color: rgb(var(--color-foreground));
37 | }
38 |
39 | .pickup-availability-info * {
40 | margin: 0 0 0.6rem;
41 | }
42 |
43 | pickup-availability-drawer {
44 | background-color: rgb(var(--color-background));
45 | height: 100%;
46 | opacity: 0;
47 | overflow-y: auto;
48 | padding: 2rem;
49 | position: fixed;
50 | top: 0;
51 | right: 0;
52 | z-index: 4;
53 | transition: opacity var(--duration-default) ease, transform var(--duration-default) ease;
54 | transform: translateX(100%);
55 | width: 100%;
56 | border-width: 0 0 0 var(--drawer-border-width);
57 | border-color: rgba(var(--color-foreground), var(--drawer-border-opacity));
58 | border-style: solid;
59 | filter: drop-shadow(
60 | var(--drawer-shadow-horizontal-offset) var(--drawer-shadow-vertical-offset) var(--drawer-shadow-blur-radius)
61 | rgba(var(--color-shadow), var(--drawer-shadow-opacity))
62 | );
63 | }
64 |
65 | pickup-availability-drawer[open] {
66 | transform: translateX(0);
67 | opacity: 1;
68 | }
69 |
70 | @media screen and (min-width: 750px) {
71 | pickup-availability-drawer {
72 | transform: translateX(100%);
73 | width: 37.5rem;
74 | }
75 |
76 | pickup-availability-drawer[open] {
77 | opacity: 1;
78 | transform: translateX(0);
79 | animation: animateDrawerOpen var(--duration-default) ease;
80 | }
81 | }
82 |
83 | .pickup-availability-header {
84 | align-items: flex-start;
85 | display: flex;
86 | justify-content: space-between;
87 | margin-bottom: 1.2rem;
88 | }
89 |
90 | .pickup-availability-drawer-title {
91 | margin: 0.5rem 0 0;
92 | }
93 |
94 | .pickup-availability-header .icon {
95 | width: 2rem;
96 | }
97 |
98 | .pickup-availability-drawer-button {
99 | background-color: transparent;
100 | border: none;
101 | color: rgb(var(--color-foreground));
102 | cursor: pointer;
103 | display: block;
104 | height: 4.4rem;
105 | padding: 1.2rem;
106 | width: 4.4rem;
107 | }
108 |
109 | .pickup-availability-drawer-button:hover {
110 | color: rgba(var(--color-foreground), 0.75);
111 | }
112 |
113 | .pickup-availability-variant {
114 | font-size: 1.3rem;
115 | line-height: calc(1 + 0.2 / var(--font-body-scale));
116 | margin: 0 0 1.2rem;
117 | text-transform: capitalize;
118 | }
119 |
120 | .pickup-availability-variant > * + strong {
121 | margin-left: 1rem;
122 | }
123 |
124 | .pickup-availability-list__item {
125 | border-bottom: 0.1rem solid rgba(var(--color-foreground), 0.08);
126 | padding: 2rem 0;
127 | }
128 |
129 | .pickup-availability-list__item:first-child {
130 | border-top: 0.1rem solid rgba(var(--color-foreground), 0.08);
131 | }
132 |
133 | .pickup-availability-list__item > * {
134 | margin: 0;
135 | }
136 |
137 | .pickup-availability-list__item > * + * {
138 | margin-top: 1rem;
139 | }
140 |
141 | .pickup-availability-address {
142 | font-style: normal;
143 | font-size: 1.2rem;
144 | line-height: calc(1 + 0.5 / var(--font-body-scale));
145 | }
146 |
147 | .pickup-availability-address p {
148 | margin: 0;
149 | }
150 |
151 | @keyframes animateDrawerOpen {
152 | @media screen and (max-width: 749px) {
153 | 0% {
154 | opacity: 0;
155 | transform: translateX(100%);
156 | }
157 |
158 | 100% {
159 | opacity: 1;
160 | transform: translateX(0);
161 | }
162 | }
163 |
164 | @media screen and (min-width: 750px) {
165 | 0% {
166 | opacity: 0;
167 | transform: translateX(100%);
168 | }
169 |
170 | 100% {
171 | opacity: 1;
172 | transform: translateX(0);
173 | }
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/snippets/email-signup-banner-background.liquid:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/assets/product-info.js:
--------------------------------------------------------------------------------
1 | if (!customElements.get('product-info')) {
2 | customElements.define(
3 | 'product-info',
4 | class ProductInfo extends HTMLElement {
5 | constructor() {
6 | super();
7 | this.input = this.querySelector('.quantity__input');
8 | this.currentVariant = this.querySelector('.product-variant-id');
9 | this.variantSelects = this.querySelector('variant-radios');
10 | this.submitButton = this.querySelector('[type="submit"]');
11 | }
12 |
13 | cartUpdateUnsubscriber = undefined;
14 | variantChangeUnsubscriber = undefined;
15 |
16 | connectedCallback() {
17 | if (!this.input) return;
18 | this.quantityForm = this.querySelector('.product-form__quantity');
19 | if (!this.quantityForm) return;
20 | this.setQuantityBoundries();
21 | if (!this.dataset.originalSection) {
22 | this.cartUpdateUnsubscriber = subscribe(PUB_SUB_EVENTS.cartUpdate, this.fetchQuantityRules.bind(this));
23 | }
24 | this.variantChangeUnsubscriber = subscribe(PUB_SUB_EVENTS.variantChange, (event) => {
25 | const sectionId = this.dataset.originalSection ? this.dataset.originalSection : this.dataset.section;
26 | if (event.data.sectionId !== sectionId) return;
27 | this.updateQuantityRules(event.data.sectionId, event.data.html);
28 | this.setQuantityBoundries();
29 | });
30 | }
31 |
32 | disconnectedCallback() {
33 | if (this.cartUpdateUnsubscriber) {
34 | this.cartUpdateUnsubscriber();
35 | }
36 | if (this.variantChangeUnsubscriber) {
37 | this.variantChangeUnsubscriber();
38 | }
39 | }
40 |
41 | setQuantityBoundries() {
42 | const data = {
43 | cartQuantity: this.input.dataset.cartQuantity ? parseInt(this.input.dataset.cartQuantity) : 0,
44 | min: this.input.dataset.min ? parseInt(this.input.dataset.min) : 1,
45 | max: this.input.dataset.max ? parseInt(this.input.dataset.max) : null,
46 | step: this.input.step ? parseInt(this.input.step) : 1,
47 | };
48 |
49 | let min = data.min;
50 | const max = data.max === null ? data.max : data.max - data.cartQuantity;
51 | if (max !== null) min = Math.min(min, max);
52 | if (data.cartQuantity >= data.min) min = Math.min(min, data.step);
53 |
54 | this.input.min = min;
55 | this.input.max = max;
56 | this.input.value = min;
57 | publish(PUB_SUB_EVENTS.quantityUpdate, undefined);
58 | }
59 |
60 | fetchQuantityRules() {
61 | if (!this.currentVariant || !this.currentVariant.value) return;
62 | this.querySelector('.quantity__rules-cart .loading-overlay').classList.remove('hidden');
63 | fetch(`${this.dataset.url}?variant=${this.currentVariant.value}§ion_id=${this.dataset.section}`)
64 | .then((response) => {
65 | return response.text();
66 | })
67 | .then((responseText) => {
68 | const html = new DOMParser().parseFromString(responseText, 'text/html');
69 | this.updateQuantityRules(this.dataset.section, html);
70 | this.setQuantityBoundries();
71 | })
72 | .catch((e) => {
73 | console.error(e);
74 | })
75 | .finally(() => {
76 | this.querySelector('.quantity__rules-cart .loading-overlay').classList.add('hidden');
77 | });
78 | }
79 |
80 | updateQuantityRules(sectionId, html) {
81 | const quantityFormUpdated = html.getElementById(`Quantity-Form-${sectionId}`);
82 | const selectors = ['.quantity__input', '.quantity__rules', '.quantity__label'];
83 | for (let selector of selectors) {
84 | const current = this.quantityForm.querySelector(selector);
85 | const updated = quantityFormUpdated.querySelector(selector);
86 | if (!current || !updated) continue;
87 | if (selector === '.quantity__input') {
88 | const attributes = ['data-cart-quantity', 'data-min', 'data-max', 'step'];
89 | for (let attribute of attributes) {
90 | const valueUpdated = updated.getAttribute(attribute);
91 | if (valueUpdated !== null) current.setAttribute(attribute, valueUpdated);
92 | }
93 | } else {
94 | current.innerHTML = updated.innerHTML;
95 | }
96 | }
97 | }
98 | }
99 | );
100 | }
101 |
--------------------------------------------------------------------------------
/sections/pickup-availability.liquid:
--------------------------------------------------------------------------------
1 | {% comment %}theme-check-disable UndefinedObject{% endcomment %}
2 | {%- assign pick_up_availabilities = product_variant.store_availabilities | where: 'pick_up_enabled', true -%}
3 |
4 | {%- if pick_up_availabilities.size > 0 -%}
5 |
6 | {%- liquid
7 | assign closest_location = pick_up_availabilities.first
8 |
9 | if closest_location.available
10 | render 'icon-tick'
11 | endif
12 | -%}
13 |
14 |
15 | {%- if closest_location.available -%}
16 |
17 | {{
18 | 'products.product.pickup_availability.pick_up_available_at_html'
19 | | t: location_name: closest_location.location.name
20 | }}
21 |
22 |
{{ closest_location.pick_up_time }}
23 |
34 | {%- else -%}
35 |
36 | {{
37 | 'products.product.pickup_availability.pick_up_unavailable_at_html'
38 | | t: location_name: closest_location.location.name
39 | }}
40 |
41 | {%- if pick_up_availabilities.size > 1 -%}
42 |
49 | {%- endif -%}
50 | {%- endif -%}
51 |
52 |
53 |
54 |
61 |
69 |
70 | {%- unless product_variant.product.has_only_default_variant -%}
71 |
72 | {%- for product_option in product_variant.product.options_with_values -%}
73 | {{ product_option.name | escape }}:
74 | {%- for value in product_option.values -%}
75 | {%- if product_option.selected_value == value -%}
76 | {{ value | escape }}
77 | {%- endif -%}
78 | {%- endfor -%}
79 | {%- unless forloop.last -%}, {%- endunless -%}
80 | {%- endfor -%}
81 |
82 | {%- endunless -%}
83 |
84 |
107 |
108 | {%- endif -%}
109 |
--------------------------------------------------------------------------------
/assets/component-cart.css:
--------------------------------------------------------------------------------
1 | .cart {
2 | position: relative;
3 | display: block;
4 | }
5 |
6 | .cart__empty-text,
7 | .is-empty .cart__contents,
8 | cart-items.is-empty .title-wrapper-with-link,
9 | .is-empty .cart__footer {
10 | display: none;
11 | }
12 |
13 | .is-empty .cart__empty-text,
14 | .is-empty .cart__warnings {
15 | display: block;
16 | }
17 |
18 | .cart__warnings {
19 | display: none;
20 | text-align: center;
21 | padding: 3rem 0 1rem;
22 | }
23 |
24 | .cart__empty-text {
25 | margin: 4.5rem 0 2rem;
26 | }
27 |
28 | .cart__contents > * + * {
29 | margin-top: 2.5rem;
30 | }
31 |
32 | .cart__login-title {
33 | margin: 5.5rem 0 0.5rem;
34 | }
35 |
36 | .cart__login-paragraph {
37 | margin-top: 0.8rem;
38 | }
39 |
40 | .cart__login-paragraph a {
41 | font-size: inherit;
42 | }
43 |
44 | @media screen and (min-width: 990px) {
45 | .cart__warnings {
46 | padding: 7rem 0 1rem;
47 | }
48 |
49 | .cart__empty-text {
50 | margin: 0 0 3rem;
51 | }
52 | }
53 |
54 | cart-items {
55 | display: block;
56 | }
57 |
58 | .cart__items {
59 | position: relative;
60 | padding-bottom: 3rem;
61 | border-bottom: 0.1rem solid rgba(var(--color-foreground), 0.08);
62 | }
63 |
64 | .cart__items--disabled {
65 | pointer-events: none;
66 | }
67 |
68 | .cart__footer {
69 | padding: 4rem 0 0;
70 | }
71 |
72 | .cart__footer-wrapper:last-child .cart__footer {
73 | padding-bottom: 5rem;
74 | }
75 |
76 | .cart__footer > div:only-child {
77 | margin-left: auto;
78 | }
79 |
80 | .cart__footer > * + * {
81 | margin-top: 4rem;
82 | }
83 |
84 | .cart__footer .discounts {
85 | margin-top: 1rem;
86 | }
87 |
88 | .cart__note {
89 | height: fit-content;
90 | }
91 |
92 | .cart__note label {
93 | display: flex;
94 | align-items: flex-end;
95 | position: absolute;
96 | line-height: 1;
97 | height: 1.8rem;
98 | top: -3rem;
99 | color: rgba(var(--color-foreground), 0.75);
100 | }
101 |
102 | .cart__note .field__input {
103 | height: 100%;
104 | position: relative;
105 | border-radius: var(--inputs-radius);
106 | padding: 1rem 2rem;
107 | }
108 |
109 | .cart__note .text-area {
110 | resize: vertical;
111 | }
112 |
113 | .cart__note:after,
114 | .cart__note:hover.cart__note:after,
115 | .cart__note:before,
116 | .cart__note:hover.cart__note:before,
117 | .cart__note .field__input:focus,
118 | .cart__note .field__input {
119 | border-bottom-right-radius: 0;
120 | }
121 |
122 | @media screen and (min-width: 750px) {
123 | .cart__items {
124 | grid-column-start: 1;
125 | grid-column-end: 3;
126 | padding-bottom: 4rem;
127 | }
128 |
129 | .cart__contents > * + * {
130 | margin-top: 0;
131 | }
132 |
133 | .cart__items + .cart__footer {
134 | grid-column: 2;
135 | }
136 |
137 | .cart__footer {
138 | display: flex;
139 | justify-content: space-between;
140 | border: 0;
141 | }
142 |
143 | .cart__footer-wrapper:last-child {
144 | padding-top: 0;
145 | }
146 |
147 | .cart__footer > * {
148 | width: 35rem;
149 | }
150 |
151 | .cart__footer > * + * {
152 | margin-left: 4rem;
153 | margin-top: 0;
154 | }
155 | }
156 |
157 | .cart__ctas button {
158 | width: 100%;
159 | }
160 |
161 | .cart__ctas > *:not(noscript:first-child) + * {
162 | margin-top: 1rem;
163 | }
164 |
165 | .cart__update-button {
166 | margin-bottom: 1rem;
167 | }
168 |
169 | .cart__dynamic-checkout-buttons {
170 | max-width: 36rem;
171 | margin: 0 auto;
172 | }
173 |
174 | .cart__blocks > * + * {
175 | margin-top: 1rem;
176 | }
177 |
178 | .cart__dynamic-checkout-buttons div[role='button'] {
179 | border-radius: var(--buttons-radius-outset) !important;
180 | }
181 |
182 | .cart-note__label {
183 | display: inline-block;
184 | margin-bottom: 1rem;
185 | line-height: calc(1 + 1 / var(--font-body-scale));
186 | }
187 |
188 | .tax-note {
189 | margin: 2.2rem 0 1.6rem auto;
190 | text-align: center;
191 | display: block;
192 | }
193 |
194 | .cart__checkout-button {
195 | max-width: 36rem;
196 | }
197 |
198 | .cart__ctas {
199 | text-align: center;
200 | }
201 |
202 | @media screen and (min-width: 750px) {
203 | .cart-note {
204 | max-width: 35rem;
205 | }
206 |
207 | .cart__update-button {
208 | margin-bottom: 0;
209 | margin-right: 0.8rem;
210 | }
211 |
212 | .tax-note {
213 | margin-bottom: 2.2rem;
214 | text-align: right;
215 | }
216 |
217 | [data-shopify-buttoncontainer] {
218 | justify-content: flex-end;
219 | }
220 |
221 | .cart__ctas {
222 | display: flex;
223 | gap: 1rem;
224 | }
225 | }
226 |
--------------------------------------------------------------------------------