├── locales ├── fr.json ├── en.default.json └── en.default.schema.json ├── src ├── scripts │ ├── vendors │ │ └── .gitkeep │ ├── animations │ │ └── .gitkeep │ ├── base.js │ ├── utils │ │ └── fetch.js │ ├── giftcard.js │ ├── password.js │ └── components │ │ └── dark-mode-button.js └── styles │ ├── components │ ├── cart.scss │ ├── _price.scss │ ├── article-card.scss │ ├── pagination.scss │ ├── product-card.scss │ ├── predictive-search.scss │ ├── dark-mode-button.scss │ ├── _typeface.scss │ ├── _field.scss │ └── _button.scss │ ├── sections │ ├── _footer.scss │ ├── main-404.scss │ ├── main-blog.scss │ ├── main-cart.scss │ ├── main-page.scss │ ├── rich-text.scss │ ├── main-account.scss │ ├── main-article.scss │ ├── main-login.scss │ ├── main-order.scss │ ├── main-product.scss │ ├── main-search.scss │ ├── multicolumn.scss │ ├── newsletter.scss │ ├── _main-giftcard.scss │ ├── _main-password.scss │ ├── main-register.scss │ ├── featured-product.scss │ ├── image-with-text.scss │ ├── main-adresses.scss │ ├── main-collection.scss │ ├── main-reset-password.scss │ ├── main-activate-account.scss │ ├── main-list-collection.scss │ ├── _header.scss │ ├── _header-password.scss │ └── welcome.scss │ ├── objects │ ├── _container.scss │ └── _grid.scss │ ├── settings │ ├── _breakpoints.scss │ ├── _fonts.scss │ └── _colors.scss │ ├── utilities │ ├── _align.scss │ ├── _space.scss │ └── _display.scss │ ├── generic │ ├── _print.scss │ ├── _elements.scss │ └── _reset.scss │ ├── giftcard.scss │ ├── password.scss │ ├── base.scss │ └── tools │ ├── _functions.scss │ └── _mixins.scss ├── assets ├── base.js ├── giftcard.js ├── password.js ├── manifest.json ├── giftcard.css ├── password.css └── base.css ├── config ├── settings_data.json └── settings_schema.json ├── snippets ├── weglot_hreftags.liquid ├── weglot_switcher.liquid ├── component-price.liquid ├── component-product-card.liquid ├── component-article-card.liquid ├── head-metas.liquid ├── component-social-list.liquid ├── head-seo.liquid └── head-settings.liquid ├── templates ├── 404.json ├── blog.json ├── cart.json ├── page.json ├── search.json ├── article.json ├── product.json ├── collection.json ├── customers │ ├── login.json │ ├── order.json │ ├── account.json │ ├── addresses.json │ ├── register.json │ ├── activate_account.json │ └── reset_password.json ├── list-collections.json ├── password.json ├── index.json └── gift_card.liquid ├── sections ├── footer.liquid ├── footer-password.liquid ├── main-blog.liquid ├── main-cart.liquid ├── main-404.liquid ├── main-login.liquid ├── main-order.liquid ├── main-page.liquid ├── main-search.liquid ├── main-account.liquid ├── main-adresses.liquid ├── main-collection.liquid ├── main-register.liquid ├── main-activate-account.liquid ├── main-list-collections.liquid ├── main-reset-password.liquid ├── main-article.liquid ├── main-product.liquid ├── custom-liquid.liquid ├── apps.liquid ├── header.liquid ├── header-password.liquid └── welcome.liquid ├── .gitignore ├── .shopifyignore ├── .github ├── workflows │ ├── check.yml │ └── lighthouse.yml ├── LICENSE ├── CHANGELOG.md └── CONTRIBUTING.md ├── translation.yml ├── package.json ├── README.md └── layout ├── password.liquid ├── giftcard.liquid └── theme.liquid /locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | } 3 | -------------------------------------------------------------------------------- /src/scripts/vendors/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/scripts/animations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/scripts/base.js: -------------------------------------------------------------------------------- 1 | window.console.log('Hello from Theme Layout 👋.') 2 | -------------------------------------------------------------------------------- /assets/base.js: -------------------------------------------------------------------------------- 1 | window.console.log("Hello from Theme Layout \u{1F44B}."); 2 | -------------------------------------------------------------------------------- /src/scripts/utils/fetch.js: -------------------------------------------------------------------------------- 1 | window.console.log('Hello from fetch utility.') 2 | -------------------------------------------------------------------------------- /assets/giftcard.js: -------------------------------------------------------------------------------- 1 | window.console.log("Hello from Giftcard Layout \u{1F44B}."); 2 | -------------------------------------------------------------------------------- /assets/password.js: -------------------------------------------------------------------------------- 1 | window.console.log("Hello from Password Layout \u{1F44B}."); 2 | -------------------------------------------------------------------------------- /src/scripts/giftcard.js: -------------------------------------------------------------------------------- 1 | window.console.log('Hello from Giftcard Layout 👋.') 2 | -------------------------------------------------------------------------------- /src/scripts/password.js: -------------------------------------------------------------------------------- 1 | window.console.log('Hello from Password Layout 👋.') 2 | -------------------------------------------------------------------------------- /config/settings_data.json: -------------------------------------------------------------------------------- 1 | { 2 | "current": { 3 | }, 4 | "presets": { 5 | "Default": { 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /snippets/weglot_hreftags.liquid: -------------------------------------------------------------------------------- 1 | {%- comment -%} Variables set by Weglot's preferences panel {%- endcomment -%} 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /templates/404.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-404" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/blog.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-blog" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/cart.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-cart" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/page.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-page" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/search.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-search" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/article.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-article" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/product.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-product" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-collection" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/customers/login.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-login" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/customers/order.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-order" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/customers/account.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-account" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/customers/addresses.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-adresses" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/customers/register.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-register" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/list-collections.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-list-collections" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/customers/activate_account.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-activate-account" 5 | } 6 | }, 7 | "order": [ 8 | "main" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /templates/password.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "password", 3 | "sections": { 4 | "main": { 5 | "type": "footer-password" 6 | } 7 | }, 8 | "order": [ 9 | "main" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/styles/components/cart.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## COMPONENT: CART 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/components/_price.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## COMPONENT: PRICE 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /sections/footer.liquid: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% schema %} 4 | { 5 | "name": "t:sections.footer.name", 6 | "tag": "footer", 7 | "settings": [ 8 | 9 | ] 10 | } 11 | {% endschema %} 12 | -------------------------------------------------------------------------------- /templates/customers/reset_password.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "main-reset-password", 5 | "settings": { 6 | } 7 | } 8 | }, 9 | "order": [ 10 | "main" 11 | ] 12 | } -------------------------------------------------------------------------------- /src/styles/components/article-card.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## COMPONENT: ARTICLE CARD 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/components/pagination.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## COMPONENT: PAGGINATION 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/components/product-card.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## COMPONENT: PRODUCT CARD 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/_footer.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: FOOTER 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-404.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN 404 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-blog.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN BLOG 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-cart.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN CART 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-page.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN PAGE 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/rich-text.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY DYNAMIC SECTION: RICH TEXT 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/components/predictive-search.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## COMPONENT: PREDICTIVE SEARCH 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-account.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN ACCOUNT 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-article.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN ARTICLE 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-login.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN LOGIN 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-order.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN ORDER 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-product.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN PRODUCT 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-search.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN SEARCH 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/multicolumn.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY DYNAMIC SECTION: MULTICOLUMN 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/newsletter.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY DYNAMIC SECTION: NEWSLETTER 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /sections/footer-password.liquid: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% schema %} 4 | { 5 | "name": "t:sections.password.name", 6 | "tag": "footer", 7 | "settings": [ 8 | 9 | ] 10 | } 11 | {% endschema %} 12 | -------------------------------------------------------------------------------- /src/styles/sections/_main-giftcard.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN GIFTCARD 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/_main-password.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN PASSWORD 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-register.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN REGISTER 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/featured-product.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY DYNAMIC SECTION: FEATURED PRODUCT 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/image-with-text.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY DYNAMIC SECTION: IMAGE WITH TEXT 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-adresses.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN ACTIVATE ACCOUNT 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-collection.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN COLLECTION 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-reset-password.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN RESET PASSWORD 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-activate-account.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN ACTIVATE ACCOUNT 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /src/styles/sections/main-list-collection.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: MAIN LIST COLLECTION 3 | // ========================================================================== 4 | -------------------------------------------------------------------------------- /snippets/weglot_switcher.liquid: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /sections/main-blog.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-blog.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | 5 | {% schema %} 6 | { 7 | "name": "t:sections.blog.name", 8 | "tag": "section", 9 | "settings": [ 10 | 11 | ] 12 | } 13 | {% endschema %} 14 | -------------------------------------------------------------------------------- /sections/main-cart.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-cart.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | 5 | {% schema %} 6 | { 7 | "name": "t:sections.cart.name", 8 | "tag": "section", 9 | "settings": [ 10 | 11 | ] 12 | } 13 | {% endschema %} 14 | -------------------------------------------------------------------------------- /sections/main-404.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-404.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | 5 | 6 | {% schema %} 7 | { 8 | "name": "t:sections.404.name", 9 | "tag": "section", 10 | "settings": [ 11 | 12 | ] 13 | } 14 | {% endschema %} 15 | -------------------------------------------------------------------------------- /sections/main-login.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-login.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | 5 | 6 | {% schema %} 7 | { 8 | "name": "t:sections.login.name", 9 | "tag": "section", 10 | "settings": [ 11 | 12 | ] 13 | } 14 | {% endschema %} 15 | -------------------------------------------------------------------------------- /sections/main-order.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-order.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | 5 | 6 | {% schema %} 7 | { 8 | "name": "t:sections.order.name", 9 | "tag": "section", 10 | "settings": [ 11 | 12 | ] 13 | } 14 | {% endschema %} 15 | -------------------------------------------------------------------------------- /sections/main-page.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-page.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | 5 | 6 | {% schema %} 7 | { 8 | "name": "t:sections.page.name", 9 | "tag": "section", 10 | "settings": [ 11 | 12 | ] 13 | } 14 | {% endschema %} 15 | -------------------------------------------------------------------------------- /sections/main-search.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-search.css' | asset_url | stylesheet_tag }} 2 | 3 | 4 | 5 | {% schema %} 6 | { 7 | "name": "t:sections.search.name", 8 | "tag": "section", 9 | "settings": [ 10 | 11 | ] 12 | } 13 | {% endschema %} 14 | -------------------------------------------------------------------------------- /sections/main-account.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-account.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | 5 | {% schema %} 6 | { 7 | "name": "t:sections.account.name", 8 | "tag": "section", 9 | "settings": [ 10 | 11 | ] 12 | } 13 | {% endschema %} 14 | -------------------------------------------------------------------------------- /sections/main-adresses.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-adresses.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | 5 | {% schema %} 6 | { 7 | "name": "t:sections.adresses.name", 8 | "tag": "section", 9 | "settings": [ 10 | 11 | ] 12 | } 13 | {% endschema %} 14 | -------------------------------------------------------------------------------- /sections/main-collection.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-collection.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | 5 | {% schema %} 6 | { 7 | "name": "t:sections.collection.name", 8 | "tag": "section", 9 | "settings": [ 10 | 11 | ] 12 | } 13 | {% endschema %} 14 | -------------------------------------------------------------------------------- /sections/main-register.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-register.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | 5 | 6 | {% schema %} 7 | { 8 | "name": "t:sections.register.name", 9 | "tag": "section", 10 | "settings": [ 11 | 12 | ] 13 | } 14 | {% endschema %} 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Misc 2 | .DS_Store 3 | .DS_Store? 4 | ._* 5 | .Spotlight-V100 6 | ehthumbs.db 7 | Thumbs.db 8 | 9 | # Dependencies 10 | node_modules 11 | deploy.log 12 | npm-debug.log 13 | .env 14 | .env.* 15 | yarn-error.log 16 | package-lock.json 17 | yarn.lock 18 | 19 | # Others 20 | *.sass-cache* 21 | .cache/* 22 | _site 23 | /.idea 24 | -------------------------------------------------------------------------------- /sections/main-activate-account.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-activate-account.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | 5 | {% schema %} 6 | { 7 | "name": "t:sections.activate_account.name", 8 | "tag": "section", 9 | "settings": [ 10 | 11 | ] 12 | } 13 | {% endschema %} 14 | -------------------------------------------------------------------------------- /sections/main-list-collections.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-list-collection.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | 5 | {% schema %} 6 | { 7 | "name": "t:sections.list_collections.name", 8 | "tag": "section", 9 | "settings": [ 10 | 11 | ] 12 | } 13 | {% endschema %} 14 | -------------------------------------------------------------------------------- /sections/main-reset-password.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-reset-password.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | 5 | 6 | {% schema %} 7 | { 8 | "name": "t:sections.reset_password.name", 9 | "tag": "section", 10 | "settings": [ 11 | 12 | ] 13 | } 14 | {% endschema %} 15 | -------------------------------------------------------------------------------- /sections/main-article.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-article.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | {%- render 'component-article-card' -%} 5 |
6 | 7 | {% schema %} 8 | { 9 | "name": "t:sections.article.name", 10 | "tag": "article", 11 | "settings": [ 12 | 13 | ] 14 | } 15 | {% endschema %} 16 | -------------------------------------------------------------------------------- /sections/main-product.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-main-product.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 | {%- render 'component-product-card' -%} 5 |
6 | 7 | 8 | {% schema %} 9 | { 10 | "name": "t:sections.product.name", 11 | "tag": "section", 12 | "settings": [ 13 | 14 | ] 15 | } 16 | {% endschema %} 17 | -------------------------------------------------------------------------------- /.shopifyignore: -------------------------------------------------------------------------------- 1 | # See https://shopify.dev/themes/tools/cli#excluding-files-from-shopify-cli 2 | # for more about ignoring files while using Shopify CLI. 3 | 4 | # Misc 5 | .DS_Store 6 | .DS_Store? 7 | .Spotlight-V100 8 | .Trashes 9 | ehthumbs.db 10 | Thumbs.db 11 | 12 | # Dependencies 13 | node_modules 14 | package.json 15 | package-lock.json 16 | yarn.lock 17 | src/* 18 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | # Theme check CI 2 | # For more info check: https://shopify.dev/themes/tools/theme-check 3 | 4 | name: Shopify Theme Check 5 | on: [push] 6 | jobs: 7 | theme-check: 8 | name: Theme Check 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Theme Check 13 | uses: shopify/theme-check-action@v1 14 | -------------------------------------------------------------------------------- /snippets/component-price.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Renders a list of product's price regular or sale. 3 | 4 | Accepts: 5 | - product: {Object} Product Liquid object (optional) 6 | - price_class: {String} Adds a price class to the price element (optional) 7 | 8 | Usage: 9 | {%- render 'component-price', product: product -%} 10 | {% endcomment %} 11 | 12 |
13 | -------------------------------------------------------------------------------- /src/styles/sections/_header.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: HEADER 3 | // ========================================================================== 4 | 5 | .header { 6 | display: flex; 7 | flex-wrap: nowrap; 8 | justify-content: space-between; 9 | padding-top: 1rem; 10 | padding-bottom: 1rem; 11 | 12 | .header_logo { 13 | font-size: 1.4rem; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /assets/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Helium", 3 | "short_name": "Helium", 4 | "description": "A Shopify theme environment from scratch ⚙️, with Online Store 2.0 features. Built with performance ⚡️ and best practices in mind..", 5 | "background_color": "#ffffff", 6 | "theme_color": "#ffffff", 7 | "start_url": "https://helium.idbakkasse.com", 8 | "display": "standalone", 9 | "related_applications": [ 10 | { 11 | "platform": "web" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /translation.yml: -------------------------------------------------------------------------------- 1 | source_language: en 2 | target_languages: [] 3 | non_blocking_languages: [] 4 | components: 5 | - name: buyer 6 | audience: buyer 7 | scheme: 'online-store-theme' 8 | owners: ['@Shopify/themes-translations'] 9 | paths: 10 | - locales/{{language}}.json 11 | - name: merchant 12 | target_languages: [] 13 | audience: merchant 14 | scheme: 'online-store-theme' 15 | owners: ['@Shopify/themes-translations'] 16 | paths: 17 | - locales/{{language}}.schema.json 18 | -------------------------------------------------------------------------------- /sections/custom-liquid.liquid: -------------------------------------------------------------------------------- 1 |
2 | {{- section.settings.custom_liquid -}} 3 |
4 | 5 | {% schema %} 6 | { 7 | "name": "t:sections.custom-liquid.name", 8 | "tag": "section", 9 | "settings": [ 10 | { 11 | "type": "liquid", 12 | "id": "custom_liquid", 13 | "label": "t:sections.custom-liquid.settings.custom_liquid.label", 14 | "info": "t:sections.custom-liquid.settings.custom_liquid.info" 15 | } 16 | ], 17 | "presets": [ 18 | { 19 | "name": "t:sections.custom-liquid.presets.name" 20 | } 21 | ] 22 | } 23 | {% endschema %} 24 | -------------------------------------------------------------------------------- /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 | "settings": [ 11 | { 12 | "type": "checkbox", 13 | "id": "include_container", 14 | "default": true, 15 | "label": "t:sections.apps.settings.include_container.label" 16 | } 17 | ], 18 | "blocks": [ 19 | { 20 | "type": "@app" 21 | } 22 | ], 23 | "presets": [ 24 | { 25 | "name": "t:sections.apps.presets.name" 26 | } 27 | ] 28 | } 29 | {% endschema %} 30 | -------------------------------------------------------------------------------- /sections/header.liquid: -------------------------------------------------------------------------------- 1 | {{ 'component-dark-mode-button.css' | asset_url | stylesheet_tag }} 2 | 3 | 4 |
5 | 6 | 7 | 11 | 12 |
13 | 14 | {% schema %} 15 | { 16 | "name": "t:sections.header.name", 17 | "settings": [ 18 | 19 | ] 20 | } 21 | {% endschema %} 22 | -------------------------------------------------------------------------------- /snippets/component-product-card.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Renders a product card component 3 | 4 | Accepts: 5 | - product_card_product: {Object} Product Liquid object (optional) 6 | - media_size: {String} Size of the product image card. Values are "square" and "portrait". Default is "square" (optional) 7 | - show_secondary_image: {Boolean} Show the secondary image on hover. Default: false (optional) 8 | - show_vendor: {Boolean} Show the product vendor. Default: false 9 | - show_rating: {Boolean} Show the product rating. Default: false 10 | 11 | Usage: 12 | {%- render 'component-product-card', 13 | show_vendor: section.settings.show_vendor 14 | -%} 15 | {% endcomment %} 16 | 17 |
18 | -------------------------------------------------------------------------------- /src/scripts/components/dark-mode-button.js: -------------------------------------------------------------------------------- 1 | class DarkModeButton extends HTMLElement { 2 | constructor() { 3 | super() 4 | this.button = this.querySelector('button'); 5 | this.moonIcon = this.querySelector('.-moon'); 6 | this.sunIcon = this.querySelector('.-sun'); 7 | this.sunIcon.classList.add('u-hide'); 8 | 9 | if (!this.button) return; 10 | this.toggleMode = this.toggleMode.bind(this); 11 | this.button.addEventListener('click', this.toggleMode); 12 | } 13 | 14 | toggleMode() { 15 | document.documentElement.classList.toggle('is-dark'); 16 | this.moonIcon.classList.toggle('u-hide'); 17 | this.sunIcon.classList.toggle('u-hide'); 18 | } 19 | } 20 | 21 | customElements.define('dark-mode-button', DarkModeButton); 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "helium", 3 | "version": "2.0.0", 4 | "description": "Modern Shopify development workflow, with Online Store 2.0 features and built with performance and best practices in mind..", 5 | "repository": "blanklob/helium", 6 | "author": "Blanklob ", 7 | "license": "MIT", 8 | "keywords": [ 9 | "helium", 10 | "shopify", 11 | "starter", 12 | "boilerplate", 13 | "themes" 14 | ], 15 | "browserslist": [ 16 | "defaults" 17 | ], 18 | "scripts": { 19 | "serve": "helium serve", 20 | "watch": "helium watch", 21 | "build": "helium build", 22 | "lint": "helium lint" 23 | }, 24 | "devDependencies": { 25 | "@blanklob/helium": "^0.1.5" 26 | }, 27 | "dependencies": {}, 28 | "engines": { 29 | "node": ">=14.0.0", 30 | "npm": ">=7.0.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/styles/sections/_header-password.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY STATIC SECTION: HEADER PASSWORD 3 | // ========================================================================== 4 | 5 | .header-password { 6 | display: flex; 7 | justify-content: space-between; 8 | align-items: center; 9 | padding-top: 1rem; 10 | 11 | &_logo { 12 | font-size: 1.4rem; 13 | } 14 | } 15 | 16 | .header-password_form { 17 | position: absolute; 18 | top: 3rem; 19 | left: 0; 20 | bottom: 0; 21 | right: 0; 22 | 23 | &-inner { 24 | position: relative; 25 | top: 45%; 26 | transform: translateY(-50%); 27 | display: flex; 28 | flex-direction: column; 29 | justify-content: center; 30 | gap: 1rem; 31 | max-width: 400px; 32 | width: 85%; 33 | margin: auto; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /snippets/component-article-card.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Renders an article card for a given blog with settings to either show the date or not. 3 | 4 | Accepts: 5 | - blog: {Object} Blog object 6 | - article: {Object} Article object 7 | - show_date: {String} The setting either show the article date or not. If it's not included it will not show the image by default 8 | - show_author: {String} The setting either show the article author or not. If it's not included it will not show the author by default 9 | 10 | Usage: 11 | {%- render 'component-article-card' 12 | blog: blog, 13 | article: article, 14 | show_date: section.settings.show_date 15 | -%} 16 | {% endcomment %} 17 | 18 |
19 | 20 | 21 |
22 | -------------------------------------------------------------------------------- /src/styles/objects/_container.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## OBJECTS: CONTAINER 3 | // ========================================================================== 4 | 5 | /// @content Object classes for diffrentes container sizes. 6 | /// 7 | /// .container {} - Base container. 8 | /// .container.-small {} - Small container. 9 | /// and others, add as you wish... 10 | /// 11 | 12 | .container { 13 | width: 100%; 14 | margin: { 15 | left: auto; 16 | right: auto; 17 | top: 0; 18 | bottom: 0; 19 | } 20 | 21 | &.-small { 22 | padding-left: rem(8px); 23 | padding-right: rem(8px); 24 | } 25 | 26 | &, 27 | &.-medium { 28 | padding-left: rem(16px); 29 | padding-right: rem(16px); 30 | } 31 | 32 | &.-large { 33 | padding-left: rem(32px); 34 | padding-right: rem(32px); 35 | } 36 | 37 | &.-narrow { 38 | max-width: 30rem; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/styles/sections/welcome.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SHOPIFY DYNAMIC SECTION: WELCOME 3 | // ========================================================================== 4 | 5 | .welcome { 6 | display: grid; 7 | justify-content: center; 8 | align-items: center; 9 | 10 | .icon { 11 | width: 1.5rem; 12 | height: 1.5rem; 13 | margin-left: 0.5rem; 14 | } 15 | 16 | .welcome_wrapper { 17 | width: 90%; 18 | max-width: 900px; 19 | margin: 0 auto; 20 | } 21 | 22 | .welcome_feature-wrapper { 23 | max-width: 1200px; 24 | display: flex; 25 | justify-content: space-between; 26 | flex-flow: row wrap; 27 | column-gap: 30px; 28 | } 29 | 30 | @media screen and (max-width: 749px) { 31 | .welcome_feature-wrapper { 32 | justify-content: center; 33 | row-gap: 20px; 34 | } 35 | } 36 | 37 | .welcome_feature { 38 | width: 90%; 39 | max-width: 360px; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/styles/components/dark-mode-button.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## COMPONENT: DARK MODE BUTTON 3 | // ========================================================================== 4 | 5 | dark-mode-button { 6 | .button { 7 | padding: 0.5rem; 8 | border-radius: 100%; 9 | } 10 | } 11 | 12 | .is-dark { 13 | body { 14 | background-color: rgba(var(--color-base-solid-button), 0.98); 15 | color: rgba(var(--color-base-background-primary), 0.98); 16 | } 17 | 18 | .heading, 19 | .body { 20 | color: rgba(var(--color-base-background-primary), 0.96); 21 | } 22 | 23 | .button { 24 | background-color: rgba(var(--color-base-background-primary), 0.96); 25 | color: rgba(var(--color-base-solid-button), 0.98); 26 | } 27 | 28 | .field { 29 | border-color: rgba(var(--color-base-background-primary), 0.96); 30 | &_input { 31 | color: rgba(var(--color-base-background-primary), 0.96); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.github/workflows/lighthouse.yml: -------------------------------------------------------------------------------- 1 | # For more infos check out https://shopify.dev/themes/tools/lighthouse-ci 2 | 3 | name: Shopify Lighthouse CI 4 | on: [push] 5 | jobs: 6 | lhci: 7 | name: Lighthouse 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Lighthouse 12 | uses: shopify/lighthouse-ci-action@1.0 13 | with: 14 | app_id: ${{ secrets.SHOP_APP_ID }} 15 | app_password: ${{ secrets.SHOP_APP_PASSWORD }} 16 | store: ${{ secrets.SHOP_STORE }} 17 | password: ${{ secrets.SHOP_PASSWORD }} 18 | 19 | # You first need to configure these in Github secrets. 20 | lhci_github_app_token: ${{ secrets.LHCI_GITHUB_APP_TOKEN }} 21 | 22 | ## Lighthouse settings 23 | 24 | # lhci_min_score_performance: 0.9 25 | # lhci_min_score_accessibility: 0.9 26 | 27 | ## Run Lighthouse test on specific product/collection 28 | 29 | # product_handle: 'worst-sneakers' 30 | # collection_handle: 'sneakers' 31 | 32 | -------------------------------------------------------------------------------- /src/styles/settings/_breakpoints.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SETTINGS: BREAKPOINTS 3 | // ========================================================================== 4 | 5 | /// @content This core file sets up reponsive breakpoints. 6 | /// These are the same breakpoints that are used in reponsive 7 | /// 8 | /// @throw 9 | /// Global variable name must always start with '$theme-' prefix/namespace. 10 | /// 11 | /// @type Map 12 | /// @access public 13 | /// 14 | /// Add as you wish. 15 | 16 | $breakpoint-xs: 425px !default; 17 | $breakpoint-sm: 750px !default; 18 | $breakpoint-md: 1025px !default; 19 | $breakpoint-lg: 1200px !default; 20 | $breakpoint-xlg: 1440px !default; 21 | 22 | $breakpoint-xxs-max: ($breakpoint-xs - 1); 23 | $breakpoint-xs-max: ($breakpoint-sm - 1); 24 | $breakpoint-sm-max: ($breakpoint-md - 1); 25 | $breakpoint-md-max: ($breakpoint-lg - 1); 26 | $breakpoint-lg-max: ($breakpoint-xlg - 1); 27 | 28 | $breakpoints: ( 29 | xxs: 0px, 30 | xs: $breakpoint-xs, 31 | sm: $breakpoint-sm, 32 | md: $breakpoint-md, 33 | lg: $breakpoint-lg, 34 | xlg: $breakpoint-xlg, 35 | ) !default; 36 | -------------------------------------------------------------------------------- /.github/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Youness Idbakkasse (youness@idbakkasse.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/styles/utilities/_align.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## UTILITIES: ALIGN 3 | // ========================================================================== 4 | 5 | /// @content Utility classes to align elements inside containers. 6 | /// 7 | /// .u-float-left {} - Float to the left. 8 | /// .u-align-middle {} - Align in the middle. 9 | /// and others... 10 | /// 11 | 12 | // Floats 13 | .u-float-left { 14 | float: left !important; 15 | } 16 | 17 | .u-float-right { 18 | float: right !important; 19 | } 20 | 21 | // Horizontal alignement 22 | .u-align-left { 23 | text-align: left !important; 24 | } 25 | 26 | .u-align-right { 27 | text-align: right !important; 28 | } 29 | 30 | .u-align-center { 31 | text-align: center !important; 32 | } 33 | 34 | // Vertical alignement 35 | .u-align-top { 36 | vertical-align: top !important; 37 | } 38 | 39 | .u-align-baseline { 40 | vertical-align: baseline !important; 41 | } 42 | 43 | .u-align-bottom { 44 | vertical-align: bottom !important; 45 | } 46 | 47 | .u-align-middle { 48 | vertical-align: middle !important; 49 | } 50 | 51 | .u-align-top { 52 | vertical-align: top !important; 53 | } 54 | -------------------------------------------------------------------------------- /src/styles/settings/_fonts.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SETTINGS: FONTS 3 | // ========================================================================== 4 | 5 | /// @content Basic Theme font variables extracted from css custom properties 6 | /// defined in the "snippets/head-settings.liquid" file. 7 | /// 8 | /// This file sets up the theme font variables. 9 | /// Basically, take the custom properties defined in the "snippets/head-settings.liquid" 10 | /// file and turned them to SCSS $variables. 11 | /// 12 | 13 | // All these font properties can be changed in the theme customizer/editor. 14 | /// @type String 15 | /// @access public 16 | /// 17 | 18 | // Heading text ************************ 19 | $font-heading-family: var(--font-heading-family) !default; 20 | $font-heading-style: var(--font-heading-style) !default; 21 | $font-heading-weight: var(--font-heading-weight) !default; 22 | 23 | // Body text ************************ 24 | $font-body-family: var(--font-body-family) !default; 25 | $font-body-style: var(--font-body-style) !default; 26 | $font-body-weight: var(--font-body-weight) !default; 27 | 28 | // Base size & line-height ************************ 29 | $font-base-size: 16px !default; 30 | -------------------------------------------------------------------------------- /src/styles/settings/_colors.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## SETTINGS: COLORS 3 | // ========================================================================== 4 | 5 | /// @content This file sets up the theme color variables. 6 | /// 7 | /// This file is mounted to the global settings liquid file. 8 | 9 | // All these colors can be changed in the theme customizer/editor, 10 | // Ude the base colors to create more color schemas. 11 | /// @type String 12 | /// @access public 13 | 14 | // Global brand colors 15 | $color-base-primary: rgba(var(--color-base-accent-primary), 1) !default; 16 | $color-base-secondary: rgba(var(--color-base-accent-secondary), 1) !default; 17 | 18 | // Text 19 | $color-base-text: rgba(var(--color-base-text), 1) !default; 20 | 21 | // Buttons 22 | // Secondary button style can be added if needed. 23 | $color-base-solid-button: rgba(var(--color-base-solid-button), 1) !default; 24 | $color-base-outline-button: rgba(var(--color-base-outline-button), 1) !default; 25 | 26 | // Background 27 | $color-base-background-primary: rgba( 28 | var(--color-base-background-primary), 29 | 1 30 | ) !default; 31 | 32 | $color-base-background-secondary: rgba( 33 | var(--color-base-background-secondary), 34 | 1 35 | ) !default; 36 | -------------------------------------------------------------------------------- /src/styles/components/_typeface.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## COMPONENT: TYPEFACE 3 | // ========================================================================== 4 | 5 | /// @content Component specific classes for heading. 6 | /// This file contains suite of classes like. 7 | /// 8 | /// .heading {} - Base heading font. 9 | /// ...add others as you wish. 10 | /// 11 | 12 | .heading, 13 | h1, 14 | h2, 15 | h3, 16 | h4, 17 | h5, 18 | h6 { 19 | font-family: $font-heading-family; 20 | font-style: $font-heading-style; 21 | font-weight: $font-heading-weight; 22 | color: inherit; 23 | text-decoration: none; 24 | } 25 | 26 | .heading { 27 | // Size variants 28 | h1, 29 | &.-h1 { 30 | font-size: rem(54px); 31 | line-height: 1.2; 32 | @media screen and (max-width: 750px) { 33 | font-size: rem(38px); 34 | } 35 | } 36 | 37 | h2, 38 | &.-h2 { 39 | font-size: rem(26px); 40 | @media screen and (max-width: 750px) { 41 | font-size: rem(22px); 42 | } 43 | } 44 | 45 | h3, 46 | &.-h3 { 47 | font-size: rem(19px); 48 | } 49 | 50 | h4, 51 | &.-h4 { 52 | font-size: rem(17px); 53 | } 54 | 55 | &.-bold { 56 | font-weight: 700; 57 | } 58 | 59 | &.-upper { 60 | text-transform: uppercase; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/styles/utilities/_space.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## UTILITIES: SPACE 3 | // ========================================================================== 4 | 5 | /// @content Utility classes to put specific spacing values into elements. 6 | /// 7 | /// .u-ph-s {} - small horizontal padding 8 | /// .u-m-l {} - large margin 9 | /// .u-mv-none {} - no vertical margin 10 | /// and others... 11 | /// 12 | 13 | $theme-spacing-directions: ( 14 | null: null, 15 | 't': '-top', 16 | 'r': '-right', 17 | 'b': '-bottom', 18 | 'l': '-left', 19 | 'h': '-left' '-right', 20 | 'v': '-top' '-bottom', 21 | ) !default; 22 | 23 | $theme-spacing-properties: ( 24 | 'p': 'padding', 25 | 'm': 'margin', 26 | ) !default; 27 | 28 | $theme-spacing-sizes: ( 29 | '-small': em(8px), 30 | '-medium': em(32px), 31 | '-large': em(64px), 32 | '-none': 0, 33 | ) !default; 34 | 35 | @each $property-namespace, $property in $theme-spacing-properties { 36 | @each $direction-namespace, $direction-rules in $theme-spacing-directions { 37 | @each $size-namespace, $size in $theme-spacing-sizes { 38 | .u-#{$property-namespace}#{$direction-namespace}#{$size-namespace} { 39 | @each $direction in $direction-rules { 40 | #{$property}#{$direction}: $size !important; 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /locales/en.default.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "social": { 4 | "title": { 5 | "twitter": "Twitter", 6 | "facebook": "Facebook", 7 | "pinterest": "Pinterest", 8 | "instagram": "Instagram", 9 | "tumblr": "Tumblr", 10 | "snapchat": "Snapchat", 11 | "youtube": "YouTube", 12 | "vimeo": "Vimeo", 13 | "tiktok": "TikTok" 14 | } 15 | } 16 | }, 17 | "accessibility": { 18 | "skip_to_content": "Skip to main content", 19 | "refresh_page": "Refresh the page", 20 | "close": "Close" 21 | }, 22 | "sections": { 23 | "cart": { 24 | "empty": "Your cart is empty", 25 | "cart_error": "There was an error while updating your cart. Please try again.", 26 | "cart_quantity_error": "You can only add [quantity] of this item to your cart." 27 | } 28 | }, 29 | "templates": { 30 | "gift_card": { 31 | "title": "Here's your {{ value }} gift card for {{ shop }}!", 32 | "subtext": "Your gift card", 33 | "gift_card_code": "Gift card code", 34 | "shop_link": "Continue shopping", 35 | "remaining_html": "Remaining {{ balance }}", 36 | "add_to_apple_wallet": "Add to Apple Wallet", 37 | "qr_image_alt": "QR code — scan to redeem gift card", 38 | "copy_code": "Copy code", 39 | "expired": "Expired", 40 | "copy_code_success": "Code copied successfully", 41 | "print_gift_card": "Print" 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/styles/generic/_print.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## GENERIC: PRINT 3 | // ========================================================================== 4 | 5 | /// Very crude, reset-like styles for the print query. 6 | @media print { 7 | /// 1. Black prints faster: http://www.sanbeiji.com/archives/953 8 | *, 9 | *::before, 10 | *::after { 11 | background: transparent !important; 12 | box-shadow: none !important; 13 | color: #000000 !important; // [1] 14 | text-shadow: none !important; 15 | } 16 | 17 | a, 18 | a:visited { 19 | text-decoration: underline; 20 | } 21 | 22 | a[href]::after { 23 | content: ' (' attr(href) ')'; 24 | } 25 | 26 | abbr[title]::after { 27 | content: ' (' attr(title) ')'; 28 | } 29 | 30 | // Don’t show links that are fragment identifiers, or use the `javascript:` 31 | // pseudo protocol. 32 | a[href^='#']::after, 33 | a[href^='javascript:']::after { 34 | content: ''; 35 | } 36 | 37 | pre, 38 | blockquote { 39 | border: 1px solid #999999; 40 | page-break-inside: avoid; 41 | } 42 | 43 | // Printing Tables: http://css-discuss.incutio.com/wiki/Printing_Tables 44 | thead { 45 | display: table-header-group; 46 | } 47 | 48 | tr, 49 | img { 50 | page-break-inside: avoid; 51 | } 52 | 53 | img { 54 | max-width: 100% !important; 55 | } 56 | 57 | p, 58 | h2, 59 | h3 { 60 | orphans: 3; 61 | widows: 3; 62 | } 63 | 64 | h2, 65 | h3 { 66 | page-break-after: avoid; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Helium 2 | 3 | > A Shopify theme environment from scratch ⚙️, with Online Store 2.0 features. Built with performance ⚡️ and best practices in mind, has sensible defaults for structured data, open graphs. Hot Module Reloading on SASS/ES6 file changes for rapid development and many other features... 4 | 5 | This was made as a follow-up to the Shopify Unite 2021 event revealing the new theme online store 2.0 that has supports for JSON templates and section everywhere concept and few other features. 6 | 7 | ## Quick starter 8 | 9 | Make sure you have the following minimum versions: 10 | 11 | * Shopify CLI >= 2.4.0 12 | * Node >= 14.0.0 13 | 14 | > ℹ️ You'll need to authenticate to your development Shopify store before runing the development server. 15 | 16 | ```shell 17 | shopify login --store your-store.myshopify.com 18 | ``` 19 | 20 | Get started by cloning the repository. 21 | 22 | ```shell 23 | shopify theme init -u https://github.com/blanklob/helium.git 24 | ``` 25 | 26 | > Pro tip: click the `Use this template` button above to start from a fresh repositry. 27 | 28 | Then lunch the development server on `localhost:9292` using NPM/Yarn. 29 | 30 | The command will also run Helium's watch mode on files. 31 | 32 | ```shell 33 | npm run serve 34 | ``` 35 | 36 | Happy coding :penguin: 37 | 38 | ## Contributing 39 | 40 | Everyone is welcome to make Shopify theme development better! Please read the [Contributing guide](.github/CONTRIBUTING.md) before creating issues or submitting pull requests. 41 | 42 | ## License 43 | 44 | MIT License Copyright (c) 2022 Blanklob. See [LICENSE](.github/LICENSE) for further details. 45 | -------------------------------------------------------------------------------- /src/styles/giftcard.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## LAYOUT: GIFTCARD 3 | // ========================================================================== 4 | 5 | /// @content 6 | /// DO NOT ADD CLASSES OR RULES IN THIS FILE DIRECTLY. 7 | /// Instead, use imports to add extensions or snippets you made along the project. 8 | /// 9 | /// 10 | /// Production build weights only ~10kb (~2kb gzipped) 11 | /// 12 | 13 | /// - SETTINGS & TOOLS (MUST BE AT THE TOP) 14 | /// Common settings and tools. 15 | // 16 | @import './settings/colors'; 17 | @import './settings/fonts'; 18 | @import './settings/breakpoints'; 19 | 20 | @import './tools/functions'; 21 | @import './tools/mixins'; 22 | 23 | /// - GENERIC 24 | /// Reset............A level playing field using @necolas’s Normalize. 25 | /// Print................Reset-like styles for print media. 26 | /// 27 | @import './generic/reset'; 28 | @import './generic/print'; 29 | 30 | /// - COMPONENTS 31 | // Build and include your project’s UI components. 32 | // Uncomment and add to this as necessary. 33 | /// 34 | /// Button..............Specific styles for btn component and its variations. 35 | /// Typeface............Specific styles for heading component and its size variations. 36 | /// Field...............Specific styles for field and input component. 37 | /// 38 | @import './components/button'; 39 | @import './components/typeface'; 40 | @import './components/field'; 41 | // @import './components/price'; 42 | 43 | /// - SECTIONS 44 | /// 45 | /// Main giftcard..............Shopify only giftcard main static section. 46 | /// 47 | @import './sections/main-giftcard'; 48 | -------------------------------------------------------------------------------- /src/styles/components/_field.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## COMPONENT: FIELD 3 | // ========================================================================== 4 | 5 | /// @content Component specific classes for buttons. 6 | /// This file contains suite of classes like. 7 | // 8 | /// .field {} - Base field class. 9 | // 10 | 11 | .field { 12 | position: relative; 13 | display: flex; 14 | align-items: stretch; 15 | justify-content: center; 16 | width: 100%; 17 | max-width: 22em; 18 | margin: 0 auto; 19 | border: 1px solid $color-base-outline-button; 20 | border-radius: rem(3px); 21 | 22 | &_label { 23 | position: absolute; 24 | left: 0; 25 | top: 50%; 26 | left: 1rem; 27 | transform-origin: center left; 28 | transform: translateY(-50%); 29 | transition: transform 200ms ease; 30 | pointer-events: none; 31 | cursor: text; 32 | } 33 | 34 | &_input { 35 | padding: 0.8rem 1rem 0.2rem; 36 | flex: 1; 37 | } 38 | 39 | &_label, 40 | &_input { 41 | font-family: $font-body-family; 42 | font-style: $font-heading-style; 43 | font-weight: $font-heading-weight; 44 | text-decoration: none; 45 | } 46 | 47 | .field_input::placeholder { 48 | color: transparent; 49 | } 50 | 51 | &_input:active + &_label, 52 | &_input:focus + &_label, 53 | &_input:focus-visible + &_label, 54 | &_input:not(:placeholder-shown) + &_label, 55 | &_input:-webkit-autofill + &_label { 56 | transform: translateY(-100%) scale(0.6); 57 | } 58 | 59 | // State variations 60 | &.-error { 61 | border-color: rgba(240, 0, 0, 0.9); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/styles/components/_button.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## COMPONENT: BUTTON 3 | // ========================================================================== 4 | 5 | /// @content Component specific classes for buttons. 6 | /// This file contains suite of classes like. 7 | /// 8 | /// .button {} - Base button. 9 | /// .button.-secondary {} - Secondary button. 10 | /// .button.-large {} - Large size button. 11 | /// ...add others if you want. 12 | /// 13 | 14 | 15 | button, 16 | .button { 17 | cursor: pointer; 18 | display: inline-flex; 19 | justify-content: center; 20 | align-items: center; 21 | margin: 0; 22 | text-align: center; 23 | text-decoration: none; 24 | border: 0; 25 | border-radius: rem(3px); 26 | padding: rem(12px) rem(18px); 27 | font-family: $font-heading-family; 28 | font-style: $font-heading-style; 29 | font-weight: $font-heading-weight; 30 | font-size: rem(20px); 31 | user-select: none; 32 | appearance: none; 33 | transition: transform 200ms ease-in; 34 | 35 | &:hover, 36 | &.-primary:hover { 37 | text-decoration: none; 38 | } 39 | 40 | /// Color variants 41 | &, 42 | &.-primary { 43 | background-color: $color-base-solid-button; 44 | color: $color-base-background-primary; 45 | } 46 | 47 | &.-secondary { 48 | background-color: transparent; 49 | color: $color-base-outline-button; 50 | border: 1px solid $color-base-outline-button; 51 | } 52 | 53 | /// Size variants 54 | &.-small { 55 | min-width: 6rem; 56 | } 57 | 58 | &.-large { 59 | min-width: 20rem; 60 | } 61 | 62 | /// State variation 63 | &.-loading { 64 | cursor: not-allowed; 65 | opacity: 0.8; 66 | } 67 | 68 | &:disabled, 69 | &[aria-disabled='true'] { 70 | cursor: not-allowed; 71 | background-color: gray; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /.github/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | > 29 December 2022 v2.0.0 6 | 7 | - ✨ Removed all unnecessary configuation files that depend on users like editorconfig etc.. 8 | - ✨ Added a Helium CLI based on Esbuild for fast build times. 9 | - 🔥 Changed some utility classes. 10 | - ⏫ Removed some dependecies amd some deprecated Shopify filters. 11 | - 🐛 Fixed issues and refactored code. 12 | 13 | 14 | > 28 October 2021 v1.2.2 15 | 16 | - ✨ Added grid object for easy responsive grid layouts. 17 | - 🔥 Added hidden responsive utility classes. 18 | - ⏫ Upgraded some dependecies. 19 | - 🐛 Fixed issues and refactored code. 20 | - 🧰 Added media query mixins. 21 | 22 | > 20 October 2021 v1.2.1 23 | 24 | - ✨ Added social list component. 25 | - 🐛 Fixed some issues with password layout. 26 | - ♻️ Changed BEM to minimal BEM instead of ```block__element--modifier``` now it's ```block_element -modifier```. 27 | - Added a form to password page. 28 | - 🐛 Fixed issue #42: manifest.json Error 29 | - Added field styles component. 30 | - ⏫ Upgraded some dependecies. 31 | 32 | 33 | > 13 October 2021 v1.2.0 34 | 35 | - ✨ Improved the structure. 36 | - Added manifest.json for PWA support. 37 | - ♻️ Changed the code structure for more scalable projects. 38 | - 🐛 Issue #37: Fixed copy files to assets directory. 39 | - ⬆️ Upgrade dependencies, tools. 40 | - 🌈 Improved giftcard layout and template. 41 | - 🌍 Added translations for settings and configs. 42 | - 😎 Dark mode on the welcome page. 43 | 44 | > 20 September 2021 v1.1.1 45 | 46 | - 📝 Improved the docs. 47 | - ✨ Added Husky for Git hooks. 48 | - ♻️ Changed the code structure based on sections and components concept. 49 | - 🐛 Fixed some Webpack issues. 50 | - ⬆️ Upgrade dependencies, tools. 51 | - Removed Typescript option. 52 | - ⚡️ Published the docs website https://workflow.younessidbakkasse.com 53 | -------------------------------------------------------------------------------- /sections/header-password.liquid: -------------------------------------------------------------------------------- 1 | {{ 'component-dark-mode-button.css' | asset_url | stylesheet_tag }} 2 | 3 | 4 |
5 |

Workflow.

6 | 7 | 11 | 12 | 13 | {%- form 'storefront_password', class: 'header-password_form' -%} 14 |
15 |

Enter using password

16 |
17 | 28 | 29 | 30 | {%- if form.errors -%} 31 |
Error
32 | {%- endif -%} 33 |
34 | 35 | 38 | Are you the store owner? Log in here 39 |
40 | {%- endform -%} 41 |
42 | 43 | {% schema %} 44 | { 45 | "name": "t:sections.header_password.name", 46 | "tag": "section", 47 | "settings": [ 48 | 49 | ] 50 | } 51 | {% endschema %} 52 | -------------------------------------------------------------------------------- /layout/password.liquid: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {%- unless settings.fonts_header.system? and settings.fonts_body.system? -%} 10 | 11 | {%- endunless -%} 12 | 13 | 14 | {%- unless settings.fonts_header.system? and settings.fonts_body.system? -%} 15 | 16 | {%- endunless -%} 17 | 18 | 19 | 20 | 21 | {%- liquid 22 | render 'head-seo' 23 | render 'head-metas' 24 | render 'head-settings' 25 | -%} 26 | 27 | {{ 'password.css' | asset_url | stylesheet_tag }} 28 | 29 | 30 | 31 | {{ content_for_header }} 32 | {% render 'weglot_hreftags' %} 33 | {% render 'weglot_switcher' %} 34 | 35 | 36 | {% comment %} Accessibilty {% endcomment %} 37 |
38 | 39 | {{- "accessibility.skip_to_content" | t -}} 40 | 41 | 42 |
43 | 44 | {%- section 'header-password' -%} 45 | 46 |
47 | {{ content_for_layout }} 48 |
49 | 50 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/styles/password.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## LAYOUT: PASSWORD 3 | // ========================================================================== 4 | 5 | /// @content 6 | /// DO NOT ADD CLASSES OR RULES IN THIS FILE DIRECTLY. 7 | /// Instead, use imports to add extensions or snippets you made along the project. 8 | /// 9 | /// 10 | /// Production build weights only ~11kb (~2.1kb gzipped) 11 | /// 12 | 13 | /// - SETTINGS & TOOLS (MUST BE AT THE TOP) 14 | /// Common settings and tools. 15 | // 16 | @import './settings/colors'; 17 | @import './settings/fonts'; 18 | @import './settings/breakpoints'; 19 | 20 | @import './tools/functions'; 21 | @import './tools/mixins'; 22 | 23 | /// - GENERIC 24 | /// Reset............A level playing field using @necolas’s Normalize. 25 | /// Print................Reset-like styles for print media. 26 | /// Elements.............Sensibly and tersely share some global commonalities. 27 | /// 28 | @import './generic/reset'; 29 | @import './generic/print'; 30 | @import './generic/elements'; 31 | 32 | /// - COMPONENTS 33 | // Build and include your project’s UI components. 34 | // Uncomment and add to this as necessary. 35 | /// 36 | /// Button..............Specific styles for btn component and its variations. 37 | /// Typeface............Specific styles for heading component and its size variations. 38 | /// Field...............Specific styles for field and input component. 39 | /// 40 | @import './components/button'; 41 | @import './components/typeface'; 42 | @import './components/field'; 43 | 44 | /// - SECTIONS 45 | /// 46 | /// Header password..............Shopify header password static section. 47 | /// Main password..............Shopify main password static section. 48 | /// 49 | @import './sections/header-password'; 50 | @import './sections/main-password'; 51 | 52 | /// - OBJECTS 53 | // Be aware that enabling offsets produces a large chunk of classes which might 54 | // bloat your CSS, depending on the amount of breakpoints you defined. 55 | // Only set this to `true` if you are absolutely sure about what you are doing. 56 | /// 57 | /// Container............Helper classes for aligning elements inside containers. 58 | /// 59 | @import './objects/container'; 60 | 61 | /// - UTILITIES 62 | /// Display..............Helper utility classes to hide/show content. 63 | /// 64 | @import './utilities/display'; 65 | -------------------------------------------------------------------------------- /layout/giftcard.liquid: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {%- unless settings.fonts_header.system? and settings.fonts_body.system? -%} 11 | 12 | {%- endunless -%} 13 | 14 | 15 | {%- unless settings.fonts_header.system? and settings.fonts_body.system? -%} 16 | 17 | {%- endunless -%} 18 | 19 | 20 | 21 | {{- 'gift_cards.issued.title' -}} 22 | 23 | 24 | {%- if canonical_url != blank -%} 25 | 26 | {%- endif -%} 27 | 28 | {%- liquid 29 | render 'head-metas' 30 | render 'head-settings' 31 | -%} 32 | 33 | {{ 'giftcard.css' | asset_url | stylesheet_tag }} 34 | 35 | 36 | {{ content_for_header }} 37 | {% render 'weglot_hreftags' %} 38 | {% render 'weglot_switcher' %} 39 | 40 | 41 | {% comment %} Accessibilty {% endcomment %} 42 |
43 | 44 | {{- "accessibility.skip_to_content" | t -}} 45 | 46 | 47 |
48 | 49 |
50 | {{ content_for_layout }} 51 |
52 | 53 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /snippets/head-metas.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Renders all social sharing and theme color meta tags. 3 | 4 | Usage: 5 | {%- render 'head-metas' -%} 6 | {% endcomment %} 7 | 8 | {% comment %} Social sharing {% endcomment %} 9 | {%- liquid 10 | assign og_title = page_title | default: shop.name 11 | assign og_url = canonical_url | default: shop.url 12 | assign og_type = 'website' 13 | assign og_description = page_description | default: shop.description | default: shop.name 14 | 15 | if request.page_type == 'product' 16 | assign og_type = 'product' 17 | elsif request.page_type == 'article' 18 | assign og_type = 'article' 19 | elsif request.page_type == 'collection' 20 | assign og_type = 'product.group' 21 | elsif request.page_type == 'password' 22 | assign og_url = shop.url 23 | endif 24 | %} 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {%- if page_image -%} 33 | 34 | 35 | 36 | 37 | {%- endif -%} 38 | 39 | {%- if request.page_type == 'product' -%} 40 | 41 | 42 | {%- endif -%} 43 | 44 | {%- if settings.social_twitter_link != blank -%} 45 | 46 | {%- endif -%} 47 | 48 | 49 | 50 | 51 | {% comment %} Theme color {% endcomment %} 52 | {%- if settings.primary_color -%} 53 | 54 | 55 | {%- endif -%} 56 | 57 | {% comment %} {% endcomment %} 58 | 59 | -------------------------------------------------------------------------------- /layout/theme.liquid: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {%- unless settings.fonts_header.system? and settings.fonts_body.system? -%} 10 | 11 | {%- endunless -%} 12 | 13 | {%- unless settings.fonts_header.system? -%} 14 | 15 | {%- endunless -%} 16 | 17 | {%- unless settings.fonts_body.system? -%} 18 | 19 | {%- endunless -%} 20 | 21 | 22 | 23 | 24 | {%- liquid 25 | render 'head-seo' 26 | render 'head-metas' 27 | render 'head-settings' 28 | -%} 29 | 30 | {{ 'base.css' | asset_url | stylesheet_tag }} 31 | 32 | 33 | 34 | {{ content_for_header }} 35 | {% render 'weglot_hreftags' %} 36 | {% render 'weglot_switcher' %} 37 | 38 | 39 | {%- capture template_name -%} 40 | {{- template.name -}}{%- if template.suffix -%}-{{- template.suffix -}}{%- endif -%} 41 | {%- endcapture -%} 42 | 43 | 44 | 45 |
46 | 47 | {{- "accessibility.skip_to_content" | t -}} 48 | 49 | 50 |
51 | 52 | {%- section 'header' -%} 53 | 54 |
55 | {{ content_for_layout }} 56 |
57 | 58 | {%- section 'footer' -%} 59 | 60 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /templates/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "sections": { 3 | "main": { 4 | "type": "welcome", 5 | "blocks": { 6 | "card1": { 7 | "type": "card", 8 | "settings": { 9 | "heading": "Supports Shopify CLI", 10 | "description": "Built on top of the latest Shopify developer tooling ecosystem. To quickly scaffold, test, and share Shopify themes." 11 | } 12 | }, 13 | "card2": { 14 | "type": "card", 15 | "settings": { 16 | "heading": "Fast by default ⚡️", 17 | "description": "Get 100 scores on Google Lighthouse by default. Workflow has built in code splitting, prefetches links, and lazy loads files with zero dependencies." 18 | } 19 | }, 20 | "card3": { 21 | "type": "card", 22 | "settings": { 23 | "heading": "SEO-ready 🎯", 24 | "description": "Use sensible defaults for structured data, open graph, and Twitter cards. Or easily change the SEO settings to your liking." 25 | } 26 | }, 27 | "card4": { 28 | "type": "card", 29 | "settings": { 30 | "heading": "Modern ES6 and SCSS based 🌈", 31 | "description": "Hot Module Reloading on sass/ES6 file changes for rapid development, Extensible, scalable OOCSS and BEM architecture." 32 | } 33 | }, 34 | "card5": { 35 | "type": "card", 36 | "settings": { 37 | "heading": "Shopify Github integration", 38 | "description": "Connect your Github repository with Shopify, no extra branches needed, 100% compatible out of the box!" 39 | } 40 | }, 41 | "card6": { 42 | "type": "card", 43 | "settings": { 44 | "heading": "Shopify CI & Theme linting ♻️", 45 | "description": "Ensure your theme is performant and tested with Theme check at every push to prevent bad code in your theme." 46 | } 47 | } 48 | }, 49 | "block_order": [ 50 | "card1", 51 | "card2", 52 | "card3", 53 | "card4", 54 | "card5", 55 | "card6" 56 | ], 57 | "settings": { 58 | "heading": "Modern Shopify
development Workflow.", 59 | "subheading": "A Shopify theme environment from scratch ⚙️, with Online Store 2.0 features. Built with performance ⚡️ and best practices in mind..", 60 | "link_label": "Get started" 61 | } 62 | } 63 | }, 64 | "order": [ 65 | "main" 66 | ] 67 | } 68 | -------------------------------------------------------------------------------- /sections/welcome.liquid: -------------------------------------------------------------------------------- 1 | {{ 'section-welcome.css' | asset_url | stylesheet_tag }} 2 | 3 |
4 |
5 |

{{ section.settings.heading }}

6 |

{{ section.settings.subheading }}

7 | {{ section.settings.link_label }} 10 | {%- render 'component-icon' 11 | icon: 'arrow', 12 | icon_size: 20 13 | -%} 14 |

15 | Open-source MIT Licensed. GitHub v1.2.2 16 |

17 |
18 | 19 |
20 | {% for block in section.blocks %} 21 | {%- if block.settings.heading != blank and block.settings.description != blank -%} 22 |
23 |

{{ block.settings.heading }}

24 |

{{ block.settings.description }}

25 |
26 | {% endif %} 27 | {% endfor %} 28 |
29 |
30 | 31 | 32 | {% schema %} 33 | { 34 | "name": "t:sections.welcome.name", 35 | "tag": "section", 36 | "max_blocks": 6, 37 | "settings": [ 38 | { 39 | "type": "textarea", 40 | "id": "heading", 41 | "label": "t:sections.welcome.settings.heading.label" 42 | }, 43 | { 44 | "type": "textarea", 45 | "id": "subheading", 46 | "label": "t:sections.welcome.settings.subheading.label" 47 | }, 48 | { 49 | "type": "text", 50 | "id": "link_label", 51 | "label": "t:sections.welcome.settings.link_label.label" 52 | } 53 | ], 54 | "blocks": [ 55 | { 56 | "name": "t:sections.welcome.blocks.card.name", 57 | "type": "card", 58 | "settings": [ 59 | { 60 | "type": "text", 61 | "id": "heading", 62 | "label": "t:sections.welcome.blocks.card.settings.heading.label" 63 | }, 64 | { 65 | "type": "textarea", 66 | "id": "description", 67 | "label": "t:sections.welcome.blocks.card.settings.description.label" 68 | } 69 | ] 70 | } 71 | ], 72 | "presets": [ 73 | { 74 | "name": "t:sections.welcome.presets.name" 75 | } 76 | ] 77 | } 78 | {% endschema %} 79 | -------------------------------------------------------------------------------- /src/styles/base.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## LAYOUT: BASE 3 | // ========================================================================== 4 | 5 | /// @content 6 | /// DO NOT ADD CLASSES OR RULES IN THIS FILE DIRECTLY. 7 | /// Instead, use imports to add extensions or snippets you made along the project. 8 | /// 9 | /// 10 | /// Production build weights only ~25kb (~4kb gzipped) 11 | /// 12 | 13 | /// - SETTINGS & TOOLS (MUST BE AT THE TOP) 14 | /// Common settings and tools. 15 | // 16 | @import './settings/colors'; 17 | @import './settings/fonts'; 18 | @import './settings/breakpoints'; 19 | 20 | @import './tools/functions'; 21 | @import './tools/mixins'; 22 | 23 | /// - GENERIC 24 | /// Reset............A level playing field using @necolas’s Normalize. 25 | /// Print................Reset-like styles for print media. 26 | /// Elements.............Sensibly and tersely share some global commonalities. 27 | /// 28 | @import './generic/reset'; 29 | @import './generic/print'; 30 | @import './generic/elements'; 31 | 32 | /// - COMPONENTS 33 | // Build and include your project’s UI components. 34 | // Uncomment and add to this as necessary. 35 | /// 36 | /// Button..............Specific styles for btn component and its variations. 37 | /// Typeface............Specific styles for heading component and its size variations. 38 | /// Field...............Specific styles for field and input component. 39 | /// 40 | @import './components/button'; 41 | @import './components/typeface'; 42 | @import './components/field'; 43 | // @import './components/price'; 44 | 45 | /// - SECTIONS 46 | /// 47 | /// Header..............Shopify section. 48 | /// Footer..............Shopify section. 49 | /// Weclome..............Shopify dynamic section. 50 | /// 51 | @import './sections/header'; 52 | @import './sections/footer'; 53 | @import './sections/welcome'; 54 | 55 | /// - OBJECTS 56 | // Be aware that enabling offsets produces a large chunk of classes which might 57 | // bloat your CSS, depending on the amount of breakpoints you defined. 58 | // Only set this to `true` if you are absolutely sure about what you are doing. 59 | /// 60 | /// Container............Helper classes for aligning elements inside containers. 61 | /// 62 | @import './objects/container'; 63 | @import './objects/grid'; 64 | 65 | /// - UTILITIES 66 | /// Space................Nudge bits of the DOM around with these spacing classes. 67 | /// Display..............Helper utility classes to hide/show content. 68 | /// Align................Helper classes for aligning elements inside containers. 69 | /// 70 | @import './utilities/space'; 71 | @import './utilities/display'; 72 | @import './utilities/align'; 73 | -------------------------------------------------------------------------------- /src/styles/generic/_elements.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## GENERIC: ELEMENTS 3 | // ========================================================================== 4 | 5 | // Some common declarations for certain elements. 6 | /// 7 | 8 | ul, 9 | ol { 10 | margin: 0; 11 | padding: 0; 12 | list-style: none; 13 | } 14 | 15 | summary { 16 | cursor: pointer; 17 | list-style: none; 18 | position: relative; 19 | } 20 | 21 | details > * { 22 | box-sizing: border-box; 23 | } 24 | 25 | a { 26 | text-decoration: none; 27 | color: inherit; 28 | 29 | &:hover { 30 | text-decoration: underline; 31 | } 32 | } 33 | 34 | // Hide empty elements 35 | a:empty, 36 | ul:empty, 37 | dl:empty, 38 | div:empty, 39 | section:empty, 40 | article:empty, 41 | p:empty, 42 | h1:empty, 43 | h2:empty, 44 | h3:empty, 45 | h4:empty, 46 | h5:empty, 47 | h6:empty { 48 | display: none !important; 49 | } 50 | 51 | p, 52 | figure { 53 | margin: 0; 54 | padding: 0; 55 | } 56 | 57 | // 1. Single taps should be dispatched immediately on clickable elements 58 | /// 59 | a, 60 | area, 61 | button, 62 | input, 63 | label, 64 | select, 65 | textarea, 66 | [tabindex] { 67 | -ms-touch-action: manipulation; // [1] 68 | touch-action: manipulation; 69 | } 70 | 71 | [hreflang] > abbr[title] { 72 | text-decoration: none; 73 | } 74 | 75 | table { 76 | border-spacing: 0; 77 | border-collapse: collapse; 78 | } 79 | 80 | button { 81 | cursor: pointer; 82 | } 83 | 84 | .a11y { 85 | position: absolute; 86 | display: flex; 87 | justify-content: space-between; 88 | align-items: center; 89 | z-index: 999; 90 | transform: translateY(-150%); 91 | transition: none; 92 | 93 | &:focus-within { 94 | transform: translateY(0%); 95 | } 96 | } 97 | 98 | // 1. Fluid images for responsive purposes. 99 | // 2. Offset `alt` text from surrounding copy. 100 | // 3. Setting `vertical-align` removes the whitespace that appears under `img` 101 | // elements when they are dropped into a page as-is. Safer alternative to 102 | // using `display: block;`. 103 | /// 104 | img { 105 | max-width: 100%; // [1] 106 | font-style: italic; // [2] 107 | vertical-align: middle; // [3] 108 | } 109 | 110 | // 4. Setting `vertical-align` removes the whitespace that appears under `img` 111 | // elements when they are dropped into a page as-is. 112 | // 113 | audio, 114 | canvas, 115 | iframe, 116 | img, 117 | svg, 118 | video { 119 | vertical-align: middle; // [4] 120 | } 121 | 122 | // 5. SVG elements should fallback to their surrounding text color. 123 | // 124 | svg { 125 | fill: currentColor; // [5] 126 | } 127 | -------------------------------------------------------------------------------- /templates/gift_card.liquid: -------------------------------------------------------------------------------- 1 | {%- layout 'giftcard' -%} 2 | 3 |
4 |
5 | Giftcard image 6 |
7 |
8 |
9 | 16 |
17 | 18 | 19 | 22 |
23 | {%- if gift_card.pass_url -%} 24 | 25 | {{ 'templates.gift_card.add_to_apple_wallet' | t }} 26 | 27 | {%- endif -%} 28 |
29 | 36 | {{ 'templates.gift_card.shop_link' | t }} 37 | 38 | 44 |
45 |
46 |
47 | 48 | 73 | -------------------------------------------------------------------------------- /src/styles/tools/_functions.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## TOOLS: FUNCTIONS 3 | // ========================================================================== 4 | 5 | @use 'sass:math'; 6 | 7 | /// @content Function that converts the given pixel value to its EM quivalent. 8 | /// 9 | /// @param {Number} $size 10 | /// The pixel value to convert. 11 | /// 12 | /// @return {Number} 13 | /// Scalable pixel value in EMs. 14 | /// 15 | /// @access public 16 | /// 17 | @function em($size) { 18 | @if (type-of($size) == number) { 19 | @if (unit($size) != 'px') { 20 | @error "`#{$size}` needs to be a pixel value."; 21 | } 22 | } @else { 23 | @error "`#{$size}` needs to be a number."; 24 | } 25 | 26 | @return math.div($size, $font-base-size) * 1em; 27 | } 28 | 29 | /// @content Function that converts the given pixel value to its REM quivalent. 30 | /// 31 | /// @param {Number} $size 32 | /// The pixel value to convert. 33 | /// 34 | /// @return {Number} 35 | /// Scalable pixel value in REMs. 36 | /// 37 | /// @access public 38 | /// 39 | @function rem($size) { 40 | @if (type-of($size) == number) { 41 | @if (unit($size) != 'px') { 42 | @error "`#{$size}` needs to be a pixel value."; 43 | } 44 | } @else { 45 | @error "`#{$size}` needs to be a number."; 46 | } 47 | 48 | @return math.div($size, $font-base-size) * 1rem; 49 | } 50 | 51 | // Breakpoint viewport sizes and media queries. 52 | // 53 | // Breakpoints are defined as a map of (name: minimum width), order from small to large: 54 | // (xs: 576px, sm: 768px, md: 992px) 55 | // The map defined in the `$breakpoints` global variable is used as the `$breakpoints` argument by default. 56 | // Name of the next breakpoint, or null for the last breakpoint. 57 | // >> breakpoint-next(sm) -> md 58 | // >> breakpoint-next(sm, $breakpoints: (xs: 576px, sm: 768px, md: 992px)) -> md 59 | // >> breakpoint-next(sm, $breakpoint-names: (xs sm md)) -> md 60 | @function breakpoint-next( 61 | $name, 62 | $breakpoints: $breakpoints, 63 | $breakpoint-names: map-keys($breakpoints) 64 | ) { 65 | $n: index($breakpoint-names, $name); 66 | @return if( 67 | $n < length($breakpoint-names), 68 | nth($breakpoint-names, $n + 1), 69 | null 70 | ); 71 | } 72 | 73 | // Minimum breakpoint width. Null for the smallest (first) breakpoint. 74 | // >> breakpoint-min(sm, (xs: 576px, sm: 768px, md: 992px)) -> 768px 75 | @function breakpoint-min($name, $breakpoints: $breakpoints) { 76 | $min: map-get($breakpoints, $name); 77 | @return if($min !=0, $min, null); 78 | } 79 | 80 | // Maximum breakpoint width. Null for the largest (last) breakpoint. 81 | // The maximum value is calculated as the minimum of the next one less 0.1. 82 | // >> breakpoint-max(sm, (xs: 576px, sm: 768px, md: 992px)) -> 991px 83 | @function breakpoint-max($name, $breakpoints: $breakpoints) { 84 | $next: breakpoint-next($name, $breakpoints); 85 | @return if($next, breakpoint-min($next, $breakpoints) - 1, null); 86 | } 87 | -------------------------------------------------------------------------------- /src/styles/utilities/_display.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## UTILITIES: DISPLAY 3 | // ========================================================================== 4 | 5 | /// @content Utility classes to hide/show elements. 6 | /// 7 | /// .u-hidden-visually {} - hide and visible for a11y. 8 | /// .u-hide {} - always hidden. 9 | /// .u-visible {} - always visible. 10 | /// and others... 11 | /// 12 | 13 | // Always hide an element. 14 | .u-hide { 15 | display: none !important; 16 | } 17 | 18 | /// Reponsive hiding utility classes. 19 | /// @todo 20 | /// Reponsive hiding utility classes. 21 | @mixin responsive-hide-helpers() { 22 | // We need to handle xxs and xlg breakpoints differently 23 | $hide-breakpoints: map-remove($breakpoints, xxs, xlg); 24 | 25 | .u-hide-xxs { 26 | @include mq-only('xxs') { 27 | display: none !important; 28 | } 29 | } 30 | 31 | @each $bp in map-keys($hide-breakpoints) { 32 | .u-hide-#{$bp}-up { 33 | @include mq-up($bp) { 34 | display: none !important; 35 | } 36 | } 37 | 38 | .u-hide-#{$bp}-down { 39 | @include mq-down($bp) { 40 | display: none !important; 41 | } 42 | } 43 | } 44 | 45 | .u-hide-xlg { 46 | @include mq-only('xlg') { 47 | display: none !important; 48 | } 49 | } 50 | } 51 | 52 | @include responsive-hide-helpers(); 53 | 54 | // Hide only visually, but have it available for screen readers. 55 | .u-hide-visually { 56 | position: absolute !important; 57 | border: 0; 58 | clip: rect(0 0 0 0); 59 | height: 1px; 60 | margin: -1px; 61 | overflow: hidden; 62 | padding: 0 !important; 63 | width: 1px; 64 | word-wrap: normal !important; 65 | } 66 | 67 | // Allows an accessibly hidden element to be focusable via keyboard navigation. 68 | .u-hide-visually-focusable { 69 | position: absolute !important; 70 | word-wrap: normal !important; 71 | border: 0; 72 | clip: rect(0 0 0 0); 73 | height: 1px; 74 | margin: -1px; 75 | overflow: hidden; 76 | padding: 0 !important; 77 | width: 1px; 78 | 79 | @include actus { 80 | clip: auto; 81 | width: auto; 82 | height: auto; 83 | } 84 | } 85 | 86 | // Reduce motion for accessibility 87 | @media (prefers-reduced-motion) { 88 | .u-motion-reduce { 89 | transition: none !important; 90 | } 91 | } 92 | 93 | // Always show an element. 94 | .u-show, 95 | .u-hide-none { 96 | display: block !important; 97 | visibility: visible !important; 98 | } 99 | 100 | /// @throw Dangerous for a11y - Use with care 101 | .u-focus-none { 102 | box-shadow: none !important; 103 | outline: 0 !important; 104 | } 105 | 106 | // Control visibility without affecting flow. 107 | .u-visible { 108 | visibility: visible !important; 109 | opacity: 1 !important; 110 | } 111 | 112 | .u-invisible { 113 | visibility: hidden !important; 114 | opacity: 0 !important; 115 | } 116 | -------------------------------------------------------------------------------- /snippets/component-social-list.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Renders a social list. 3 | Usage: 4 | {%- render 'component-social-list' -%} 5 | {% endcomment %} 6 | 7 | 81 | -------------------------------------------------------------------------------- /src/styles/tools/_mixins.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## TOOLS: MIXINS 3 | // ========================================================================== 4 | 5 | /// @content Generate `:hover` and `:focus` styles in one go. 6 | /// 7 | /// @example scss - basic usage 8 | /// .foo { 9 | /// @include hocus { 10 | /// color: black; 11 | /// } 12 | /// } 13 | /// 14 | /// @output Wraps the given content in `:focus` and `:hover` pseudo-classes. 15 | /// .foo:focus, 16 | /// .foo:hover { 17 | /// color: black; 18 | /// } 19 | /// 20 | /// @type Mixin 21 | /// @access public 22 | /// 23 | @mixin hocus { 24 | &:focus, 25 | &:hover { 26 | @content; 27 | } 28 | } 29 | 30 | /// @content Generate `:active` and `:focus` styles in one go. 31 | /// 32 | /// @example scss - basic usage 33 | /// .foo { 34 | /// @include actus { 35 | /// color: white; 36 | /// } 37 | /// } 38 | /// 39 | /// @output Wraps the given content in `:active` and `:focus` pseudo-classes. 40 | /// .foo:focus, 41 | /// .foo:active { 42 | /// color: white; 43 | /// } 44 | /// 45 | /// @type Mixin 46 | /// @access public 47 | /// 48 | @mixin actus { 49 | &:focus, 50 | &:active { 51 | @content; 52 | } 53 | } 54 | 55 | /// @content Prevent text from wrapping into multiple lines for the current element. 56 | /// 57 | /// 1. Ensure that the node has a maximum width after which truncation can occur. 58 | /// 2. Fix for IE 8/9 if `word-wrap: break-word` is in effect on ancestor nodes. 59 | /// 60 | /// @param {Number} $width 61 | /// The maximum width of element, it's '100%' by default. 62 | /// 63 | /// @example scss - basic usage 64 | /// .foo { 65 | /// @include truncate(); 66 | /// } 67 | /// 68 | /// @type Mixin 69 | /// @access public 70 | /// 71 | @mixin truncate($width: 100%) { 72 | overflow: hidden; 73 | text-overflow: ellipsis; 74 | white-space: nowrap; 75 | word-wrap: normal; // [2] 76 | @if $width { 77 | max-width: $width; // [1] 78 | } 79 | } 80 | 81 | /// @content A generator that makes working with media queries effortless and fun. 82 | /// 83 | /// 84 | /// @param {String} $alias 85 | /// The alias for the breakpoint example: xs, s, from-md... 86 | /// 87 | /// @example scss - basic usage 88 | /// .foo { 89 | /// @include mq('from-xs') { 90 | /// color: black; 91 | /// } 92 | /// } 93 | /// 94 | /// @type Mixin 95 | /// @access public 96 | /// 97 | @mixin mq($alias) { 98 | // Search breakpoint map for alias 99 | $query: map-get($theme-breakpoints-queries, $alias); 100 | // If alias exists, print out media query 101 | @if $query { 102 | @media #{$query} { 103 | @content; 104 | } 105 | } @else { 106 | @error "No breakpoint found for #{$alias}"; 107 | } 108 | } 109 | 110 | /// @content A mixin that makes elements fluid in there containers. 111 | /// 112 | /// @param none 113 | /// 114 | /// @example scss - basic usage 115 | /// .foo { 116 | /// @include fluid; 117 | /// } 118 | /// 119 | /// @type Mixin 120 | /// @access public 121 | /// 122 | @mixin fluid() { 123 | width: 100%; 124 | padding-left: 0; 125 | padding-right: 0; 126 | } 127 | 128 | // Media query mixins 129 | 130 | // Media of at least the minimum breakpoint width. No query for the smallest breakpoint. 131 | // Makes the @content apply to the given breakpoint and wider. 132 | @mixin mq-up($name, $breakpoints: $breakpoints) { 133 | $min: breakpoint-min($name, $breakpoints); 134 | 135 | @if $min { 136 | @media screen and (min-width: $min) { 137 | @content; 138 | } 139 | } @else { 140 | @content; 141 | } 142 | } 143 | 144 | // Media of at most the maximum breakpoint width. No query for the largest breakpoint. 145 | // Makes the @content apply to the given breakpoint and narrower. 146 | @mixin mq-down($name, $breakpoints: $breakpoints) { 147 | $max: breakpoint-max($name, $breakpoints); 148 | 149 | @if $max { 150 | @media screen and (max-width: $max) { 151 | @content; 152 | } 153 | } @else { 154 | @content; 155 | } 156 | } 157 | 158 | // Media between the breakpoint's minimum and maximum widths. 159 | // No minimum for the smallest breakpoint, and no maximum for the largest one. 160 | // Makes the @content apply only to the given breakpoint, not viewports any wider or narrower. 161 | @mixin mq-only($name, $breakpoints: $breakpoints) { 162 | @include mq-up($name, $breakpoints) { 163 | @include mq-down($name, $breakpoints) { 164 | @content; 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /snippets/head-seo.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Renders all related SEO and favicon tags in the head. 3 | 4 | Usage: 5 | {%- render 'head-seo' -%} 6 | {% endcomment %} 7 | 8 | 9 | 10 | 11 | {{ page_title }} 12 | {%- if current_tags %} – tagged "{{ current_tags | join: ', ' }}"{% endif -%} 13 | {%- if current_page != 1 %} – Page {{ current_page }}{% endif -%} 14 | {%- unless page_title contains shop.name %} – {{ shop.name }}{% endunless -%} 15 | 16 | 17 | {%- if page_description -%} 18 | 19 | {% endif -%} 20 | 21 | 22 | {% comment %} Strcutured data {% endcomment %} 23 | 45 | 46 | {%- if request.page_type == 'index' -%} 47 | {% assign potential_action_target = shop.url | append: routes.search_url | append: "?q={search_term_string}" %} 48 | 61 | {%- endif -%} 62 | 63 | {%- if request.page_type == 'article' -%} 64 | 102 | {%- endif -%} 103 | 104 | {% comment %} Favicons {% endcomment %} 105 | {%- if settings.favicon != blank -%} 106 | 107 | 108 | 109 | 110 | 111 | 112 | {%- endif -%} 113 | -------------------------------------------------------------------------------- /snippets/head-settings.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Passes global shopify settings to CSS custom properties and 3 | Theme global object. Use good old ES5 in this file! 4 | 5 | Usage: 6 | {%- render 'head-settings' -%} 7 | 8 | Warning: 9 | This file is mounted to the global settings files in 10 | 'src/styles/settings' directory, any modification need 11 | to also be applied to the other file and vice versa. 12 | {% endcomment %} 13 | 14 | {% comment %} Style/Liquid Settings {% endcomment %} 15 | {%- liquid 16 | assign font_header_bold = settings.fonts_header | font_modify: 'weight', 'bold' 17 | assign font_body_bold = settings.fonts_body | font_modify: 'weight', 'bold' 18 | 19 | assign font_header_italic= settings.fonts_header | font_modify: 'style', 'italic' 20 | assign font_body_italic = settings.fonts_body | font_modify: 'style', 'italic' 21 | 22 | assign font_header_bold_italic= font_header_bold | font_modify: 'style', 'italic' 23 | assign font_body_bold_italic = font_body_bold | font_modify: 'style', 'italic' 24 | -%} 25 | 26 | {%- style -%} 27 | {% comment %} Header font face {% endcomment %} 28 | {{ settings.fonts_header | font_face: font_display: 'swap' }} 29 | {{ font_header_bold | font_face: font_display: 'swap' }} 30 | {{ font_header_italic | font_face: font_display: 'swap' }} 31 | {{ font_header_bold_italic | font_face: font_display: 'swap' }} 32 | 33 | {% comment %} Body font face {% endcomment %} 34 | {{ settings.fonts_body | font_face: font_display: 'swap' }} 35 | {{ font_body_bold | font_face: font_display: 'swap' }} 36 | {{ font_body_italic | font_face: font_display: 'swap' }} 37 | {{ font_body_bold_italic | font_face: font_display: 'swap' }} 38 | 39 | {% comment %} Theme custom properties {% endcomment %} 40 | :root { 41 | --font-heading-family: {{ settings.fonts_header.family }}, {{ settings.fonts_header.fallback_families }}; 42 | --font-heading-style: {{ settings.fonts_header.style }}; 43 | --font-heading-weight: {{ settings.fonts_header.weight }}; 44 | 45 | --font-body-family: {{ settings.fonts_body.family }}, {{ settings.fonts_body.fallback_families }}; 46 | --font-body-style: {{ settings.fonts_body.style }}; 47 | --font-body-weight: {{ settings.fonts_body.weight }}; 48 | 49 | --color-base-text: {{ settings.colors_text.red }}, {{ settings.colors_text.green }}, {{ settings.colors_text.blue }}; 50 | --color-base-background-primary: {{ settings.colors_background_primary.red }}, {{ settings.colors_background_primary.green }}, {{ settings.colors_background_primary.blue }}; 51 | --color-base-background-secondary: {{ settings.colors_background_secondary.red }}, {{ settings.colors_background_secondary.green }}, {{ settings.colors_background_secondary.blue }}; 52 | --color-base-solid-button: {{ settings.colors_solid_button.red }}, {{ settings.colors_solid_button.green }}, {{ settings.colors_solid_button.blue }}; 53 | --color-base-outline-button: {{ settings.colors_outline_button.red }}, {{ settings.colors_outline_button.green }}, {{ settings.colors_outline_button.blue }}; 54 | --color-base-accent-primary: {{ settings.colors_accent_primary.red }}, {{ settings.colors_accent_primary.green }}, {{ settings.colors_accent_primary.blue }}; 55 | --color-base-accent-secondary: {{ settings.colors_accent_secondary.red }}, {{ settings.colors_accent_secondary.green }}, {{ settings.colors_accent_secondary.blue }}; 56 | } 57 | 58 | *, 59 | *::before, 60 | *::after { 61 | box-sizing: inherit; 62 | } 63 | 64 | html { 65 | box-sizing: border-box; 66 | font-size: 16px; 67 | line-height: 1.3; 68 | min-height: 100%; 69 | scroll-behavior: smooth; 70 | } 71 | 72 | body { 73 | display: grid; 74 | grid-template-rows: auto 1fr auto; 75 | grid-template-columns: 100%; 76 | min-height: 100%; 77 | margin: 0; 78 | font-size: 1.5rem; 79 | letter-spacing: -0.02rem; 80 | line-height: 1.4; 81 | font-family: var(--font-body-family); 82 | font-style: var(--font-body-style); 83 | font-weight: var(--font-body-weight); 84 | background-color: rgba(var(--color-base-background-primary), 1); 85 | } 86 | 87 | @media screen and (min-width: 750px) { 88 | body { 89 | font-size: 1.6rem; 90 | } 91 | } 92 | {%- endstyle -%} 93 | 94 | {% comment %} JavaScript/Liquid Settings {% endcomment %} 95 | 112 | 113 | -------------------------------------------------------------------------------- /assets/giftcard.css: -------------------------------------------------------------------------------- 1 | html{box-sizing:border-box;-webkit-text-size-adjust:100%;word-break:normal;-moz-tab-size:4;tab-size:4}*,:before,:after{background-repeat:no-repeat;box-sizing:inherit}:before,:after{text-decoration:inherit;vertical-align:inherit}*{padding:0;margin:0}hr{overflow:visible;height:0;color:inherit}details,main{display:block}summary{display:list-item}small{font-size:80%}[hidden]{display:none}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}a{background-color:transparent}a:active,a:hover{outline-width:0}code,kbd,pre,samp{font-family:monospace,monospace}pre{font-size:1em}b,strong{font-weight:bolder}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-color:inherit;text-indent:0}input{border-radius:0}[disabled]{cursor:default}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}textarea{overflow:auto;resize:vertical}button,input,optgroup,select,textarea{font:inherit}optgroup{font-weight:700}button{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit],[role=button]{cursor:pointer;color:inherit}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{outline:1px dotted ButtonText}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button,input,select,textarea{background-color:transparent;border-style:none}a:focus,button:focus,input:focus,select:focus,textarea:focus{outline-width:0}select{-moz-appearance:none;-webkit-appearance:none}select::-ms-expand{display:none}select::-ms-value{color:currentColor}legend{border:0;color:inherit;display:table;white-space:normal;max-width:100%}::-webkit-file-upload-button{-webkit-appearance:button;color:inherit;font:inherit}img{border-style:none}progress{vertical-align:baseline}[aria-busy=true]{cursor:progress}[aria-controls]{cursor:pointer}[aria-disabled=true]{cursor:default}@media print{*,*:before,*:after{background:transparent!important;box-shadow:none!important;color:#000!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}button,.button{cursor:pointer;display:inline-flex;justify-content:center;align-items:center;margin:0;text-align:center;text-decoration:none;border:0;border-radius:.1875rem;padding:.75rem 1.125rem;font-family:var(--font-heading-family);font-style:var(--font-heading-style);font-weight:var(--font-heading-weight);font-size:1.25rem;user-select:none;appearance:none;transition:transform .2s ease-in}button:hover,button.-primary:hover,.button:hover,.button.-primary:hover{text-decoration:none}button,button.-primary,.button,.button.-primary{background-color:rgba(var(--color-base-solid-button),1);color:rgba(var(--color-base-background-primary),1)}button.-secondary,.button.-secondary{background-color:transparent;color:rgba(var(--color-base-outline-button),1);border:1px solid rgba(var(--color-base-outline-button),1)}button.-small,.button.-small{min-width:6rem}button.-large,.button.-large{min-width:20rem}button.-loading,.button.-loading{cursor:not-allowed;opacity:.8}button:disabled,button[aria-disabled=true],.button:disabled,.button[aria-disabled=true]{cursor:not-allowed;background-color:gray}.heading,h1,h2,h3,h4,h5,h6{font-family:var(--font-heading-family);font-style:var(--font-heading-style);font-weight:var(--font-heading-weight);color:inherit;text-decoration:none}.heading h1,.heading.-h1{font-size:3.375rem;line-height:1.2}@media screen and (max-width: 750px){.heading h1,.heading.-h1{font-size:2.375rem}}.heading h2,.heading.-h2{font-size:1.625rem}@media screen and (max-width: 750px){.heading h2,.heading.-h2{font-size:1.375rem}}.heading h3,.heading.-h3{font-size:1.1875rem}.heading h4,.heading.-h4{font-size:1.0625rem}.heading.-bold{font-weight:700}.heading.-upper{text-transform:uppercase}.field{position:relative;display:flex;align-items:stretch;justify-content:center;width:100%;max-width:22em;margin:0 auto;border:1px solid rgba(var(--color-base-outline-button),1);border-radius:.1875rem}.field_label{position:absolute;left:0;top:50%;left:1rem;transform-origin:center left;transform:translateY(-50%);transition:transform .2s ease;pointer-events:none;cursor:text}.field_input{padding:.8rem 1rem .2rem;flex:1}.field_label,.field_input{font-family:var(--font-body-family);font-style:var(--font-heading-style);font-weight:var(--font-heading-weight);text-decoration:none}.field .field_input::placeholder{color:transparent}.field_input:active+.field_label,.field_input:focus+.field_label,.field_input:focus-visible+.field_label,.field_input:not(:placeholder-shown)+.field_label,.field_input:-webkit-autofill+.field_label{transform:translateY(-100%) scale(.6)}.field.-error{border-color:#f00000e6} 2 | -------------------------------------------------------------------------------- /locales/en.default.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings_schema": { 3 | "colors": { 4 | "name": "Colors", 5 | "settings": { 6 | "header_primary_colors": { 7 | "content": "Primary colors" 8 | }, 9 | "header_secondary_colors": { 10 | "content": "Secondary colors" 11 | }, 12 | "colors_text": { 13 | "label": "Text", 14 | "info": "Used as foreground color on background colors." 15 | }, 16 | "colors_solid_button": { 17 | "label": "Solid button", 18 | "info": "Used as foreground color on accent colors." 19 | }, 20 | "colors_outline_button": { 21 | "label": "Outline button", 22 | "info": "Also used for text links." 23 | }, 24 | "colors_accent_primary": { 25 | "label": "Accent primary", 26 | "info": "Used for solid button background." 27 | }, 28 | "colors_accent_secondary": { 29 | "label": "Accent secondary" 30 | }, 31 | "colors_background_primary": { 32 | "label": "Background primary" 33 | }, 34 | "colors_background_secondary": { 35 | "label": "Background secondary" 36 | } 37 | } 38 | }, 39 | "typography": { 40 | "name": "Typography", 41 | "settings": { 42 | "header_headings": { 43 | "content": "Headings" 44 | }, 45 | "header_body": { 46 | "content": "Body" 47 | }, 48 | "fonts_header": { 49 | "label": "Font", 50 | "info": "Selecting a different font can affect the speed of your store. [Learn more about system fonts.](https://help.shopify.com/en/manual/online-store/os/store-speed/improving-speed#fonts)" 51 | }, 52 | "fonts_body": { 53 | "label": "Font", 54 | "info": "Selecting a different font can affect the speed of your store. [Learn more about system fonts.](https://help.shopify.com/en/manual/online-store/os/store-speed/improving-speed#fonts)" 55 | } 56 | } 57 | }, 58 | "social_media": { 59 | "name": "Social media", 60 | "settings": { 61 | "header": { 62 | "content": "Social accounts" 63 | }, 64 | "social_twitter_link": { 65 | "label": "Twitter", 66 | "info": "https://twitter.com/shopify" 67 | }, 68 | "social_facebook_link": { 69 | "label": "Facebook", 70 | "info": "https://facebook.com/shopify" 71 | }, 72 | "social_pinterest_link": { 73 | "label": "Pinterest", 74 | "info": "https://pinterest.com/shopify" 75 | }, 76 | "social_instagram_link": { 77 | "label": "Instagram", 78 | "info": "http://instagram.com/shopify" 79 | }, 80 | "social_tiktok_link": { 81 | "label": "TikTok", 82 | "info": "https://tiktok.com/@shopify" 83 | }, 84 | "social_tumblr_link": { 85 | "label": "Tumblr", 86 | "info": "https://shopify.tumblr.com" 87 | }, 88 | "social_snapchat_link": { 89 | "label": "Snapchat", 90 | "info": "https://www.snapchat.com/add/shopify" 91 | }, 92 | "social_youtube_link": { 93 | "label": "YouTube", 94 | "info": "https://www.youtube.com/shopify" 95 | }, 96 | "social_vimeo_link": { 97 | "label": "Vimeo", 98 | "info": "https://vimeo.com/shopify" 99 | } 100 | } 101 | }, 102 | "favicon": { 103 | "name": "Favicon", 104 | "settings": { 105 | "favicon": { 106 | "label": "Favicon image", 107 | "info": "Will be scaled down to 64 x 64px" 108 | } 109 | } 110 | }, 111 | "currency_format": { 112 | "name": "Currency format", 113 | "settings": { 114 | "content": "Currency codes", 115 | "paragraph": "Cart and checkout prices always show currency codes. Example: $1.00 USD.", 116 | "currency_code_enabled": { 117 | "label": "Show currency codes" 118 | } 119 | } 120 | } 121 | }, 122 | "sections": { 123 | "header": { 124 | "name": "Header" 125 | }, 126 | "footer": { 127 | "name": "Footer" 128 | }, 129 | "custom-liquid": { 130 | "name": "Custom Liquid", 131 | "settings": { 132 | "custom_liquid": { 133 | "label": "Custom Liquid", 134 | "info": "Add app snippets or other Liquid code to create advanced customizations." 135 | } 136 | }, 137 | "presets": { 138 | "name": "Custom Liquid" 139 | } 140 | }, 141 | "apps": { 142 | "name": "Apps", 143 | "settings": { 144 | "include_container": { 145 | "label": "Make section margins the same as theme" 146 | } 147 | }, 148 | "presets": { 149 | "name": "Apps" 150 | } 151 | }, 152 | "404": { 153 | "name": "404" 154 | }, 155 | "account": { 156 | "name": "Account" 157 | }, 158 | "activate_account": { 159 | "name": "Activate account" 160 | }, 161 | "adresses": { 162 | "name": "Adresses" 163 | }, 164 | "article": { 165 | "name": "Article" 166 | }, 167 | "blog": { 168 | "name": "Blog" 169 | }, 170 | "cart": { 171 | "name": "Cart" 172 | }, 173 | "collection": { 174 | "name": "Collection" 175 | }, 176 | "list_collections": { 177 | "name": "List collections" 178 | }, 179 | "login": { 180 | "name": "Login" 181 | }, 182 | "order": { 183 | "name": "Order" 184 | }, 185 | "page": { 186 | "name": "Page" 187 | }, 188 | "header_password": { 189 | "name": "Password header" 190 | }, 191 | "password": { 192 | "name": "Password" 193 | }, 194 | "product": { 195 | "name": "Product" 196 | }, 197 | "register": { 198 | "name": "Register" 199 | }, 200 | "reset_password": { 201 | "name": "Reset password" 202 | }, 203 | "search": { 204 | "name": "Search" 205 | }, 206 | "welcome": { 207 | "name": "Welcome", 208 | "settings": { 209 | "heading": { 210 | "label": "Heading" 211 | }, 212 | "subheading": { 213 | "label": "Subeading" 214 | }, 215 | "link_label": { 216 | "label": "Link label" 217 | } 218 | }, 219 | "blocks": { 220 | "card": { 221 | "name": "Card", 222 | "settings": { 223 | "heading": { 224 | "label": "Heading" 225 | }, 226 | "description": { 227 | "label": "Description" 228 | } 229 | } 230 | } 231 | }, 232 | "presets": { 233 | "name": "Welcome" 234 | } 235 | } 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /config/settings_schema.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "theme_info", 4 | "theme_name": "Helium", 5 | "theme_version": "2.0.0", 6 | "theme_author": "Youness Idbakkasse", 7 | "theme_documentation_url": "https://helium.idbakkasse", 8 | "theme_support_url": "https://github.com/idbakkasse/helium" 9 | }, 10 | { 11 | "name": "t:settings_schema.colors.name", 12 | "settings": [ 13 | { 14 | "type": "header", 15 | "content": "t:settings_schema.colors.settings.header_primary_colors.content" 16 | }, 17 | { 18 | "type": "color", 19 | "id": "colors_solid_button", 20 | "default": "#222222", 21 | "label": "t:settings_schema.colors.settings.colors_solid_button.label", 22 | "info": "t:settings_schema.colors.settings.colors_solid_button.info" 23 | }, 24 | { 25 | "type": "color", 26 | "id": "colors_accent_primary", 27 | "default": "#121212", 28 | "label": "t:settings_schema.colors.settings.colors_accent_primary.label", 29 | "info": "t:settings_schema.colors.settings.colors_accent_primary.info" 30 | }, 31 | { 32 | "type": "color", 33 | "id": "colors_accent_secondary", 34 | "default": "#4B4B4B", 35 | "label": "t:settings_schema.colors.settings.colors_accent_secondary.label" 36 | }, 37 | { 38 | "type": "header", 39 | "content": "t:settings_schema.colors.settings.header_secondary_colors.content" 40 | }, 41 | { 42 | "type": "color", 43 | "id": "colors_text", 44 | "default": "#252525", 45 | "label": "t:settings_schema.colors.settings.colors_text.label", 46 | "info": "t:settings_schema.colors.settings.colors_text.info" 47 | }, 48 | { 49 | "type": "color", 50 | "id": "colors_outline_button", 51 | "default": "#222222", 52 | "label": "t:settings_schema.colors.settings.colors_outline_button.label", 53 | "info": "t:settings_schema.colors.settings.colors_outline_button.info" 54 | }, 55 | { 56 | "type": "color", 57 | "id": "colors_background_primary", 58 | "default": "#FFFFFF", 59 | "label": "t:settings_schema.colors.settings.colors_background_primary.label" 60 | }, 61 | { 62 | "type": "color", 63 | "id": "colors_background_secondary", 64 | "default": "#F3F3F3", 65 | "label": "t:settings_schema.colors.settings.colors_background_secondary.label" 66 | } 67 | ] 68 | }, 69 | { 70 | "name": "t:settings_schema.typography.name", 71 | "settings": [ 72 | { 73 | "type": "header", 74 | "content": "t:settings_schema.typography.settings.header_headings.content" 75 | }, 76 | { 77 | "type": "font_picker", 78 | "id": "fonts_header", 79 | "default": "sans-serif", 80 | "label": "t:settings_schema.typography.settings.fonts_header.label", 81 | "info": "t:settings_schema.typography.settings.fonts_header.info" 82 | }, 83 | { 84 | "type": "header", 85 | "content": "t:settings_schema.typography.settings.header_body.content" 86 | }, 87 | { 88 | "type": "font_picker", 89 | "id": "fonts_body", 90 | "default": "sans-serif", 91 | "label": "t:settings_schema.typography.settings.fonts_body.label", 92 | "info": "t:settings_schema.typography.settings.fonts_body.info" 93 | } 94 | ] 95 | }, 96 | { 97 | "name": "t:settings_schema.social_media.name", 98 | "settings": [ 99 | { 100 | "type": "header", 101 | "content": "t:settings_schema.social_media.settings.header.content" 102 | }, 103 | { 104 | "type": "text", 105 | "id": "social_twitter_link", 106 | "label": "t:settings_schema.social_media.settings.social_twitter_link.label", 107 | "info": "t:settings_schema.social_media.settings.social_twitter_link.info" 108 | }, 109 | { 110 | "type": "text", 111 | "id": "social_facebook_link", 112 | "label": "t:settings_schema.social_media.settings.social_facebook_link.label", 113 | "info": "t:settings_schema.social_media.settings.social_facebook_link.info" 114 | }, 115 | { 116 | "type": "text", 117 | "id": "social_pinterest_link", 118 | "label": "t:settings_schema.social_media.settings.social_pinterest_link.label", 119 | "info": "t:settings_schema.social_media.settings.social_pinterest_link.info" 120 | }, 121 | { 122 | "type": "text", 123 | "id": "social_instagram_link", 124 | "label": "t:settings_schema.social_media.settings.social_instagram_link.label", 125 | "info": "t:settings_schema.social_media.settings.social_instagram_link.info" 126 | }, 127 | { 128 | "type": "text", 129 | "id": "social_tiktok_link", 130 | "label": "t:settings_schema.social_media.settings.social_tiktok_link.label", 131 | "info": "t:settings_schema.social_media.settings.social_tiktok_link.info" 132 | }, 133 | { 134 | "type": "text", 135 | "id": "social_tumblr_link", 136 | "label": "t:settings_schema.social_media.settings.social_tumblr_link.label", 137 | "info": "t:settings_schema.social_media.settings.social_tumblr_link.info" 138 | }, 139 | { 140 | "type": "text", 141 | "id": "social_snapchat_link", 142 | "label": "t:settings_schema.social_media.settings.social_snapchat_link.label", 143 | "info": "t:settings_schema.social_media.settings.social_snapchat_link.info" 144 | }, 145 | { 146 | "type": "text", 147 | "id": "social_youtube_link", 148 | "label": "t:settings_schema.social_media.settings.social_youtube_link.label", 149 | "info": "t:settings_schema.social_media.settings.social_youtube_link.info" 150 | }, 151 | { 152 | "type": "text", 153 | "id": "social_vimeo_link", 154 | "label": "t:settings_schema.social_media.settings.social_vimeo_link.label", 155 | "info": "t:settings_schema.social_media.settings.social_vimeo_link.info" 156 | } 157 | ] 158 | }, 159 | { 160 | "name": "t:settings_schema.favicon.name", 161 | "settings": [ 162 | { 163 | "type": "image_picker", 164 | "id": "favicon", 165 | "label": "t:settings_schema.favicon.settings.favicon.label", 166 | "info": "t:settings_schema.favicon.settings.favicon.info" 167 | } 168 | ] 169 | }, 170 | { 171 | "name": "t:settings_schema.currency_format.name", 172 | "settings": [ 173 | { 174 | "type": "header", 175 | "content": "t:settings_schema.currency_format.settings.content" 176 | }, 177 | { 178 | "type": "paragraph", 179 | "content": "t:settings_schema.currency_format.settings.paragraph" 180 | }, 181 | { 182 | "type": "checkbox", 183 | "id": "currency_code_enabled", 184 | "label": "t:settings_schema.currency_format.settings.currency_code_enabled.label", 185 | "default": true 186 | } 187 | ] 188 | } 189 | ] 190 | -------------------------------------------------------------------------------- /src/styles/generic/_reset.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## GENERIC: RESET 3 | // ========================================================================== 4 | 5 | /// @content ress.css • v4.0.0 6 | /// @link https://github.com/filipelinhares/ress for more Docs. 7 | /// 8 | 9 | html { 10 | box-sizing: border-box; 11 | -webkit-text-size-adjust: 100%; // Prevent adjustments of font size after orientation changes in iOS // 12 | word-break: normal; 13 | -moz-tab-size: 4; 14 | tab-size: 4; 15 | } 16 | 17 | *, 18 | ::before, 19 | ::after { 20 | background-repeat: no-repeat; // Set `background-repeat: no-repeat` to all elements and pseudo elements // 21 | box-sizing: inherit; 22 | } 23 | 24 | ::before, 25 | ::after { 26 | text-decoration: inherit; // Inherit text-decoration and vertical align to ::before and ::after pseudo elements // 27 | vertical-align: inherit; 28 | } 29 | 30 | * { 31 | padding: 0; // Reset `padding` and `margin` of all elements // 32 | margin: 0; 33 | } 34 | 35 | // # ================================================================= 36 | // # General elements 37 | // # ================================================================= // 38 | 39 | hr { 40 | overflow: visible; // Show the overflow in Edge and IE // 41 | height: 0; // Add the correct box sizing in Firefox // 42 | color: inherit; // Correct border color in Firefox. // 43 | } 44 | 45 | details, 46 | main { 47 | display: block; // Render the `main` element consistently in IE. // 48 | } 49 | 50 | summary { 51 | display: list-item; // Add the correct display in all browsers // 52 | } 53 | 54 | small { 55 | font-size: 80%; // Set font-size to 80% in `small` elements // 56 | } 57 | 58 | [hidden] { 59 | display: none; // Add the correct display in IE // 60 | } 61 | 62 | abbr[title] { 63 | border-bottom: none; // Remove the bottom border in Chrome 57 // 64 | // Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari // 65 | text-decoration: underline; 66 | text-decoration: underline dotted; 67 | } 68 | 69 | a { 70 | background-color: transparent; // Remove the gray background on active links in IE 10 // 71 | } 72 | 73 | a:active, 74 | a:hover { 75 | outline-width: 0; // Remove the outline when hovering in all browsers // 76 | } 77 | 78 | code, 79 | kbd, 80 | pre, 81 | samp { 82 | font-family: monospace, monospace; // Specify the font family of code elements // 83 | } 84 | 85 | pre { 86 | font-size: 1em; // Correct the odd `em` font sizing in all browsers // 87 | } 88 | 89 | b, 90 | strong { 91 | font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari // 92 | } 93 | 94 | // https://gist.github.com/unruthless/413930 // 95 | sub, 96 | sup { 97 | font-size: 75%; 98 | line-height: 0; 99 | position: relative; 100 | vertical-align: baseline; 101 | } 102 | 103 | sub { 104 | bottom: -0.25em; 105 | } 106 | 107 | sup { 108 | top: -0.5em; 109 | } 110 | 111 | table { 112 | border-color: inherit; // Correct border color in all Chrome, Edge, and Safari. // 113 | text-indent: 0; // Remove text indentation in Chrome, Edge, and Safari // 114 | } 115 | 116 | // # ================================================================= 117 | // # Forms 118 | // # ================================================================= // 119 | 120 | input { 121 | border-radius: 0; 122 | } 123 | 124 | // Replace pointer cursor in disabled elements // 125 | [disabled] { 126 | cursor: default; 127 | } 128 | 129 | [type='number']::-webkit-inner-spin-button, 130 | [type='number']::-webkit-outer-spin-button { 131 | height: auto; // Correct the cursor style of increment and decrement buttons in Chrome // 132 | } 133 | 134 | [type='search'] { 135 | -webkit-appearance: textfield; // Correct the odd appearance in Chrome and Safari // 136 | outline-offset: -2px; // Correct the outline style in Safari // 137 | } 138 | 139 | [type='search']::-webkit-search-decoration { 140 | -webkit-appearance: none; // Remove the inner padding in Chrome and Safari on macOS // 141 | } 142 | 143 | textarea { 144 | overflow: auto; // Internet Explorer 11+ // 145 | resize: vertical; // Specify textarea resizability // 146 | } 147 | 148 | button, 149 | input, 150 | optgroup, 151 | select, 152 | textarea { 153 | font: inherit; // Specify font inheritance of form elements // 154 | } 155 | 156 | optgroup { 157 | font-weight: bold; // Restore the font weight unset by the previous rule // 158 | } 159 | 160 | button { 161 | overflow: visible; // Address `overflow` set to `hidden` in IE 8/9/10/11 // 162 | } 163 | 164 | button, 165 | select { 166 | text-transform: none; // Firefox 40+, Internet Explorer 11- // 167 | } 168 | 169 | // Apply cursor pointer to button elements // 170 | button, 171 | [type='button'], 172 | [type='reset'], 173 | [type='submit'], 174 | [role='button'] { 175 | cursor: pointer; 176 | color: inherit; 177 | } 178 | 179 | // Remove inner padding and border in Firefox 4+ // 180 | button::-moz-focus-inner, 181 | [type='button']::-moz-focus-inner, 182 | [type='reset']::-moz-focus-inner, 183 | [type='submit']::-moz-focus-inner { 184 | border-style: none; 185 | padding: 0; 186 | } 187 | 188 | // Replace focus style removed in the border reset above // 189 | button:-moz-focusring, 190 | [type='button']::-moz-focus-inner, 191 | [type='reset']::-moz-focus-inner, 192 | [type='submit']::-moz-focus-inner { 193 | outline: 1px dotted ButtonText; 194 | } 195 | 196 | button, 197 | html [type='button'], // Prevent a WebKit bug where (2) destroys native `audio` and `video`controls in Android 4 // 198 | [type='reset'], 199 | [type='submit'] { 200 | -webkit-appearance: button; // Correct the inability to style clickable types in iOS // 201 | } 202 | 203 | // Remove the default button styling in all browsers // 204 | button, 205 | input, 206 | select, 207 | textarea { 208 | background-color: transparent; 209 | border-style: none; 210 | } 211 | 212 | a:focus, 213 | button:focus, 214 | input:focus, 215 | select:focus, 216 | textarea:focus { 217 | outline-width: 0; 218 | } 219 | 220 | // Style select like a standard input // 221 | select { 222 | -moz-appearance: none; // Firefox 36+ // 223 | -webkit-appearance: none; // Chrome 41+ // 224 | } 225 | 226 | select::-ms-expand { 227 | display: none; // Internet Explorer 11+ // 228 | } 229 | 230 | select::-ms-value { 231 | color: currentColor; // Internet Explorer 11+ // 232 | } 233 | 234 | legend { 235 | border: 0; // Correct `color` not being inherited in IE 8/9/10/11 // 236 | color: inherit; // Correct the color inheritance from `fieldset` elements in IE // 237 | display: table; // Correct the text wrapping in Edge and IE // 238 | max-width: 100%; // Correct the text wrapping in Edge and IE // 239 | white-space: normal; // Correct the text wrapping in Edge and IE // 240 | max-width: 100%; // Correct the text wrapping in Edge 18- and IE // 241 | } 242 | 243 | ::-webkit-file-upload-button { 244 | // Correct the inability to style clickable types in iOS and Safari // 245 | -webkit-appearance: button; 246 | color: inherit; 247 | font: inherit; // Change font properties to `inherit` in Chrome and Safari // 248 | } 249 | 250 | // # ================================================================= 251 | // # Specify media element style 252 | // # ================================================================= // 253 | 254 | img { 255 | border-style: none; // Remove border when inside `a` element in IE 8/9/10 // 256 | } 257 | 258 | // Add the correct vertical alignment in Chrome, Firefox, and Opera // 259 | progress { 260 | vertical-align: baseline; 261 | } 262 | 263 | // # ================================================================= 264 | // # Accessibility 265 | // # ================================================================= 266 | 267 | // Specify the progress cursor of updating elements // 268 | [aria-busy='true'] { 269 | cursor: progress; 270 | } 271 | 272 | // Specify the pointer cursor of trigger elements // 273 | [aria-controls] { 274 | cursor: pointer; 275 | } 276 | 277 | // Specify the unstyled cursor of disabled, not-editable, or otherwise inoperable elements // 278 | [aria-disabled='true'] { 279 | cursor: default; 280 | } 281 | -------------------------------------------------------------------------------- /assets/password.css: -------------------------------------------------------------------------------- 1 | html{box-sizing:border-box;-webkit-text-size-adjust:100%;word-break:normal;-moz-tab-size:4;tab-size:4}*,:before,:after{background-repeat:no-repeat;box-sizing:inherit}:before,:after{text-decoration:inherit;vertical-align:inherit}*{padding:0;margin:0}hr{overflow:visible;height:0;color:inherit}details,main{display:block}summary{display:list-item}small{font-size:80%}[hidden]{display:none}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}a{background-color:transparent}a:active,a:hover{outline-width:0}code,kbd,pre,samp{font-family:monospace,monospace}pre{font-size:1em}b,strong{font-weight:bolder}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-color:inherit;text-indent:0}input{border-radius:0}[disabled]{cursor:default}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}textarea{overflow:auto;resize:vertical}button,input,optgroup,select,textarea{font:inherit}optgroup{font-weight:700}button{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit],[role=button]{cursor:pointer;color:inherit}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{outline:1px dotted ButtonText}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button,input,select,textarea{background-color:transparent;border-style:none}a:focus,button:focus,input:focus,select:focus,textarea:focus{outline-width:0}select{-moz-appearance:none;-webkit-appearance:none}select::-ms-expand{display:none}select::-ms-value{color:currentColor}legend{border:0;color:inherit;display:table;white-space:normal;max-width:100%}::-webkit-file-upload-button{-webkit-appearance:button;color:inherit;font:inherit}img{border-style:none}progress{vertical-align:baseline}[aria-busy=true]{cursor:progress}[aria-controls]{cursor:pointer}[aria-disabled=true]{cursor:default}@media print{*,*:before,*:after{background:transparent!important;box-shadow:none!important;color:#000!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}ul,ol{margin:0;padding:0;list-style:none}summary{cursor:pointer;list-style:none;position:relative}details>*{box-sizing:border-box}a{text-decoration:none;color:inherit}a:hover{text-decoration:underline}a:empty,ul:empty,dl:empty,div:empty,section:empty,article:empty,p:empty,h1:empty,h2:empty,h3:empty,h4:empty,h5:empty,h6:empty{display:none!important}p,figure{margin:0;padding:0}a,area,button,input,label,select,textarea,[tabindex]{-ms-touch-action:manipulation;touch-action:manipulation}[hreflang]>abbr[title]{text-decoration:none}table{border-spacing:0;border-collapse:collapse}button{cursor:pointer}.a11y{position:absolute;display:flex;justify-content:space-between;align-items:center;z-index:999;transform:translateY(-150%);transition:none}.a11y:focus-within{transform:translateY(0)}img{max-width:100%;font-style:italic;vertical-align:middle}audio,canvas,iframe,img,svg,video{vertical-align:middle}svg{fill:currentColor}button,.button{cursor:pointer;display:inline-flex;justify-content:center;align-items:center;margin:0;text-align:center;text-decoration:none;border:0;border-radius:.1875rem;padding:.75rem 1.125rem;font-family:var(--font-heading-family);font-style:var(--font-heading-style);font-weight:var(--font-heading-weight);font-size:1.25rem;user-select:none;appearance:none;transition:transform .2s ease-in}button:hover,button.-primary:hover,.button:hover,.button.-primary:hover{text-decoration:none}button,button.-primary,.button,.button.-primary{background-color:rgba(var(--color-base-solid-button),1);color:rgba(var(--color-base-background-primary),1)}button.-secondary,.button.-secondary{background-color:transparent;color:rgba(var(--color-base-outline-button),1);border:1px solid rgba(var(--color-base-outline-button),1)}button.-small,.button.-small{min-width:6rem}button.-large,.button.-large{min-width:20rem}button.-loading,.button.-loading{cursor:not-allowed;opacity:.8}button:disabled,button[aria-disabled=true],.button:disabled,.button[aria-disabled=true]{cursor:not-allowed;background-color:gray}.heading,h1,h2,h3,h4,h5,h6{font-family:var(--font-heading-family);font-style:var(--font-heading-style);font-weight:var(--font-heading-weight);color:inherit;text-decoration:none}.heading h1,.heading.-h1{font-size:3.375rem;line-height:1.2}@media screen and (max-width: 750px){.heading h1,.heading.-h1{font-size:2.375rem}}.heading h2,.heading.-h2{font-size:1.625rem}@media screen and (max-width: 750px){.heading h2,.heading.-h2{font-size:1.375rem}}.heading h3,.heading.-h3{font-size:1.1875rem}.heading h4,.heading.-h4{font-size:1.0625rem}.heading.-bold{font-weight:700}.heading.-upper{text-transform:uppercase}.field{position:relative;display:flex;align-items:stretch;justify-content:center;width:100%;max-width:22em;margin:0 auto;border:1px solid rgba(var(--color-base-outline-button),1);border-radius:.1875rem}.field_label{position:absolute;left:0;top:50%;left:1rem;transform-origin:center left;transform:translateY(-50%);transition:transform .2s ease;pointer-events:none;cursor:text}.field_input{padding:.8rem 1rem .2rem;flex:1}.field_label,.field_input{font-family:var(--font-body-family);font-style:var(--font-heading-style);font-weight:var(--font-heading-weight);text-decoration:none}.field .field_input::placeholder{color:transparent}.field_input:active+.field_label,.field_input:focus+.field_label,.field_input:focus-visible+.field_label,.field_input:not(:placeholder-shown)+.field_label,.field_input:-webkit-autofill+.field_label{transform:translateY(-100%) scale(.6)}.field.-error{border-color:#f00000e6}.header-password{display:flex;justify-content:space-between;align-items:center;padding-top:1rem}.header-password_logo{font-size:1.4rem}.header-password_form{position:absolute;top:3rem;left:0;bottom:0;right:0}.header-password_form-inner{position:relative;top:45%;transform:translateY(-50%);display:flex;flex-direction:column;justify-content:center;gap:1rem;max-width:400px;width:85%;margin:auto}.container{width:100%;margin:0 auto}.container.-small{padding-left:.5rem;padding-right:.5rem}.container,.container.-medium{padding-left:1rem;padding-right:1rem}.container.-large{padding-left:2rem;padding-right:2rem}.container.-narrow{max-width:30rem}.u-hide{display:none!important}@media screen and (min-width: 0px) and (max-width: 424px){.u-hide-xxs{display:none!important}}@media screen and (min-width: 425px){.u-hide-xs-up{display:none!important}}@media screen and (max-width: 749px){.u-hide-xs-down{display:none!important}}@media screen and (min-width: 750px){.u-hide-sm-up{display:none!important}}@media screen and (max-width: 1024px){.u-hide-sm-down{display:none!important}}@media screen and (min-width: 1025px){.u-hide-md-up{display:none!important}}@media screen and (max-width: 1199px){.u-hide-md-down{display:none!important}}@media screen and (min-width: 1200px){.u-hide-lg-up{display:none!important}}@media screen and (max-width: 1439px){.u-hide-lg-down{display:none!important}}@media screen and (min-width: 1440px){.u-hide-xlg{display:none!important}}.u-hide-visually{position:absolute!important;border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0!important;width:1px;word-wrap:normal!important}.u-hide-visually-focusable{position:absolute!important;word-wrap:normal!important;border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0!important;width:1px}.u-hide-visually-focusable:focus,.u-hide-visually-focusable:active{clip:auto;width:auto;height:auto}@media (prefers-reduced-motion){.u-motion-reduce{transition:none!important}}.u-show,.u-hide-none{display:block!important;visibility:visible!important}.u-focus-none{box-shadow:none!important;outline:0!important}.u-visible{visibility:visible!important;opacity:1!important}.u-invisible{visibility:hidden!important;opacity:0!important} 2 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | [Before contributing](#before-contributing) | 4 | [Scope](#scope) | 5 | [Theme code principles](#theme-code-principles) | 6 | [Contributing code](#contributing-code) | 7 | [Reporting a bug](#reporting-a-bug) | 8 | [Reviewing](#reviewing) 9 | 10 | We're really glad you're reading this, because we would love to have more developers contribute to this theme! If you're passionate about building for the next million entrepreneurs, you're in the right place. 11 | 12 | ## Before contributing 13 | 14 | If you encounter a bug or think of a useful feature for Helium, please [create a new issue](https://github.com/idbakkasse/helium/issues/new). Creating an issue before jumping into code ensures we can discuss it and determine whether it aligns with the direction of the theme. 15 | 16 | If you want to contribute to the theme, regardless of whether it's a small bug fix or correcting a typo, please feel free to do so. Any help goes a long way! Also, contributions aren't necessarily all code related. Other contributions can be in the form of issues, pull requests, discussions, etc. 17 | 18 | ## Scope 19 | 20 | This Github repository exists for the theme development community to discuss and solve problems directly related to Helium. It **is not the place** to discuss general theme development problems, nor the place to seek help for non-related problems. 21 | 22 | Theme development is a big topic and it's completely normal that you will encounter problems which might require you to reach out for help. In fact, we provide several knowledge and support platforms for theme development already: 23 | 24 | * [Theme Development](https://shopify.dev/themes) 25 | 26 | ## Theme code principles 27 | 28 | Before contributing to Helium, please read the following theme code principles to better understand our fundamental approach to theme development. The expectation is that you follow these principles as you build for Helium. 29 | 30 | ### Why these principles? 31 | 32 | Browsers provide APIs to solve many problems: from [WebGL](https://en.wikipedia.org/wiki/WebGL) and [WASM](https://en.wikipedia.org/wiki/WebAssembly)-powered apps to static websites. The best APIs to use depends on the thing you’re building. Themes power ecommerce websites. In most cases, _Web-native_—making the most of the built-in features of browsers: HTTP, HTML, CSS, JavaScript, and the DOM—is a perfect fit for ecommerce websites. Ecommerce needs incredibly fast websites for mostly “logged out” traffic. 33 | 34 | ### Web-native in its purest form 35 | 36 | _The most important principle._ 37 | 38 | Themes run on the [evergreen Web](https://www.w3.org/2001/tag/doc/evergreen-web/). We leverage the latest web browsers to their fullest, while maintaining support for the older ones through progressive enhancement—not polyfills. 39 | 40 | We write bespoke Web-native code with no abstractions. Frameworks, libraries, and dependencies don’t belong in our themes. 41 | 42 | We engage with the browser ecosystem on behalf of our merchants to make Web-native ecommerce the best it can be. 43 | 44 | “Don’t repeat yourself” is an anti-pattern. We do our utmost best to do more with less, but we don’t build abstractions around repetition. Instead, we use linting and testing to enforce consistently-good and up-to-date Web-native code. 45 | 46 | ### Lean, fast, and reliable 47 | 48 | _The principle requirement._ 49 | 50 | Code must be lean, fast, and reliable. Our targets include: 51 | 52 | * Zero [Cumulative Layout Shift](https://web.dev/cls/) 53 | * No DOM manipulation before user input 54 | * No render-blocking JavaScript 55 | * No [long tasks](https://developer.mozilla.org/en-US/docs/Web/API/Long_Tasks_API) 56 | 57 | Functionality and design defaults to “no” until it meets this requirement. Code ships on quality. 58 | 59 | We relentlessly and continuously optimize code within the constraint of being Web-native. If ever there is a feature that browsers have not made fast yet, we either don’t use it, or use it “as is” if it is fast enough. We trust that browsers will get faster over time. 60 | 61 | Themes must be built with purpose. They shouldn’t support each and every feature in Shopify. 62 | 63 | ### JavaScript not required, fails gracefully 64 | 65 | _NoJS is our baseline._ 66 | 67 | We extract every bit of speed and functionality out of HTTP, semantic HTML, and CSS before writing our first line of JavaScript. 68 | 69 | JavaScript can only be used to progressively enhance features. JavaScript cannot be required to find or purchase products. And the little JavaScript that we use must always fail gracefully, such that every browser gets the most “enhanced” experience that it can within the capabilities that it has. 70 | 71 | >:information_source: We do so not because we expect buyers to experience our storefronts with JavaScript disabled, but because it keeps us aligned with the other principles: writing fast, server-rendered, Web-native code. 72 | 73 | ### Server-rendered 74 | 75 | _Our main constraint._ 76 | 77 | HTML must be rendered by Shopify servers using [Liquid](https://shopify.dev/api/liquid). Business logic and platform primitives such as translations and money formatting don’t belong on the client. 78 | 79 | Server-rendered doesn’t imply “full page reload”. Async and on-demand rendering of parts of the page is OK, but we do it sparingly as a progressive enhancement. 80 | 81 | ### Functional, not pixel-perfect 82 | 83 | _No buyer is left behind._ 84 | 85 | The Web doesn’t require each page to be rendered pixel-perfect by each browser engine. Using semantic markup, progressive enhancement, and clever design, we ensure that themes remain functional regardless of the browser. 86 | 87 | And since legacy browsers are often the slowest, we don’t burden them with polyfills. We rely instead on the fail-open nature of the Web to provide them with a “minimal but functional” experience. 88 | 89 | ## Contributing code 90 | 91 | You can follow these steps to go from setting up a store to creating a pull request for helium. 92 | 93 | >:information_source: We'll assume you're already set up with Git and GitHub (if you're not familiar with these, [start with these docs](https://docs.github.com/en/github/getting-started-with-github/quickstart/set-up-git)). 94 | 95 | 1. Set up a [development store](https://shopify.dev/themes/tools/development-stores) so you can test your code changes (assuming you don't already have a store). 96 | 2. Install the [Shopify CLI](https://github.com/shopify/shopify-cli) by following [these steps](https://shopify.dev/themes/tools/cli/installation). 97 | 3. Fork the repository, clone it and create a new branch: 98 | 99 | ```sh 100 | git clone git@github.com:your-username/helium.git 101 | cd helium 102 | git checkout -b your-new-branch-name 103 | ``` 104 | 4. Launch a development server: 105 | ```sh 106 | shopify theme serve 107 | ``` 108 | 5. Add your changes to the codebase. 109 | 6. Commit your changes: 110 | ```sh 111 | git commit -a -m="Your commit message" 112 | ``` 113 | 7. Push your commit to your forked repository: 114 | ```sh 115 | git push origin your-new-branch-name 116 | ``` 117 | 8. Open a pull request. See [GitHub's official documentation](https://help.github.com/articles/creating-a-pull-request-from-a-fork/) for more details. 118 | 119 | ## Reporting a bug 120 | 121 | Bugs are tracked as [GitHub issues](https://github.com/idbakkasse/helium/issues). Search open issues to see if someone else has reported a similar bug. If it's something new, [open an issue](https://github.com/idbakkasse/helium/issues/new). We'll use the issue to have a conversation about the problem you want to fix. 122 | 123 | When creating a new issue, please ensure the issue is clear and include additional details to help maintainers reproduce it: 124 | 125 | * **Use a clear and descriptive title** for the issue to identify the problem. 126 | * **Describe the exact steps which reproduce the problem** in as many details as possible. 127 | * **Provide specific examples to demonstrate the steps.** Include links to files, or copy/pasteable snippets. If you're providing snippets in the issue, use Markdown code blocks. 128 | * **Describe the behavior you observed** after following the steps and point out what exactly is the problem with that behavior. 129 | * **Explain which behavior you expected to see** instead and why. 130 | * **Include screenshots and animated GIFs** where possible. 131 | 132 | ## Reviewing 133 | 134 | We (the Themes team) review every single PR. The purpose of reviews is to create the best version of Helium we can for merchants, developers, and others who use it. 135 | 136 | :yellow_heart: Reviews are always respectful, acknowledging that everyone did the best possible job with the knowledge they had at the time. 137 | :yellow_heart: Reviews discuss content, not the person who created it. 138 | :yellow_heart: Reviews are constructive and start conversation around feedback. 139 | 140 | ### Self review 141 | 142 | You should always review your own PR first. 143 | 144 | For code changes, make sure that you: 145 | - [ ] Confirm that the changes meet our [theme code principles](#theme-code-principles). 146 | - [ ] Check new or updated Liquid docs to confirm that the code used is up to date and isn't deprecated. 147 | - [ ] If there are any failing checks in your PR, troubleshoot them until they're all passing. 148 | - [ ] Add @username/themes-front-end-developers as a reviewer. 149 | 150 | ### Suggested changes 151 | 152 | We may ask for changes to be made before a PR can be merged, either using [suggested changes](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request) or pull request comments. You can apply suggested changes directly through the UI. You can make any other changes in your fork, then commit them to your branch. 153 | 154 | As you update your PR and apply changes, mark each conversation as [resolved](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request#resolving-conversations). 155 | -------------------------------------------------------------------------------- /src/styles/objects/_grid.scss: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // ## OBJECTS: GRID 3 | // ========================================================================== 4 | 5 | /// @todo Object classes for flex and grid layouts. 6 | /// 7 | /// .grid {} - Base grid. 8 | /// 9 | 10 | @use 'sass:math'; 11 | // Prefix 12 | // ------------------------- 13 | // You can optionally namespace grid classes to avoid clashing with other css frameworks 14 | // e.g. setting $grid-prefix as "grid-" here would cause col-sm-6 to become grid-col-sm-6 15 | // Example: $grid-prefix: grid-; 16 | // By default this is an empty string 17 | $grid-prefix: '' !default; 18 | 19 | // Legacy support 20 | // ------------------------- 21 | // grid adds a lot of css propertie to support older browsers that don't support flexbox layout. 22 | // If you prefer to use this as a purely flexbox grid without legacy support then set this to false 23 | $legacy-support: false !default; 24 | 25 | // Grid 26 | // ------------------------- 27 | $grid-columns: 12 !default; // number of columns 28 | 29 | // -------------------------------------------------- 30 | // grid mixins 31 | // -------------------------------------------------- 32 | // 33 | 34 | @mixin make-grid-grid($class) { 35 | @include loop-grid-columns($grid-columns, $class, width); 36 | } 37 | 38 | @mixin calc-grid-columns($index, $class, $type) { 39 | @if $type == width and $index > 0 { 40 | .#{$grid-prefix}#{$class}#{$index} { 41 | width: percentage(math.div($index, $grid-columns)); 42 | @if $legacy-support == true { 43 | *width: percentage(math.div($index, $grid-columns)) - 44 | 0.1; // ie7 css hack 45 | } 46 | } 47 | } 48 | } 49 | 50 | @mixin loop-grid-columns($index, $class, $type) { 51 | @if $index >= 0 { 52 | @include calc-grid-columns($index, $class, $type); 53 | // next iteration 54 | @include loop-grid-columns(($index - 1), $class, $type); 55 | } 56 | } 57 | 58 | // defaults for auto cols 59 | @mixin setup-auto-cols() { 60 | @include flex(1, 0, 0px); // a unit on last value is required by IE10-11 61 | 62 | @if $legacy-support == true { 63 | width: auto; 64 | } 65 | } 66 | 67 | // -------------------------------------------------- 68 | // inline-block specific mixins 69 | // -------------------------------------------------- 70 | 71 | @mixin setup-whitespace() { 72 | @if $legacy-support == true { 73 | letter-spacing: -0.31em; 74 | *letter-spacing: normal; 75 | word-spacing: -0.43em; 76 | } 77 | } 78 | 79 | @mixin reset-whitespace() { 80 | @if $legacy-support == true { 81 | letter-spacing: normal; 82 | word-spacing: normal; 83 | white-space: normal; 84 | } 85 | } 86 | 87 | @mixin reset-text-align() { 88 | // 89 | // We want to reset any text-align properties set by the grid 90 | // (required for the inline-block fallback) 91 | // but we don't want to override any text-align properties 92 | // set on the individual col-x element 93 | // or on any of it's child elements 94 | // 95 | // 1) set to left by default (works everywhere) 96 | // 2) set to start (respects right to left text) 97 | // 98 | text-align: left; 99 | text-align: start; 100 | -moz-text-align-last: left; 101 | -moz-text-align-last: start; 102 | text-align-last: left; 103 | text-align-last: start; 104 | } 105 | 106 | // -------------------------------------------------- 107 | // order class generation mixins 108 | // -------------------------------------------------- 109 | 110 | @mixin order($order: 0) { 111 | -ms-flex-order: $order; 112 | -webkit-order: $order; 113 | order: $order; 114 | } 115 | 116 | @mixin make-order-helpers() { 117 | @include loop-order-helpers($grid-columns); 118 | } 119 | 120 | @mixin loop-order-helpers($index, $breakpoint: null) { 121 | @if $index >= 0 { 122 | .#{$grid-prefix}order#{$breakpoint}-#{$index} { 123 | @include order($index); 124 | } 125 | // next iteration 126 | @include loop-order-helpers(($index - 1), $breakpoint); 127 | } 128 | } 129 | 130 | // -------------------------------------------------- 131 | // offset class generation mixins 132 | // -------------------------------------------------- 133 | @mixin offset($index: 0) { 134 | $offset: math.div($index, $grid-columns); 135 | // convert to percentage only if not zero 136 | @if $offset != 0 { 137 | $offset: percentage($offset); 138 | } 139 | margin-left: $offset; 140 | @if $legacy-support == true { 141 | *margin-left: percentage(math.div($index, $grid-columns)) - 142 | 0.1; // ie7 css hack 143 | } 144 | } 145 | 146 | @mixin make-offset-helpers() { 147 | @include loop-offset-helpers($grid-columns - 1); 148 | } 149 | 150 | @mixin loop-offset-helpers($index, $breakpoint: null) { 151 | @if $index > 0 and $breakpoint == null { 152 | .#{$grid-prefix}offset#{$breakpoint}-#{$index} { 153 | @include offset($index); 154 | } 155 | // next iteration 156 | @include loop-offset-helpers(($index - 1), $breakpoint); 157 | } @else if $index >= 0 and $breakpoint != null { 158 | .#{$grid-prefix}offset#{$breakpoint}-#{$index} { 159 | @include offset($index); 160 | } 161 | // next iteration 162 | @include loop-offset-helpers(($index - 1), $breakpoint); 163 | } 164 | } 165 | 166 | // -------------------------------------------------- 167 | // grid modifier mixins 168 | // -------------------------------------------------- 169 | 170 | // 171 | // display 172 | // --- 173 | 174 | @mixin display-flex() { 175 | display: -ms-flexbox; 176 | display: -webkit-flex; 177 | display: flex; 178 | } 179 | 180 | // 181 | // flex 182 | // --- 183 | 184 | @mixin flex($grow: 0, $shrink: 1, $basis: auto) { 185 | @if $basis == 0 { 186 | -ms-flex: $grow $shrink auto; //ie10 needs auto 187 | } @else { 188 | -ms-flex: $grow $shrink $basis; 189 | } 190 | 191 | -webkit-flex: $grow $shrink $basis; 192 | flex: $grow $shrink $basis; 193 | } 194 | 195 | @mixin flex-grow($grow: 1) { 196 | -ms-flex-positive: $grow; 197 | -webkit-flex-grow: $grow; 198 | flex-grow: $grow; 199 | } 200 | 201 | @mixin flex-shrink($shrink: 1) { 202 | -ms-flex-negative: $shrink; 203 | -webkit-flex-shrink: $shrink; 204 | flex-shrink: $shrink; 205 | } 206 | 207 | @mixin flex-basis($basis: auto) { 208 | -ms-flex-preferred-size: $basis; 209 | -webkit-flex-basis: $basis; 210 | flex-basis: $basis; 211 | } 212 | 213 | @mixin flex-flow($direction: row, $wrap: nowrap) { 214 | -ms-flex-wrap: $wrap; 215 | -ms-flex-direction: $direction; 216 | -webkit-flex-flow: $direction $wrap; 217 | flex-flow: $direction $wrap; 218 | } 219 | 220 | @mixin flex-wrap($wrap: wrap) { 221 | -ms-flex-wrap: $wrap; 222 | -webkit-flex-wrap: $wrap; 223 | flex-wrap: $wrap; 224 | } 225 | 226 | @mixin flex-direction($direction: row) { 227 | -ms-flex-direction: $direction; 228 | -webkit-flex-direction: $direction; 229 | flex-direction: $direction; 230 | } 231 | 232 | // 233 | // align 234 | // --- 235 | 236 | @mixin align-items($align: stretch) { 237 | @include ms-align-items($align); 238 | -webkit-align-items: $align; 239 | align-items: $align; 240 | } 241 | 242 | @mixin align-self($align: stretch) { 243 | @include ms-align-self($align); 244 | -webkit-align-self: $align; 245 | align-self: $align; 246 | } 247 | 248 | @mixin align-content($align: stretch) { 249 | @include ms-align-content($align); 250 | -webkit-align-content: $align; 251 | align-content: $align; 252 | } 253 | 254 | // 255 | // ie10 syntax for align 256 | // --- 257 | 258 | @mixin ms-align-items($align) { 259 | @if $align == 'flex-start' { 260 | -ms-flex-align: start; 261 | } @else if $align == 'flex-end' { 262 | -ms-flex-align: end; 263 | } @else { 264 | -ms-flex-align: $align; 265 | } 266 | } 267 | 268 | @mixin ms-align-self($align) { 269 | @if $align == 'flex-start' { 270 | -ms-flex-item-align: start; 271 | } @else if $align == 'flex-end' { 272 | -ms-flex-item-align: end; 273 | } @else { 274 | -ms-flex-item-align: $align; 275 | } 276 | } 277 | 278 | @mixin ms-align-content($align) { 279 | @if $align == 'flex-start' { 280 | -ms-flex-line-pack: start; 281 | } @else if $align == 'flex-end' { 282 | -ms-flex-line-pack: end; 283 | } @else if $align == 'space-between' { 284 | -ms-flex-line-pack: justify; 285 | } @else if $align == 'space-around' { 286 | -ms-flex-line-pack: distribute; 287 | } @else { 288 | -ms-flex-line-pack: $align; 289 | } 290 | } 291 | 292 | // 293 | // justify-content 294 | // 295 | // Uses "text-align" for the fallback inline-block grid 296 | // "text-align" is globally supported and works on all rows except the last 297 | // "text-align-last", where supported, handles the last line (and, happily, grids with only one row) 298 | // --- 299 | 300 | @mixin justify-content-start() { 301 | -ms-flex-pack: start; 302 | -webkit-justify-content: flex-start; 303 | justify-content: flex-start; 304 | } 305 | 306 | @mixin justify-content-end() { 307 | -ms-flex-pack: end; 308 | -webkit-justify-content: flex-end; 309 | justify-content: flex-end; 310 | } 311 | 312 | @mixin justify-content-center() { 313 | -ms-flex-pack: center; 314 | -webkit-justify-content: center; 315 | justify-content: center; 316 | } 317 | 318 | @mixin justify-content-space-between() { 319 | -ms-flex-pack: justify; 320 | -webkit-justify-content: space-between; 321 | justify-content: space-between; 322 | } 323 | 324 | @mixin justify-content-space-around() { 325 | -ms-flex-pack: distribute; 326 | -webkit-justify-content: space-around; 327 | justify-content: space-around; 328 | } 329 | 330 | // -------------------------------------------------- 331 | // grid 332 | // -------------------------------------------------- 333 | 334 | .#{$grid-prefix}grid { 335 | @include display-flex(); 336 | @include flex-wrap(); 337 | position: relative; 338 | @include setup-whitespace(); 339 | 340 | &::before, 341 | &::after { 342 | @include reset-whitespace(); 343 | } 344 | // handle when lists are used as a grid 345 | list-style-type: none; 346 | } 347 | 348 | // -------------------------------------------------- 349 | // grid col defaults 350 | // -------------------------------------------------- 351 | 352 | [class*='#{$grid-prefix}col-'] { 353 | @include reset-whitespace(); 354 | position: relative; 355 | width: 100%; 356 | vertical-align: top; 357 | // padding: $grid-grid-spacing; 358 | 359 | &::before, 360 | &::after { 361 | @include reset-whitespace(); 362 | } 363 | 364 | // // handle grids nested in columns 365 | // .#{$grid-prefix}grid { 366 | // @include flex(1, 1, auto); 367 | // margin: -$grid-grid-spacing; 368 | // } 369 | 370 | @if $legacy-support == true { 371 | display: inline-block; 372 | *display: inline; 373 | zoom: 1; 374 | } 375 | } 376 | 377 | // -------------------------------------------------- 378 | // grid generation 379 | // -------------------------------------------------- 380 | 381 | @include make-grid-grid(col-); 382 | 383 | @media screen and (min-width: $breakpoint-xs) { 384 | @include make-grid-grid(col-xs-); 385 | } 386 | 387 | @media screen and (min-width: $breakpoint-sm) { 388 | @include make-grid-grid(col-sm-); 389 | } 390 | 391 | @media screen and (min-width: $breakpoint-md) { 392 | @include make-grid-grid(col-md-); 393 | } 394 | 395 | @media screen and (min-width: $breakpoint-lg) { 396 | @include make-grid-grid(col-lg-); 397 | } 398 | 399 | @media screen and (min-width: $breakpoint-xlg) { 400 | @include make-grid-grid(col-xlg-); 401 | } 402 | 403 | // -------------------------------------------------- 404 | // grid col-auto 405 | // -------------------------------------------------- 406 | 407 | .#{$grid-prefix}col-auto { 408 | @include setup-auto-cols(); 409 | } 410 | 411 | @media screen and (min-width: $breakpoint-xs) { 412 | .#{$grid-prefix}col-xs-auto { 413 | @include setup-auto-cols(); 414 | } 415 | } 416 | 417 | @media screen and (min-width: $breakpoint-sm) { 418 | .#{$grid-prefix}col-sm-auto { 419 | @include setup-auto-cols(); 420 | } 421 | } 422 | 423 | @media screen and (min-width: $breakpoint-md) { 424 | .#{$grid-prefix}col-md-auto { 425 | @include setup-auto-cols(); 426 | } 427 | } 428 | 429 | @media screen and (min-width: $breakpoint-lg) { 430 | .#{$grid-prefix}col-lg-auto { 431 | @include setup-auto-cols(); 432 | } 433 | } 434 | 435 | @media screen and (min-width: $breakpoint-xlg) { 436 | .#{$grid-prefix}col-xlg-auto { 437 | @include setup-auto-cols(); 438 | } 439 | } 440 | 441 | // -------------------------------------------------- 442 | // grid order helpers generation 443 | // -------------------------------------------------- 444 | 445 | @include make-order-helpers(); 446 | 447 | @media screen and (min-width: $breakpoint-xs) { 448 | @include loop-order-helpers($grid-columns, '-xs'); 449 | } 450 | 451 | @media screen and (min-width: $breakpoint-sm) { 452 | @include loop-order-helpers($grid-columns, '-sm'); 453 | } 454 | 455 | @media screen and (min-width: $breakpoint-md) { 456 | @include loop-order-helpers($grid-columns, '-md'); 457 | } 458 | 459 | @media screen and (min-width: $breakpoint-lg) { 460 | @include loop-order-helpers($grid-columns, '-lg'); 461 | } 462 | 463 | @media screen and (min-width: $breakpoint-xlg) { 464 | @include loop-order-helpers($grid-columns, '-xlg'); 465 | } 466 | 467 | // -------------------------------------------------- 468 | // grid offset helpers generation 469 | // -------------------------------------------------- 470 | 471 | @include make-offset-helpers(); 472 | 473 | @media screen and (min-width: $breakpoint-xs) { 474 | @include loop-offset-helpers($grid-columns - 1, '-xs'); 475 | } 476 | 477 | @media screen and (min-width: $breakpoint-sm) { 478 | @include loop-offset-helpers($grid-columns - 1, '-sm'); 479 | } 480 | 481 | @media screen and (min-width: $breakpoint-md) { 482 | @include loop-offset-helpers($grid-columns - 1, '-md'); 483 | } 484 | 485 | @media screen and (min-width: $breakpoint-lg) { 486 | @include loop-offset-helpers($grid-columns - 1, '-lg'); 487 | } 488 | 489 | @media screen and (min-width: $breakpoint-xlg) { 490 | @include loop-offset-helpers($grid-columns - 1, '-xlg'); 491 | } 492 | 493 | // -------------------------------------------------- 494 | // grid modifiers 495 | // -------------------------------------------------- 496 | 497 | // -------------------------------------------------- 498 | // flex-wrap 499 | // -------------------------------------------------- 500 | 501 | .#{$grid-prefix}wrap { 502 | @include flex-wrap(wrap); 503 | } 504 | 505 | .#{$grid-prefix}no-wrap { 506 | @include flex-wrap(nowrap); 507 | 508 | // This is mostly needed to stop the grid contents overflowing in the 509 | // ie10 implementation of flexbox but it can't hurt in other browsers 510 | // as it is the desired behaviour of non wrapping flex items 511 | [class*='#{$grid-prefix}col-'] { 512 | @include flex-shrink(1); 513 | } 514 | } 515 | 516 | .#{$grid-prefix}wrap-reverse { 517 | @include flex-wrap(wrap-reverse); 518 | } 519 | 520 | // -------------------------------------------------- 521 | // flex-direction 522 | // -------------------------------------------------- 523 | 524 | .#{$grid-prefix}direction-row { 525 | @include flex-direction(row); 526 | } 527 | 528 | .#{$grid-prefix}direction-row-reverse { 529 | @include flex-direction(row-reverse); 530 | } 531 | 532 | .#{$grid-prefix}direction-column { 533 | @include flex-direction(column); 534 | } 535 | 536 | .#{$grid-prefix}direction-column-reverse { 537 | @include flex-direction(column-reverse); 538 | } 539 | 540 | // -------------------------------------------------- 541 | // align items (cross axis) 542 | // -------------------------------------------------- 543 | 544 | .#{$grid-prefix}align-start { 545 | @include align-items(flex-start); 546 | } 547 | 548 | .#{$grid-prefix}align-end { 549 | @include align-items(flex-end); 550 | 551 | @if $legacy-support == true { 552 | // fallback to legacy vertical-align 553 | [class*='#{$grid-prefix}col-'] { 554 | vertical-align: bottom; 555 | } 556 | } 557 | } 558 | 559 | .#{$grid-prefix}align-center { 560 | @include align-items(center); 561 | 562 | @if $legacy-support == true { 563 | // fallback to legacy vertical-align 564 | [class*='#{$grid-prefix}col-'] { 565 | vertical-align: middle; 566 | } 567 | } 568 | } 569 | 570 | .#{$grid-prefix}align-baseline { 571 | @include align-items(baseline); 572 | } 573 | 574 | // -------------------------------------------------- 575 | // align content (cross axis) 576 | // -------------------------------------------------- 577 | 578 | .#{$grid-prefix}align-content-start { 579 | @include align-content(flex-start); 580 | } 581 | 582 | .#{$grid-prefix}align-content-end { 583 | @include align-content(flex-end); 584 | 585 | // fallback to legacy vertical-align 586 | [class*='#{$grid-prefix}col-'] { 587 | vertical-align: bottom; 588 | } 589 | } 590 | 591 | .#{$grid-prefix}align-content-center { 592 | @include align-content(center); 593 | } 594 | 595 | .#{$grid-prefix}align-content-space-between { 596 | @include align-content(space-between); 597 | } 598 | 599 | .#{$grid-prefix}align-content-space-around { 600 | @include align-content(space-around); 601 | } 602 | 603 | // -------------------------------------------------- 604 | // align-self 605 | // -------------------------------------------------- 606 | 607 | .#{$grid-prefix}align-self-stretch { 608 | @include align-self(stretch); 609 | } 610 | 611 | .#{$grid-prefix}align-self-start { 612 | @include align-self(flex-start); 613 | } 614 | 615 | .#{$grid-prefix}align-self-end { 616 | @include align-self(flex-end); 617 | vertical-align: bottom; 618 | } 619 | 620 | .#{$grid-prefix}align-self-center { 621 | @include align-self(center); 622 | vertical-align: middle; 623 | } 624 | 625 | .#{$grid-prefix}align-self-baseline { 626 | @include align-self(baseline); 627 | vertical-align: baseline; 628 | } 629 | 630 | // -------------------------------------------------- 631 | // justify-content (main axis) 632 | // -------------------------------------------------- 633 | 634 | .#{$grid-prefix}justify-start { 635 | @include justify-content-start(); 636 | 637 | @if $legacy-support == true { 638 | &.grid { 639 | text-align: left; 640 | } 641 | } 642 | } 643 | 644 | .#{$grid-prefix}justify-end { 645 | @include justify-content-end(); 646 | 647 | @if $legacy-support == true { 648 | &.grid { 649 | text-align: right; 650 | -moz-text-align-last: right; 651 | text-align-last: right; 652 | 653 | [class*='#{$grid-prefix}col-'] { 654 | @include reset-text-align(); 655 | } 656 | } 657 | } 658 | } 659 | 660 | .#{$grid-prefix}justify-center { 661 | @include justify-content-center(); 662 | 663 | @if $legacy-support == true { 664 | &.grid { 665 | text-align: center; 666 | -moz-text-align-last: center; 667 | text-align-last: center; 668 | 669 | [class*='#{$grid-prefix}col-'] { 670 | @include reset-text-align(); 671 | } 672 | } 673 | } 674 | } 675 | 676 | .#{$grid-prefix}justify-space-between { 677 | @include justify-content-space-between(); 678 | 679 | @if $legacy-support == true { 680 | &.grid { 681 | text-align: justify; 682 | -moz-text-align-last: justify; 683 | text-align-last: justify; 684 | 685 | [class*='#{$grid-prefix}col-'] { 686 | @include reset-text-align(); 687 | } 688 | } 689 | } 690 | } 691 | 692 | .#{$grid-prefix}justify-space-around { 693 | @include justify-content-space-around(); 694 | 695 | @if $legacy-support == true { 696 | &.grid { 697 | text-align: justify; 698 | -moz-text-align-last: justify; 699 | text-align-last: justify; 700 | 701 | [class*='#{$grid-prefix}col-'] { 702 | @include reset-text-align(); 703 | } 704 | } 705 | } 706 | } 707 | 708 | // -------------------------------------------------- 709 | // cosmetic grid modifiers 710 | // -------------------------------------------------- 711 | 712 | // Removes internal padding from all columns in a grid 713 | .#{$grid-prefix}grid-bleed { 714 | [class*='#{$grid-prefix}col-'] { 715 | padding: 0; 716 | } 717 | } 718 | 719 | // -------------------------------------------------- 720 | // col modifiers 721 | // -------------------------------------------------- 722 | 723 | // Makes a column element into a flexbox column 724 | .#{$grid-prefix}col-grid { 725 | @include display-flex(); 726 | @include flex-direction(column); 727 | 728 | &.#{$grid-prefix}direction-row { 729 | @include flex-direction(row); 730 | } 731 | } 732 | 733 | // -------------------------------------------------- 734 | // col-grid contents 735 | // -------------------------------------------------- 736 | 737 | .#{$grid-prefix}flex-img { 738 | display: block; 739 | @include flex(0, 0, auto); 740 | max-width: 100%; 741 | height: auto; 742 | width: 100%; 743 | @if $legacy-support == true { 744 | *width: auto; 745 | } 746 | } 747 | 748 | .#{$grid-prefix}flex-footer { 749 | width: 100%; 750 | margin-top: auto; 751 | margin-bottom: 0; 752 | 753 | > :last-child { 754 | margin-bottom: 0; 755 | } 756 | } 757 | -------------------------------------------------------------------------------- /assets/base.css: -------------------------------------------------------------------------------- 1 | html{box-sizing:border-box;-webkit-text-size-adjust:100%;word-break:normal;-moz-tab-size:4;tab-size:4}*,:before,:after{background-repeat:no-repeat;box-sizing:inherit}:before,:after{text-decoration:inherit;vertical-align:inherit}*{padding:0;margin:0}hr{overflow:visible;height:0;color:inherit}details,main{display:block}summary{display:list-item}small{font-size:80%}[hidden]{display:none}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}a{background-color:transparent}a:active,a:hover{outline-width:0}code,kbd,pre,samp{font-family:monospace,monospace}pre{font-size:1em}b,strong{font-weight:bolder}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-color:inherit;text-indent:0}input{border-radius:0}[disabled]{cursor:default}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}textarea{overflow:auto;resize:vertical}button,input,optgroup,select,textarea{font:inherit}optgroup{font-weight:700}button{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit],[role=button]{cursor:pointer;color:inherit}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{outline:1px dotted ButtonText}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button,input,select,textarea{background-color:transparent;border-style:none}a:focus,button:focus,input:focus,select:focus,textarea:focus{outline-width:0}select{-moz-appearance:none;-webkit-appearance:none}select::-ms-expand{display:none}select::-ms-value{color:currentColor}legend{border:0;color:inherit;display:table;white-space:normal;max-width:100%}::-webkit-file-upload-button{-webkit-appearance:button;color:inherit;font:inherit}img{border-style:none}progress{vertical-align:baseline}[aria-busy=true]{cursor:progress}[aria-controls]{cursor:pointer}[aria-disabled=true]{cursor:default}@media print{*,*:before,*:after{background:transparent!important;box-shadow:none!important;color:#000!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}ul,ol{margin:0;padding:0;list-style:none}summary{cursor:pointer;list-style:none;position:relative}details>*{box-sizing:border-box}a{text-decoration:none;color:inherit}a:hover{text-decoration:underline}a:empty,ul:empty,dl:empty,div:empty,section:empty,article:empty,p:empty,h1:empty,h2:empty,h3:empty,h4:empty,h5:empty,h6:empty{display:none!important}p,figure{margin:0;padding:0}a,area,button,input,label,select,textarea,[tabindex]{-ms-touch-action:manipulation;touch-action:manipulation}[hreflang]>abbr[title]{text-decoration:none}table{border-spacing:0;border-collapse:collapse}button{cursor:pointer}.a11y{position:absolute;display:flex;justify-content:space-between;align-items:center;z-index:999;transform:translateY(-150%);transition:none}.a11y:focus-within{transform:translateY(0)}img{max-width:100%;font-style:italic;vertical-align:middle}audio,canvas,iframe,img,svg,video{vertical-align:middle}svg{fill:currentColor}button,.button{cursor:pointer;display:inline-flex;justify-content:center;align-items:center;margin:0;text-align:center;text-decoration:none;border:0;border-radius:.1875rem;padding:.75rem 1.125rem;font-family:var(--font-heading-family);font-style:var(--font-heading-style);font-weight:var(--font-heading-weight);font-size:1.25rem;user-select:none;appearance:none;transition:transform .2s ease-in}button:hover,button.-primary:hover,.button:hover,.button.-primary:hover{text-decoration:none}button,button.-primary,.button,.button.-primary{background-color:rgba(var(--color-base-solid-button),1);color:rgba(var(--color-base-background-primary),1)}button.-secondary,.button.-secondary{background-color:transparent;color:rgba(var(--color-base-outline-button),1);border:1px solid rgba(var(--color-base-outline-button),1)}button.-small,.button.-small{min-width:6rem}button.-large,.button.-large{min-width:20rem}button.-loading,.button.-loading{cursor:not-allowed;opacity:.8}button:disabled,button[aria-disabled=true],.button:disabled,.button[aria-disabled=true]{cursor:not-allowed;background-color:gray}.heading,h1,h2,h3,h4,h5,h6{font-family:var(--font-heading-family);font-style:var(--font-heading-style);font-weight:var(--font-heading-weight);color:inherit;text-decoration:none}.heading h1,.heading.-h1{font-size:3.375rem;line-height:1.2}@media screen and (max-width: 750px){.heading h1,.heading.-h1{font-size:2.375rem}}.heading h2,.heading.-h2{font-size:1.625rem}@media screen and (max-width: 750px){.heading h2,.heading.-h2{font-size:1.375rem}}.heading h3,.heading.-h3{font-size:1.1875rem}.heading h4,.heading.-h4{font-size:1.0625rem}.heading.-bold{font-weight:700}.heading.-upper{text-transform:uppercase}.field{position:relative;display:flex;align-items:stretch;justify-content:center;width:100%;max-width:22em;margin:0 auto;border:1px solid rgba(var(--color-base-outline-button),1);border-radius:.1875rem}.field_label{position:absolute;left:0;top:50%;left:1rem;transform-origin:center left;transform:translateY(-50%);transition:transform .2s ease;pointer-events:none;cursor:text}.field_input{padding:.8rem 1rem .2rem;flex:1}.field_label,.field_input{font-family:var(--font-body-family);font-style:var(--font-heading-style);font-weight:var(--font-heading-weight);text-decoration:none}.field .field_input::placeholder{color:transparent}.field_input:active+.field_label,.field_input:focus+.field_label,.field_input:focus-visible+.field_label,.field_input:not(:placeholder-shown)+.field_label,.field_input:-webkit-autofill+.field_label{transform:translateY(-100%) scale(.6)}.field.-error{border-color:#f00000e6}.header{display:flex;flex-wrap:nowrap;justify-content:space-between;padding-top:1rem;padding-bottom:1rem}.header .header_logo{font-size:1.4rem}.welcome{display:grid;justify-content:center;align-items:center}.welcome .icon{width:1.5rem;height:1.5rem;margin-left:.5rem}.welcome .welcome_wrapper{width:90%;max-width:900px;margin:0 auto}.welcome .welcome_feature-wrapper{max-width:1200px;display:flex;justify-content:space-between;flex-flow:row wrap;column-gap:30px}@media screen and (max-width: 749px){.welcome .welcome_feature-wrapper{justify-content:center;row-gap:20px}}.welcome .welcome_feature{width:90%;max-width:360px}.container{width:100%;margin:0 auto}.container.-small{padding-left:.5rem;padding-right:.5rem}.container,.container.-medium{padding-left:1rem;padding-right:1rem}.container.-large{padding-left:2rem;padding-right:2rem}.container.-narrow{max-width:30rem}.grid{display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap;position:relative;list-style-type:none}[class*=col-]{position:relative;width:100%;vertical-align:top}.col-12{width:100%}.col-11{width:91.6666666667%}.col-10{width:83.3333333333%}.col-9{width:75%}.col-8{width:66.6666666667%}.col-7{width:58.3333333333%}.col-6{width:50%}.col-5{width:41.6666666667%}.col-4{width:33.3333333333%}.col-3{width:25%}.col-2{width:16.6666666667%}.col-1{width:8.3333333333%}@media screen and (min-width: 425px){.col-xs-12{width:100%}.col-xs-11{width:91.6666666667%}.col-xs-10{width:83.3333333333%}.col-xs-9{width:75%}.col-xs-8{width:66.6666666667%}.col-xs-7{width:58.3333333333%}.col-xs-6{width:50%}.col-xs-5{width:41.6666666667%}.col-xs-4{width:33.3333333333%}.col-xs-3{width:25%}.col-xs-2{width:16.6666666667%}.col-xs-1{width:8.3333333333%}}@media screen and (min-width: 750px){.col-sm-12{width:100%}.col-sm-11{width:91.6666666667%}.col-sm-10{width:83.3333333333%}.col-sm-9{width:75%}.col-sm-8{width:66.6666666667%}.col-sm-7{width:58.3333333333%}.col-sm-6{width:50%}.col-sm-5{width:41.6666666667%}.col-sm-4{width:33.3333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.6666666667%}.col-sm-1{width:8.3333333333%}}@media screen and (min-width: 1025px){.col-md-12{width:100%}.col-md-11{width:91.6666666667%}.col-md-10{width:83.3333333333%}.col-md-9{width:75%}.col-md-8{width:66.6666666667%}.col-md-7{width:58.3333333333%}.col-md-6{width:50%}.col-md-5{width:41.6666666667%}.col-md-4{width:33.3333333333%}.col-md-3{width:25%}.col-md-2{width:16.6666666667%}.col-md-1{width:8.3333333333%}}@media screen and (min-width: 1200px){.col-lg-12{width:100%}.col-lg-11{width:91.6666666667%}.col-lg-10{width:83.3333333333%}.col-lg-9{width:75%}.col-lg-8{width:66.6666666667%}.col-lg-7{width:58.3333333333%}.col-lg-6{width:50%}.col-lg-5{width:41.6666666667%}.col-lg-4{width:33.3333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.6666666667%}.col-lg-1{width:8.3333333333%}}@media screen and (min-width: 1440px){.col-xlg-12{width:100%}.col-xlg-11{width:91.6666666667%}.col-xlg-10{width:83.3333333333%}.col-xlg-9{width:75%}.col-xlg-8{width:66.6666666667%}.col-xlg-7{width:58.3333333333%}.col-xlg-6{width:50%}.col-xlg-5{width:41.6666666667%}.col-xlg-4{width:33.3333333333%}.col-xlg-3{width:25%}.col-xlg-2{width:16.6666666667%}.col-xlg-1{width:8.3333333333%}}.col-auto{-ms-flex:1 0 0px;-webkit-flex:1 0 0px;flex:1 0 0px}@media screen and (min-width: 425px){.col-xs-auto{-ms-flex:1 0 0px;-webkit-flex:1 0 0px;flex:1 0 0px}}@media screen and (min-width: 750px){.col-sm-auto{-ms-flex:1 0 0px;-webkit-flex:1 0 0px;flex:1 0 0px}}@media screen and (min-width: 1025px){.col-md-auto{-ms-flex:1 0 0px;-webkit-flex:1 0 0px;flex:1 0 0px}}@media screen and (min-width: 1200px){.col-lg-auto{-ms-flex:1 0 0px;-webkit-flex:1 0 0px;flex:1 0 0px}}@media screen and (min-width: 1440px){.col-xlg-auto{-ms-flex:1 0 0px;-webkit-flex:1 0 0px;flex:1 0 0px}}.order-12{-ms-flex-order:12;-webkit-order:12;order:12}.order-11{-ms-flex-order:11;-webkit-order:11;order:11}.order-10{-ms-flex-order:10;-webkit-order:10;order:10}.order-9{-ms-flex-order:9;-webkit-order:9;order:9}.order-8{-ms-flex-order:8;-webkit-order:8;order:8}.order-7{-ms-flex-order:7;-webkit-order:7;order:7}.order-6{-ms-flex-order:6;-webkit-order:6;order:6}.order-5{-ms-flex-order:5;-webkit-order:5;order:5}.order-4{-ms-flex-order:4;-webkit-order:4;order:4}.order-3{-ms-flex-order:3;-webkit-order:3;order:3}.order-2{-ms-flex-order:2;-webkit-order:2;order:2}.order-1{-ms-flex-order:1;-webkit-order:1;order:1}.order-0{-ms-flex-order:0;-webkit-order:0;order:0}@media screen and (min-width: 425px){.order-xs-12{-ms-flex-order:12;-webkit-order:12;order:12}.order-xs-11{-ms-flex-order:11;-webkit-order:11;order:11}.order-xs-10{-ms-flex-order:10;-webkit-order:10;order:10}.order-xs-9{-ms-flex-order:9;-webkit-order:9;order:9}.order-xs-8{-ms-flex-order:8;-webkit-order:8;order:8}.order-xs-7{-ms-flex-order:7;-webkit-order:7;order:7}.order-xs-6{-ms-flex-order:6;-webkit-order:6;order:6}.order-xs-5{-ms-flex-order:5;-webkit-order:5;order:5}.order-xs-4{-ms-flex-order:4;-webkit-order:4;order:4}.order-xs-3{-ms-flex-order:3;-webkit-order:3;order:3}.order-xs-2{-ms-flex-order:2;-webkit-order:2;order:2}.order-xs-1{-ms-flex-order:1;-webkit-order:1;order:1}.order-xs-0{-ms-flex-order:0;-webkit-order:0;order:0}}@media screen and (min-width: 750px){.order-sm-12{-ms-flex-order:12;-webkit-order:12;order:12}.order-sm-11{-ms-flex-order:11;-webkit-order:11;order:11}.order-sm-10{-ms-flex-order:10;-webkit-order:10;order:10}.order-sm-9{-ms-flex-order:9;-webkit-order:9;order:9}.order-sm-8{-ms-flex-order:8;-webkit-order:8;order:8}.order-sm-7{-ms-flex-order:7;-webkit-order:7;order:7}.order-sm-6{-ms-flex-order:6;-webkit-order:6;order:6}.order-sm-5{-ms-flex-order:5;-webkit-order:5;order:5}.order-sm-4{-ms-flex-order:4;-webkit-order:4;order:4}.order-sm-3{-ms-flex-order:3;-webkit-order:3;order:3}.order-sm-2{-ms-flex-order:2;-webkit-order:2;order:2}.order-sm-1{-ms-flex-order:1;-webkit-order:1;order:1}.order-sm-0{-ms-flex-order:0;-webkit-order:0;order:0}}@media screen and (min-width: 1025px){.order-md-12{-ms-flex-order:12;-webkit-order:12;order:12}.order-md-11{-ms-flex-order:11;-webkit-order:11;order:11}.order-md-10{-ms-flex-order:10;-webkit-order:10;order:10}.order-md-9{-ms-flex-order:9;-webkit-order:9;order:9}.order-md-8{-ms-flex-order:8;-webkit-order:8;order:8}.order-md-7{-ms-flex-order:7;-webkit-order:7;order:7}.order-md-6{-ms-flex-order:6;-webkit-order:6;order:6}.order-md-5{-ms-flex-order:5;-webkit-order:5;order:5}.order-md-4{-ms-flex-order:4;-webkit-order:4;order:4}.order-md-3{-ms-flex-order:3;-webkit-order:3;order:3}.order-md-2{-ms-flex-order:2;-webkit-order:2;order:2}.order-md-1{-ms-flex-order:1;-webkit-order:1;order:1}.order-md-0{-ms-flex-order:0;-webkit-order:0;order:0}}@media screen and (min-width: 1200px){.order-lg-12{-ms-flex-order:12;-webkit-order:12;order:12}.order-lg-11{-ms-flex-order:11;-webkit-order:11;order:11}.order-lg-10{-ms-flex-order:10;-webkit-order:10;order:10}.order-lg-9{-ms-flex-order:9;-webkit-order:9;order:9}.order-lg-8{-ms-flex-order:8;-webkit-order:8;order:8}.order-lg-7{-ms-flex-order:7;-webkit-order:7;order:7}.order-lg-6{-ms-flex-order:6;-webkit-order:6;order:6}.order-lg-5{-ms-flex-order:5;-webkit-order:5;order:5}.order-lg-4{-ms-flex-order:4;-webkit-order:4;order:4}.order-lg-3{-ms-flex-order:3;-webkit-order:3;order:3}.order-lg-2{-ms-flex-order:2;-webkit-order:2;order:2}.order-lg-1{-ms-flex-order:1;-webkit-order:1;order:1}.order-lg-0{-ms-flex-order:0;-webkit-order:0;order:0}}@media screen and (min-width: 1440px){.order-xlg-12{-ms-flex-order:12;-webkit-order:12;order:12}.order-xlg-11{-ms-flex-order:11;-webkit-order:11;order:11}.order-xlg-10{-ms-flex-order:10;-webkit-order:10;order:10}.order-xlg-9{-ms-flex-order:9;-webkit-order:9;order:9}.order-xlg-8{-ms-flex-order:8;-webkit-order:8;order:8}.order-xlg-7{-ms-flex-order:7;-webkit-order:7;order:7}.order-xlg-6{-ms-flex-order:6;-webkit-order:6;order:6}.order-xlg-5{-ms-flex-order:5;-webkit-order:5;order:5}.order-xlg-4{-ms-flex-order:4;-webkit-order:4;order:4}.order-xlg-3{-ms-flex-order:3;-webkit-order:3;order:3}.order-xlg-2{-ms-flex-order:2;-webkit-order:2;order:2}.order-xlg-1{-ms-flex-order:1;-webkit-order:1;order:1}.order-xlg-0{-ms-flex-order:0;-webkit-order:0;order:0}}.offset-11{margin-left:91.6666666667%}.offset-10{margin-left:83.3333333333%}.offset-9{margin-left:75%}.offset-8{margin-left:66.6666666667%}.offset-7{margin-left:58.3333333333%}.offset-6{margin-left:50%}.offset-5{margin-left:41.6666666667%}.offset-4{margin-left:33.3333333333%}.offset-3{margin-left:25%}.offset-2{margin-left:16.6666666667%}.offset-1{margin-left:8.3333333333%}@media screen and (min-width: 425px){.offset-xs-11{margin-left:91.6666666667%}.offset-xs-10{margin-left:83.3333333333%}.offset-xs-9{margin-left:75%}.offset-xs-8{margin-left:66.6666666667%}.offset-xs-7{margin-left:58.3333333333%}.offset-xs-6{margin-left:50%}.offset-xs-5{margin-left:41.6666666667%}.offset-xs-4{margin-left:33.3333333333%}.offset-xs-3{margin-left:25%}.offset-xs-2{margin-left:16.6666666667%}.offset-xs-1{margin-left:8.3333333333%}.offset-xs-0{margin-left:0}}@media screen and (min-width: 750px){.offset-sm-11{margin-left:91.6666666667%}.offset-sm-10{margin-left:83.3333333333%}.offset-sm-9{margin-left:75%}.offset-sm-8{margin-left:66.6666666667%}.offset-sm-7{margin-left:58.3333333333%}.offset-sm-6{margin-left:50%}.offset-sm-5{margin-left:41.6666666667%}.offset-sm-4{margin-left:33.3333333333%}.offset-sm-3{margin-left:25%}.offset-sm-2{margin-left:16.6666666667%}.offset-sm-1{margin-left:8.3333333333%}.offset-sm-0{margin-left:0}}@media screen and (min-width: 1025px){.offset-md-11{margin-left:91.6666666667%}.offset-md-10{margin-left:83.3333333333%}.offset-md-9{margin-left:75%}.offset-md-8{margin-left:66.6666666667%}.offset-md-7{margin-left:58.3333333333%}.offset-md-6{margin-left:50%}.offset-md-5{margin-left:41.6666666667%}.offset-md-4{margin-left:33.3333333333%}.offset-md-3{margin-left:25%}.offset-md-2{margin-left:16.6666666667%}.offset-md-1{margin-left:8.3333333333%}.offset-md-0{margin-left:0}}@media screen and (min-width: 1200px){.offset-lg-11{margin-left:91.6666666667%}.offset-lg-10{margin-left:83.3333333333%}.offset-lg-9{margin-left:75%}.offset-lg-8{margin-left:66.6666666667%}.offset-lg-7{margin-left:58.3333333333%}.offset-lg-6{margin-left:50%}.offset-lg-5{margin-left:41.6666666667%}.offset-lg-4{margin-left:33.3333333333%}.offset-lg-3{margin-left:25%}.offset-lg-2{margin-left:16.6666666667%}.offset-lg-1{margin-left:8.3333333333%}.offset-lg-0{margin-left:0}}@media screen and (min-width: 1440px){.offset-xlg-11{margin-left:91.6666666667%}.offset-xlg-10{margin-left:83.3333333333%}.offset-xlg-9{margin-left:75%}.offset-xlg-8{margin-left:66.6666666667%}.offset-xlg-7{margin-left:58.3333333333%}.offset-xlg-6{margin-left:50%}.offset-xlg-5{margin-left:41.6666666667%}.offset-xlg-4{margin-left:33.3333333333%}.offset-xlg-3{margin-left:25%}.offset-xlg-2{margin-left:16.6666666667%}.offset-xlg-1{margin-left:8.3333333333%}.offset-xlg-0{margin-left:0}}.wrap{-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap}.no-wrap{-ms-flex-wrap:nowrap;-webkit-flex-wrap:nowrap;flex-wrap:nowrap}.no-wrap [class*=col-]{-ms-flex-negative:1;-webkit-flex-shrink:1;flex-shrink:1}.wrap-reverse{-ms-flex-wrap:wrap-reverse;-webkit-flex-wrap:wrap-reverse;flex-wrap:wrap-reverse}.direction-row{-ms-flex-direction:row;-webkit-flex-direction:row;flex-direction:row}.direction-row-reverse{-ms-flex-direction:row-reverse;-webkit-flex-direction:row-reverse;flex-direction:row-reverse}.direction-column{-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.direction-column-reverse{-ms-flex-direction:column-reverse;-webkit-flex-direction:column-reverse;flex-direction:column-reverse}.align-start{-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start}.align-end{-ms-flex-align:end;-webkit-align-items:flex-end;align-items:flex-end}.align-center{-ms-flex-align:center;-webkit-align-items:center;align-items:center}.align-baseline{-ms-flex-align:baseline;-webkit-align-items:baseline;align-items:baseline}.align-content-start{-ms-flex-line-pack:start;-webkit-align-content:flex-start;align-content:flex-start}.align-content-end{-ms-flex-line-pack:end;-webkit-align-content:flex-end;align-content:flex-end}.align-content-end [class*=col-]{vertical-align:bottom}.align-content-center{-ms-flex-line-pack:center;-webkit-align-content:center;align-content:center}.align-content-space-between{-ms-flex-line-pack:justify;-webkit-align-content:space-between;align-content:space-between}.align-content-space-around{-ms-flex-line-pack:distribute;-webkit-align-content:space-around;align-content:space-around}.align-self-stretch{-ms-flex-item-align:stretch;-webkit-align-self:stretch;align-self:stretch}.align-self-start{-ms-flex-item-align:start;-webkit-align-self:flex-start;align-self:flex-start}.align-self-end{-ms-flex-item-align:end;-webkit-align-self:flex-end;align-self:flex-end;vertical-align:bottom}.align-self-center{-ms-flex-item-align:center;-webkit-align-self:center;align-self:center;vertical-align:middle}.align-self-baseline{-ms-flex-item-align:baseline;-webkit-align-self:baseline;align-self:baseline;vertical-align:baseline}.justify-start{-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start}.justify-end{-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end}.justify-center{-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.justify-space-between{-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between}.justify-space-around{-ms-flex-pack:distribute;-webkit-justify-content:space-around;justify-content:space-around}.grid-bleed [class*=col-]{padding:0}.col-grid{display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.col-grid.direction-row{-ms-flex-direction:row;-webkit-flex-direction:row;flex-direction:row}.flex-img{display:block;-ms-flex:0 0 auto;-webkit-flex:0 0 auto;flex:0 0 auto;max-width:100%;height:auto;width:100%}.flex-footer{width:100%;margin-top:auto;margin-bottom:0}.flex-footer>:last-child{margin-bottom:0}.u-p-small{padding:.5em!important}.u-p-medium{padding:2em!important}.u-p-large{padding:4em!important}.u-p-none{padding:0!important}.u-pt-small{padding-top:.5em!important}.u-pt-medium{padding-top:2em!important}.u-pt-large{padding-top:4em!important}.u-pt-none{padding-top:0!important}.u-pr-small{padding-right:.5em!important}.u-pr-medium{padding-right:2em!important}.u-pr-large{padding-right:4em!important}.u-pr-none{padding-right:0!important}.u-pb-small{padding-bottom:.5em!important}.u-pb-medium{padding-bottom:2em!important}.u-pb-large{padding-bottom:4em!important}.u-pb-none{padding-bottom:0!important}.u-pl-small{padding-left:.5em!important}.u-pl-medium{padding-left:2em!important}.u-pl-large{padding-left:4em!important}.u-pl-none{padding-left:0!important}.u-ph-small{padding-left:.5em!important;padding-right:.5em!important}.u-ph-medium{padding-left:2em!important;padding-right:2em!important}.u-ph-large{padding-left:4em!important;padding-right:4em!important}.u-ph-none{padding-left:0!important;padding-right:0!important}.u-pv-small{padding-top:.5em!important;padding-bottom:.5em!important}.u-pv-medium{padding-top:2em!important;padding-bottom:2em!important}.u-pv-large{padding-top:4em!important;padding-bottom:4em!important}.u-pv-none{padding-top:0!important;padding-bottom:0!important}.u-m-small{margin:.5em!important}.u-m-medium{margin:2em!important}.u-m-large{margin:4em!important}.u-m-none{margin:0!important}.u-mt-small{margin-top:.5em!important}.u-mt-medium{margin-top:2em!important}.u-mt-large{margin-top:4em!important}.u-mt-none{margin-top:0!important}.u-mr-small{margin-right:.5em!important}.u-mr-medium{margin-right:2em!important}.u-mr-large{margin-right:4em!important}.u-mr-none{margin-right:0!important}.u-mb-small{margin-bottom:.5em!important}.u-mb-medium{margin-bottom:2em!important}.u-mb-large{margin-bottom:4em!important}.u-mb-none{margin-bottom:0!important}.u-ml-small{margin-left:.5em!important}.u-ml-medium{margin-left:2em!important}.u-ml-large{margin-left:4em!important}.u-ml-none{margin-left:0!important}.u-mh-small{margin-left:.5em!important;margin-right:.5em!important}.u-mh-medium{margin-left:2em!important;margin-right:2em!important}.u-mh-large{margin-left:4em!important;margin-right:4em!important}.u-mh-none{margin-left:0!important;margin-right:0!important}.u-mv-small{margin-top:.5em!important;margin-bottom:.5em!important}.u-mv-medium{margin-top:2em!important;margin-bottom:2em!important}.u-mv-large{margin-top:4em!important;margin-bottom:4em!important}.u-mv-none{margin-top:0!important;margin-bottom:0!important}.u-hide{display:none!important}@media screen and (min-width: 0px) and (max-width: 424px){.u-hide-xxs{display:none!important}}@media screen and (min-width: 425px){.u-hide-xs-up{display:none!important}}@media screen and (max-width: 749px){.u-hide-xs-down{display:none!important}}@media screen and (min-width: 750px){.u-hide-sm-up{display:none!important}}@media screen and (max-width: 1024px){.u-hide-sm-down{display:none!important}}@media screen and (min-width: 1025px){.u-hide-md-up{display:none!important}}@media screen and (max-width: 1199px){.u-hide-md-down{display:none!important}}@media screen and (min-width: 1200px){.u-hide-lg-up{display:none!important}}@media screen and (max-width: 1439px){.u-hide-lg-down{display:none!important}}@media screen and (min-width: 1440px){.u-hide-xlg{display:none!important}}.u-hide-visually{position:absolute!important;border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0!important;width:1px;word-wrap:normal!important}.u-hide-visually-focusable{position:absolute!important;word-wrap:normal!important;border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0!important;width:1px}.u-hide-visually-focusable:focus,.u-hide-visually-focusable:active{clip:auto;width:auto;height:auto}@media (prefers-reduced-motion){.u-motion-reduce{transition:none!important}}.u-show,.u-hide-none{display:block!important;visibility:visible!important}.u-focus-none{box-shadow:none!important;outline:0!important}.u-visible{visibility:visible!important;opacity:1!important}.u-invisible{visibility:hidden!important;opacity:0!important}.u-float-left{float:left!important}.u-float-right{float:right!important}.u-align-left{text-align:left!important}.u-align-right{text-align:right!important}.u-align-center{text-align:center!important}.u-align-baseline{vertical-align:baseline!important}.u-align-bottom{vertical-align:bottom!important}.u-align-middle{vertical-align:middle!important}.u-align-top{vertical-align:top!important} 2 | --------------------------------------------------------------------------------